From dc601ec50ea82b33e38aa90f695b3b0a97d490f8 Mon Sep 17 00:00:00 2001 From: Dmitriy Nekrasov Date: Fri, 27 Mar 2026 15:01:45 +0100 Subject: [PATCH 1/3] Fix cross-platform deploy issues in Azure Copilot MicroHack - Replace $env:TEMP with [System.IO.Path]::GetTempPath() in Deploy-Lab.ps1 ($env:TEMP is null on macOS/Linux, causing script to crash) - Add --timeout 600 to az webapp deploy to prevent 504 Gateway Timeout during Oryx Python build on B1 App Service plan - Auto-install application-insights CLI extension in Test-CopilotWorkshop.ps1 to prevent interactive prompt that hangs the test suite Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../12_Azure_Copilot/lab/Deploy-Lab.ps1 | 6 +++--- .../12_Azure_Copilot/scripts/Test-CopilotWorkshop.ps1 | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/lab/Deploy-Lab.ps1 b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/lab/Deploy-Lab.ps1 index a5d8c81b..f7d81952 100644 --- a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/lab/Deploy-Lab.ps1 +++ b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/lab/Deploy-Lab.ps1 @@ -96,7 +96,7 @@ $sshPublicKey = (Get-Content $sshPubKeyPath -Raw).Trim() Write-Host "`n[1/3] Deploying infrastructure (Bicep)..." -ForegroundColor Yellow $mainBicep = Join-Path $scriptPath "..\iac\main.bicep" $timestamp = Get-Date -Format "yyyyMMddHHmmss" -$paramsFile = Join-Path $env:TEMP "copilot-workshop-params-$timestamp.json" +$paramsFile = Join-Path ([System.IO.Path]::GetTempPath()) "copilot-workshop-params-$timestamp.json" @{ '`$schema' = 'https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#' @@ -127,10 +127,10 @@ Write-Host " ✓ Infrastructure deployed" -ForegroundColor Green Write-Host "`n[2/3] Deploying buggy Flask app (Ch02)..." -ForegroundColor Yellow $webAppName = "app-copilot-buggy-$suffix" $appDir = Join-Path $scriptPath "..\app" -$zipPath = Join-Path $env:TEMP "$webAppName.zip" +$zipPath = Join-Path ([System.IO.Path]::GetTempPath()) "$webAppName.zip" if (Test-Path $zipPath) { Remove-Item $zipPath -Force } Compress-Archive -Path (Join-Path $appDir "*") -DestinationPath $zipPath -Force -Invoke-Az webapp deploy --resource-group "rg-copilot-$suffix-ch02" --name $webAppName --src-path $zipPath --type zip --track-status false -o none +Invoke-Az webapp deploy --resource-group "rg-copilot-$suffix-ch02" --name $webAppName --src-path $zipPath --type zip --track-status false --timeout 600 -o none Remove-Item $zipPath -Force Write-Host " ✓ Flask app deployed to $webAppName" -ForegroundColor Green diff --git a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/scripts/Test-CopilotWorkshop.ps1 b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/scripts/Test-CopilotWorkshop.ps1 index 2fbebda3..131bc4a1 100644 --- a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/scripts/Test-CopilotWorkshop.ps1 +++ b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/scripts/Test-CopilotWorkshop.ps1 @@ -18,6 +18,9 @@ param( $ErrorActionPreference = "Continue" Set-StrictMode -Version Latest +# Ensure required CLI extensions are installed (application-insights is needed for Ch02 tests) +az extension add --name application-insights --yes 2>$null + $passed = 0 $failed = 0 $warnings = 0 From 86e21966263ef5d4d28def5afb3d65116478ffcf Mon Sep 17 00:00:00 2001 From: Dmitriy Nekrasov Date: Tue, 7 Apr 2026 13:26:08 +0200 Subject: [PATCH 2/3] Improve cross-platform robustness, docs, and app resilience Additional improvements to the Azure Copilot MicroHack discovered via dual advanced AI agent review (GPT-5.4-pro breadth + o3-pro robustness): Deploy-Lab.ps1: - Add missing shebang (#!/usr/bin/env pwsh) for consistency - Fix Invoke-Az: use @args splatting and throw instead of exit - Replace Az PowerShell RBAC (Get/New-AzRoleAssignment) with az CLI commands for cross-platform compatibility Test-CopilotWorkshop.ps1: - Add pre-flight az login check before ConvertFrom-Json app.py: - Guard configure_azure_monitor() against missing connection string requirements.txt: - Pin upper-bound version constraints to prevent breaking changes Readme.md: - Add PowerShell 7+ (pwsh) as prerequisite - Fix LinkedIn URL in Contributors section challenges/challenge-06.md & walkthrough/solution-06.md: - Add note that AKS cluster is not deployed; Task 3 is exploratory challenges/challenge-07.md: - Add navigation link to finish.md challenges/finish.md: - Replace GitHub emoji shortcode with Unicode emoji Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../01-03-Infrastructure/12_Azure_Copilot/Readme.md | 4 +++- .../01-03-Infrastructure/12_Azure_Copilot/app/app.py | 4 +++- .../12_Azure_Copilot/app/requirements.txt | 6 +++--- .../12_Azure_Copilot/challenges/challenge-06.md | 3 +++ .../12_Azure_Copilot/challenges/challenge-07.md | 2 +- .../12_Azure_Copilot/challenges/finish.md | 2 +- .../12_Azure_Copilot/lab/Deploy-Lab.ps1 | 11 ++++++----- .../12_Azure_Copilot/scripts/Test-CopilotWorkshop.ps1 | 7 ++++++- .../12_Azure_Copilot/walkthrough/solution-06.md | 3 +++ 9 files changed, 29 insertions(+), 13 deletions(-) diff --git a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/Readme.md b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/Readme.md index fb40deee..64d33817 100644 --- a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/Readme.md +++ b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/Readme.md @@ -75,6 +75,7 @@ In order to use the MicroHack time most effectively, the following tasks should 3. **Agents (Preview) access** — Your tenant must have access to Agents (preview) in Azure Copilot. Access is managed at the tenant level and rolled out gradually. Check with your tenant administrator, or [request access](https://aka.ms/azurecopilot/agents/feedbackprogram). 4. **WebSocket connections** — Your organization must allow WebSocket connections to `https://directline.botframework.com`. Ask your network administrator to enable this if blocked. 5. [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli) installed and logged in (`az login`). **Hint:** Make sure to use the latest version available. +6. [PowerShell 7+](https://learn.microsoft.com/powershell/scripting/install/installing-powershell) (pwsh) — required for all deployment and test scripts. **Hint:** On macOS install via `brew install powershell/tap/powershell`. In summary: @@ -82,6 +83,7 @@ In summary: - Azure Copilot enabled for your tenant - Agents (Preview) enabled for your tenant - Azure CLI installed +- PowerShell 7+ (pwsh) installed - WebSocket connectivity to `directline.botframework.com` Permissions for the deployment: @@ -145,4 +147,4 @@ Running all resources for one day costs approximately **$11.50–14**. For a 2-d ## Contributors -- Dmitriy Nekrasov [GitHub](https://github.com/nekdima); [LinkedIn](https://www.linkedin.com/in/inthedark/) +- Dmitriy Nekrasov [GitHub](https://github.com/nekdima); [LinkedIn](https://www.linkedin.com/in/dmne/) diff --git a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/app/app.py b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/app/app.py index 2fb75662..ca9230a7 100644 --- a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/app/app.py +++ b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/app/app.py @@ -8,12 +8,14 @@ - / -> healthy endpoint (200 OK) - /health -> health check """ +import os import time import logging from flask import Flask, jsonify from azure.monitor.opentelemetry import configure_azure_monitor -configure_azure_monitor() +if os.environ.get("APPLICATIONINSIGHTS_CONNECTION_STRING"): + configure_azure_monitor() app = Flask(__name__) logging.basicConfig(level=logging.INFO) diff --git a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/app/requirements.txt b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/app/requirements.txt index 88af53cf..fc6080f5 100644 --- a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/app/requirements.txt +++ b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/app/requirements.txt @@ -1,3 +1,3 @@ -flask>=3.0 -gunicorn>=21.2 -azure-monitor-opentelemetry>=1.6.0 +flask>=3.0,<4.0 +gunicorn>=21.2,<23.0 +azure-monitor-opentelemetry>=1.6.0,<2.0 diff --git a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/challenges/challenge-06.md b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/challenges/challenge-06.md index 99f28e4e..5fc9411d 100644 --- a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/challenges/challenge-06.md +++ b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/challenges/challenge-06.md @@ -113,6 +113,9 @@ Simulate a Cosmos DB connection issue investigation: ### Task 3: Troubleshoot AKS Cluster Issues (10 min) +> [!NOTE] +> No AKS cluster is deployed as part of the lab. This task is exploratory — you can select an existing AKS cluster in your subscription, or simply follow the prompts to see what guidance Azure Copilot provides without a specific resource selected. + Investigate Kubernetes cluster problems: 1. Start a new conversation with agent mode enabled diff --git a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/challenges/challenge-07.md b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/challenges/challenge-07.md index 543e3cc0..80e5a2c8 100644 --- a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/challenges/challenge-07.md +++ b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/challenges/challenge-07.md @@ -1,6 +1,6 @@ # Challenge 7 - Capstone Multi-Agent Scenario -**[Home](../Readme.md)** - [Previous Challenge](challenge-06.md) +**[Home](../Readme.md)** - [Previous Challenge](challenge-06.md) - [Finish](finish.md) ## Goal diff --git a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/challenges/finish.md b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/challenges/finish.md index fefdf3e4..73702f00 100644 --- a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/challenges/finish.md +++ b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/challenges/finish.md @@ -4,7 +4,7 @@ ## Congratulations -Congratulations! :partying_face: You finished the MicroHack for Azure Copilot. +Congratulations! 🥳 You finished the MicroHack for Azure Copilot. We hope you've had the opportunity to experience Azure Copilot and its five specialized agents — Deployment, Observability, Optimization, Resiliency, and Troubleshooting. diff --git a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/lab/Deploy-Lab.ps1 b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/lab/Deploy-Lab.ps1 index f7d81952..d7f110a1 100644 --- a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/lab/Deploy-Lab.ps1 +++ b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/lab/Deploy-Lab.ps1 @@ -1,3 +1,4 @@ +#!/usr/bin/env pwsh <# .SYNOPSIS Deploys the Azure Copilot Workshop lab resources (HackboxConsole entry-point). @@ -50,10 +51,9 @@ $Location = if ([string]::IsNullOrEmpty($PreferredLocation)) { "francecentral" } # Helper # ────────────────────────────────────────────── function Invoke-Az { - & az $args + & az @args if ($LASTEXITCODE -ne 0) { - Write-Error "Azure CLI command failed with exit code $LASTEXITCODE" - exit $LASTEXITCODE + throw "Azure CLI command failed with exit code $LASTEXITCODE" } } @@ -154,9 +154,10 @@ if ($DeploymentType -in @('resourcegroup','resourcegroup-with-subscriptionowner' if ($AllowedEntraUserIds.Count -gt 0) { foreach ($userId in $AllowedEntraUserIds) { $scope = "/subscriptions/$SubscriptionId/resourceGroups/$rg" - if (-not (Get-AzRoleAssignment -ObjectId $userId -RoleDefinitionName "Owner" -Scope $scope -ErrorAction SilentlyContinue)) { + $existing = az role assignment list --assignee $userId --role "Owner" --scope $scope -o json 2>$null | ConvertFrom-Json + if (-not $existing -or $existing.Count -eq 0) { Write-Host "Assigning Owner role to $userId on $rg" - New-AzRoleAssignment -ObjectId $userId -RoleDefinitionName "Owner" -Scope $scope -ErrorAction Stop | Out-Null + Invoke-Az role assignment create --assignee $userId --role "Owner" --scope $scope -o none } } } diff --git a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/scripts/Test-CopilotWorkshop.ps1 b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/scripts/Test-CopilotWorkshop.ps1 index 131bc4a1..f2b401b5 100644 --- a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/scripts/Test-CopilotWorkshop.ps1 +++ b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/scripts/Test-CopilotWorkshop.ps1 @@ -54,7 +54,12 @@ Write-Host "`n========================================" -ForegroundColor Cyan Write-Host " Azure Copilot Workshop - Test Suite" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan -$account = az account show -o json 2>&1 | ConvertFrom-Json +$accountJson = az account show -o json 2>&1 +if ($LASTEXITCODE -ne 0) { + Write-Host "ERROR: Not logged in to Azure CLI. Run 'az login' first." -ForegroundColor Red + exit 1 +} +$account = $accountJson | ConvertFrom-Json Write-Host "Subscription: $($account.name)`n" -ForegroundColor Green # ────────────────────────────────────────────── diff --git a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/walkthrough/solution-06.md b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/walkthrough/solution-06.md index 210e397e..a003ec54 100644 --- a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/walkthrough/solution-06.md +++ b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/walkthrough/solution-06.md @@ -142,6 +142,9 @@ Even when the agent can't directly access a resource (e.g., testing from your lo ## Task 3: Troubleshoot AKS Cluster Issues +> [!NOTE] +> No AKS cluster is deployed as part of the lab. The expected responses below are illustrative examples. Your actual output will vary depending on whether you select an existing AKS cluster or follow the prompts without one. + ### Steps **Prompt 1:** _"Investigate the health of my pods."_ From c8b7573493e1bd30c395bc1438b72a218ebc1d79 Mon Sep 17 00:00:00 2001 From: Dmitriy Nekrasov Date: Tue, 7 Apr 2026 14:07:51 +0200 Subject: [PATCH 3/3] Strip UTF-8 BOM from scripts/requirements, fix gunicorn pin, consistent error handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove UTF-8 BOM (ef bb bf) from Test-CopilotWorkshop.ps1, Send-CopilotTraffic.ps1, Remove-CopilotWorkshop.ps1, and requirements.txt — BOM before shebang prevents direct execution on Linux/macOS (kernel reads 0xEF not 0x23) - Widen gunicorn pin from <23.0 to <26.0 to include current stable - Replace Write-Error+exit with throw in ssh-keygen check (consistent with Invoke-Az fix from prior commit) Found via iterative GPT-5.4-pro red-team/counter-argue/verdict review. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../12_Azure_Copilot/app/requirements.txt | 4 ++-- .../01-03-Infrastructure/12_Azure_Copilot/lab/Deploy-Lab.ps1 | 3 +-- .../12_Azure_Copilot/scripts/Remove-CopilotWorkshop.ps1 | 2 +- .../12_Azure_Copilot/scripts/Send-CopilotTraffic.ps1 | 2 +- .../12_Azure_Copilot/scripts/Test-CopilotWorkshop.ps1 | 2 +- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/app/requirements.txt b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/app/requirements.txt index fc6080f5..c7e89326 100644 --- a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/app/requirements.txt +++ b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/app/requirements.txt @@ -1,3 +1,3 @@ -flask>=3.0,<4.0 -gunicorn>=21.2,<23.0 +flask>=3.0,<4.0 +gunicorn>=21.2,<26.0 azure-monitor-opentelemetry>=1.6.0,<2.0 diff --git a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/lab/Deploy-Lab.ps1 b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/lab/Deploy-Lab.ps1 index d7f110a1..979b65b9 100644 --- a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/lab/Deploy-Lab.ps1 +++ b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/lab/Deploy-Lab.ps1 @@ -84,8 +84,7 @@ if (-not (Test-Path $sshPubKeyPath)) { $sshKeyPath = Join-Path $HOME ".ssh" "id_rsa" ssh-keygen -t rsa -b 4096 -f $sshKeyPath -q -N "" if ($LASTEXITCODE -ne 0) { - Write-Error "Failed to generate SSH key pair." - exit 1 + throw "Failed to generate SSH key pair. ssh-keygen exited with code $LASTEXITCODE" } } $sshPublicKey = (Get-Content $sshPubKeyPath -Raw).Trim() diff --git a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/scripts/Remove-CopilotWorkshop.ps1 b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/scripts/Remove-CopilotWorkshop.ps1 index f77bdb21..8d6a4b16 100644 --- a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/scripts/Remove-CopilotWorkshop.ps1 +++ b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/scripts/Remove-CopilotWorkshop.ps1 @@ -1,4 +1,4 @@ -#!/usr/bin/env pwsh +#!/usr/bin/env pwsh <# .SYNOPSIS Tears down all Azure resources created for the Azure Copilot Workshop. diff --git a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/scripts/Send-CopilotTraffic.ps1 b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/scripts/Send-CopilotTraffic.ps1 index d45253b3..bfc7d6ad 100644 --- a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/scripts/Send-CopilotTraffic.ps1 +++ b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/scripts/Send-CopilotTraffic.ps1 @@ -1,4 +1,4 @@ -#!/usr/bin/env pwsh +#!/usr/bin/env pwsh <# .SYNOPSIS Generates error traffic against the Ch02 buggy app to trigger alerts. diff --git a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/scripts/Test-CopilotWorkshop.ps1 b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/scripts/Test-CopilotWorkshop.ps1 index f2b401b5..49a4ca39 100644 --- a/03-Azure/01-03-Infrastructure/12_Azure_Copilot/scripts/Test-CopilotWorkshop.ps1 +++ b/03-Azure/01-03-Infrastructure/12_Azure_Copilot/scripts/Test-CopilotWorkshop.ps1 @@ -1,4 +1,4 @@ -#!/usr/bin/env pwsh +#!/usr/bin/env pwsh <# .SYNOPSIS Tests all deployed Azure resources for the Copilot Workshop.