From 53fdaf918a5f87d75314cf6085b069de2e69f7f7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 12:17:08 -0600 Subject: [PATCH 01/13] Add Azure DevOps CI investigation guidelines with az CLI preference - Add .github/instructions/azdo-ci.instructions.md: teaches Copilot to always prefer az CLI for ADO queries, check availability first, and prompt user to install/login if missing. Falls back to anonymous REST for dnceng-public with a noted limitation. - Update .github/copilot-instructions.md: add Azure DevOps CI Access section under Development Environment Setup, marking az as strongly recommended with install/setup steps. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/copilot-instructions.md | 9 ++ .github/instructions/azdo-ci.instructions.md | 125 +++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 .github/instructions/azdo-ci.instructions.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index b8f6e9a890a0..81efad4cef87 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -40,6 +40,15 @@ This guidance assumes: - **iOS/macOS**: Xcode (current stable version) - **Windows**: Windows SDK +### Azure DevOps CI Access + +- **Azure CLI (`az`)** — **strongly recommended** for investigating CI builds, test failures, and pipeline status + - Install: `brew install azure-cli` (macOS) / `winget install Microsoft.AzureCLI` (Windows) + - Setup: `az login && az extension add --name azure-devops` + - Defaults: `az devops configure --defaults organization=https://dev.azure.com/dnceng-public project=public` + - **Always prefer `az` over raw `curl`/`Invoke-RestMethod`** when querying Azure DevOps APIs + - See `.github/instructions/azdo-ci.instructions.md` for detailed CI investigation guidance + ## Project Structure ### Important Directories diff --git a/.github/instructions/azdo-ci.instructions.md b/.github/instructions/azdo-ci.instructions.md new file mode 100644 index 000000000000..cf7e5fe5e42f --- /dev/null +++ b/.github/instructions/azdo-ci.instructions.md @@ -0,0 +1,125 @@ +--- +applyTo: "**" +--- + +# Azure DevOps CI Investigation Guidelines + +When investigating CI builds, test failures, pipeline status, or any Azure DevOps (ADO) data for this repository, **always prefer the `az` CLI** over raw REST API calls (`curl`, `Invoke-RestMethod`, etc.). + +## Why `az` CLI? + +The `az` CLI with the `azure-devops` extension provides: +- **Authenticated access** — handles tokens automatically, no manual header management +- **Richer data** — access to build logs, artifacts, test results, and timeline details that may be restricted for anonymous callers +- **Structured output** — native `--output json/table/tsv` formatting +- **Pagination** — automatic handling of large result sets +- **Rate limit resilience** — authenticated requests have much higher rate limits than anonymous + +## Required: Check `az` CLI Availability First + +**Before making ANY Azure DevOps API call**, check if `az` is installed and authenticated: + +```bash +# Check if az is installed and logged in +az account show 2>/dev/null && az extension show --name azure-devops 2>/dev/null +``` + +### If `az` is NOT installed or NOT logged in + +**STOP and tell the user:** + +``` +⚠️ The Azure CLI (az) is not installed/authenticated. CI investigation is much more +reliable with az CLI. To set up: + + 1. Install: brew install azure-cli (macOS) + winget install Microsoft.AzureCLI (Windows) + + 2. Login: az login + + 3. Extension: az extension add --name azure-devops + + 4. Defaults: `az devops configure --defaults organization=https://dev.azure.com/dnceng-public project=public` + +Once set up, I can provide much richer CI analysis. +``` + +Then proceed with anonymous access as a fallback, but **always mention the limitation**. + +## Common `az` Commands for CI Investigation + +### Get builds for a PR +```bash +# List builds triggered by a PR +az pipelines runs list --org https://dev.azure.com/dnceng-public --project public --query "[?triggerInfo.\"pr.number\"=='PR_NUMBER']" --output table + +# Or use the pr-build-status skill scripts (which use gh CLI): +pwsh .github/skills/pr-build-status/scripts/Get-PrBuildIds.ps1 -PrNumber PR_NUMBER +``` + +### Get build details and timeline +```bash +# Build summary +az pipelines runs show --id BUILD_ID --org https://dev.azure.com/dnceng-public --project public + +# Build timeline (Critical for finding WHICH step failed) +# This returns a large JSON. Filter to failed records to avoid token limits: +az devops invoke --area build --resource timeline --route-parameters buildId=BUILD_ID project=public --org https://dev.azure.com/dnceng-public --query "records[?result=='failed']" --output table +``` + +### Get build logs +```bash +# 1. Find the logId from the timeline (look for 'log' object in failed records) +# 2. Download/Show the log: +az devops invoke --area build --resource logs --route-parameters buildId=BUILD_ID logId=LOG_ID project=public --org https://dev.azure.com/dnceng-public --output json +``` + +### Get build artifacts (binlogs) +Artifacts often contain `.binlog` files which are critical for build failures. + +```bash +# List artifacts +az pipelines runs artifact list --run-id BUILD_ID --org https://dev.azure.com/dnceng-public --project public --output table + +# Download specific artifact (e.g., 'binlog') +az pipelines runs artifact download --run-id BUILD_ID --artifact-name "binlog" --path . --org https://dev.azure.com/dnceng-public --project public +``` + +### Get test results +```bash +# List test runs for a build +az devops invoke --area test --resource runs --query-parameters buildUri=vstfs:///Build/Build/BUILD_ID --org https://dev.azure.com/dnceng-public --project public --output json + +# Get test results from a run +az devops invoke --area test --resource results --route-parameters runId=RUN_ID project=public --org https://dev.azure.com/dnceng-public --query-parameters "top=100" "outcomes=Failed" --output json +``` + +## Fallback: Anonymous REST API + +Only use direct REST API calls if `az` CLI is unavailable: + +```bash +# Anonymous (works for dnceng-public only, subject to rate limits) +curl -s "https://dev.azure.com/dnceng-public/public/_apis/build/builds/BUILD_ID?api-version=7.0" +``` + +**Always note in your response** that results may be limited without `az` authentication. + +## Use Existing Skills When Appropriate + +The repository has a `pr-build-status` skill with purpose-built scripts: +- `Get-PrBuildIds.ps1` — maps PR number to ADO build IDs (uses `gh` CLI) +- `Get-BuildInfo.ps1` — build status, stages, failed jobs +- `Get-BuildErrors.ps1` — build errors and test failures +- `Get-HelixLogs.ps1` — Helix console logs for device/integration test failures + +**Use these scripts for structured queries.** Use `az` CLI directly for ad-hoc or deeper investigation. + +## ADO Organization Reference + +| Organization | Project | Access | Use | +|---|---|---|---| +| `dnceng-public` | `public` | Anonymous (with limits) | Open-source CI builds | +| `dnceng` | `internal` | **Auth required** | Internal builds (requires org membership) | + +For `dnceng/internal` builds, `az` CLI authentication is **mandatory** — anonymous access will always fail. From 431a2a3530d28c80f453d312727e0447524bba48 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 14:25:31 -0600 Subject: [PATCH 02/13] Simplify az CLI guidance: drop instruction file, keep copilot-instructions note The separate instruction file had two problems: - applyTo: "**" loaded 125 lines of CI content into every context (C# code, XAML, etc.) - No applyTo value matches conversational CI questions without an open file Replace with a concise note in copilot-instructions.md (always loaded), pointing to pr-build-status scripts for structured queries. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/copilot-instructions.md | 4 +- .github/instructions/azdo-ci.instructions.md | 125 ------------------- 2 files changed, 2 insertions(+), 127 deletions(-) delete mode 100644 .github/instructions/azdo-ci.instructions.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 81efad4cef87..38e8d61152bb 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -46,8 +46,8 @@ This guidance assumes: - Install: `brew install azure-cli` (macOS) / `winget install Microsoft.AzureCLI` (Windows) - Setup: `az login && az extension add --name azure-devops` - Defaults: `az devops configure --defaults organization=https://dev.azure.com/dnceng-public project=public` - - **Always prefer `az` over raw `curl`/`Invoke-RestMethod`** when querying Azure DevOps APIs - - See `.github/instructions/azdo-ci.instructions.md` for detailed CI investigation guidance + - **Prefer `az` over raw `curl`/`Invoke-RestMethod`** when querying Azure DevOps APIs + - For structured CI queries, use the `pr-build-status` skill scripts in `.github/skills/pr-build-status/` ## Project Structure diff --git a/.github/instructions/azdo-ci.instructions.md b/.github/instructions/azdo-ci.instructions.md deleted file mode 100644 index cf7e5fe5e42f..000000000000 --- a/.github/instructions/azdo-ci.instructions.md +++ /dev/null @@ -1,125 +0,0 @@ ---- -applyTo: "**" ---- - -# Azure DevOps CI Investigation Guidelines - -When investigating CI builds, test failures, pipeline status, or any Azure DevOps (ADO) data for this repository, **always prefer the `az` CLI** over raw REST API calls (`curl`, `Invoke-RestMethod`, etc.). - -## Why `az` CLI? - -The `az` CLI with the `azure-devops` extension provides: -- **Authenticated access** — handles tokens automatically, no manual header management -- **Richer data** — access to build logs, artifacts, test results, and timeline details that may be restricted for anonymous callers -- **Structured output** — native `--output json/table/tsv` formatting -- **Pagination** — automatic handling of large result sets -- **Rate limit resilience** — authenticated requests have much higher rate limits than anonymous - -## Required: Check `az` CLI Availability First - -**Before making ANY Azure DevOps API call**, check if `az` is installed and authenticated: - -```bash -# Check if az is installed and logged in -az account show 2>/dev/null && az extension show --name azure-devops 2>/dev/null -``` - -### If `az` is NOT installed or NOT logged in - -**STOP and tell the user:** - -``` -⚠️ The Azure CLI (az) is not installed/authenticated. CI investigation is much more -reliable with az CLI. To set up: - - 1. Install: brew install azure-cli (macOS) - winget install Microsoft.AzureCLI (Windows) - - 2. Login: az login - - 3. Extension: az extension add --name azure-devops - - 4. Defaults: `az devops configure --defaults organization=https://dev.azure.com/dnceng-public project=public` - -Once set up, I can provide much richer CI analysis. -``` - -Then proceed with anonymous access as a fallback, but **always mention the limitation**. - -## Common `az` Commands for CI Investigation - -### Get builds for a PR -```bash -# List builds triggered by a PR -az pipelines runs list --org https://dev.azure.com/dnceng-public --project public --query "[?triggerInfo.\"pr.number\"=='PR_NUMBER']" --output table - -# Or use the pr-build-status skill scripts (which use gh CLI): -pwsh .github/skills/pr-build-status/scripts/Get-PrBuildIds.ps1 -PrNumber PR_NUMBER -``` - -### Get build details and timeline -```bash -# Build summary -az pipelines runs show --id BUILD_ID --org https://dev.azure.com/dnceng-public --project public - -# Build timeline (Critical for finding WHICH step failed) -# This returns a large JSON. Filter to failed records to avoid token limits: -az devops invoke --area build --resource timeline --route-parameters buildId=BUILD_ID project=public --org https://dev.azure.com/dnceng-public --query "records[?result=='failed']" --output table -``` - -### Get build logs -```bash -# 1. Find the logId from the timeline (look for 'log' object in failed records) -# 2. Download/Show the log: -az devops invoke --area build --resource logs --route-parameters buildId=BUILD_ID logId=LOG_ID project=public --org https://dev.azure.com/dnceng-public --output json -``` - -### Get build artifacts (binlogs) -Artifacts often contain `.binlog` files which are critical for build failures. - -```bash -# List artifacts -az pipelines runs artifact list --run-id BUILD_ID --org https://dev.azure.com/dnceng-public --project public --output table - -# Download specific artifact (e.g., 'binlog') -az pipelines runs artifact download --run-id BUILD_ID --artifact-name "binlog" --path . --org https://dev.azure.com/dnceng-public --project public -``` - -### Get test results -```bash -# List test runs for a build -az devops invoke --area test --resource runs --query-parameters buildUri=vstfs:///Build/Build/BUILD_ID --org https://dev.azure.com/dnceng-public --project public --output json - -# Get test results from a run -az devops invoke --area test --resource results --route-parameters runId=RUN_ID project=public --org https://dev.azure.com/dnceng-public --query-parameters "top=100" "outcomes=Failed" --output json -``` - -## Fallback: Anonymous REST API - -Only use direct REST API calls if `az` CLI is unavailable: - -```bash -# Anonymous (works for dnceng-public only, subject to rate limits) -curl -s "https://dev.azure.com/dnceng-public/public/_apis/build/builds/BUILD_ID?api-version=7.0" -``` - -**Always note in your response** that results may be limited without `az` authentication. - -## Use Existing Skills When Appropriate - -The repository has a `pr-build-status` skill with purpose-built scripts: -- `Get-PrBuildIds.ps1` — maps PR number to ADO build IDs (uses `gh` CLI) -- `Get-BuildInfo.ps1` — build status, stages, failed jobs -- `Get-BuildErrors.ps1` — build errors and test failures -- `Get-HelixLogs.ps1` — Helix console logs for device/integration test failures - -**Use these scripts for structured queries.** Use `az` CLI directly for ad-hoc or deeper investigation. - -## ADO Organization Reference - -| Organization | Project | Access | Use | -|---|---|---|---| -| `dnceng-public` | `public` | Anonymous (with limits) | Open-source CI builds | -| `dnceng` | `internal` | **Auth required** | Internal builds (requires org membership) | - -For `dnceng/internal` builds, `az` CLI authentication is **mandatory** — anonymous access will always fail. From 7902a610c4cb0f39929089f88e11644d842ea110 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 14:55:41 -0600 Subject: [PATCH 03/13] Improve pr-build-status skill: zero-build triage, binlogtool, better triggers - Get-PrBuildIds.ps1: diagnose when CI was never triggered (path filters, draft PR, not queued) instead of silently returning empty output. Only returns rows with valid BuildIds to downstream scripts. - SKILL.md: add binlog analysis workflow (binlogtool) for MSBuild/XamlC/ NuGet failures where text logs say 'Build FAILED' with no detail. - SKILL.md: expand trigger phrases ('why is CI red', 'build failed', etc.) so the skill surfaces for more natural CI investigation questions. - SKILL.md: add 'stop if tool missing' policy and 'focus on first error' rule. Update description and version to 1.2. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/skills/pr-build-status/SKILL.md | 42 +++++++++++++++++-- .../scripts/Get-PrBuildIds.ps1 | 21 +++++++++- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/.github/skills/pr-build-status/SKILL.md b/.github/skills/pr-build-status/SKILL.md index c4a542b8b9a3..1c97100f79c3 100644 --- a/.github/skills/pr-build-status/SKILL.md +++ b/.github/skills/pr-build-status/SKILL.md @@ -1,28 +1,37 @@ --- name: pr-build-status -description: "Retrieve Azure DevOps build information for GitHub Pull Requests, including build IDs, stage status, failed jobs, and Helix console logs for any Helix-based test failures." +description: "Investigate CI failures for dotnet/maui PRs — build errors, Helix test logs, and binlog analysis. Use when asked about failing checks, CI status, test failures, 'why is CI red', 'build failed', 'what's failing on PR', Helix failures, or device test failures." metadata: author: dotnet-maui - version: "1.1" + version: "1.2" compatibility: Requires GitHub CLI (gh) authenticated with access to dotnet/maui repository. --- # PR Build Status Skill -Retrieve Azure DevOps build information for GitHub Pull Requests, including Helix test logs. +Investigate CI failures for dotnet/maui PRs — build errors, Helix test logs, and binlog analysis. ## Tools Required This skill uses `bash` together with `pwsh` (PowerShell 7+) to run the PowerShell scripts. No file editing or other tools are required. +**If `gh` or `pwsh` is missing: stop immediately and tell the user to install the missing tool. Do NOT attempt to install it yourself.** + +- `gh`: https://cli.github.com/ +- `pwsh`: https://aka.ms/install-powershell + +Optional for binlog analysis (MSBuild failures): +- `binlogtool`: `dotnet tool install -g binlogtool` (https://www.nuget.org/packages/binlogtool) + ## When to Use - User asks about CI/CD status for a PR - User asks about failed checks or builds -- User asks "what's failing on PR #XXXXX" +- User asks "what's failing on PR #XXXXX" / "why is CI red" / "build failed" - User wants to see test results - **User asks about Helix failures (device tests, integration tests, etc.)** - **User needs to debug why tests are failing on Helix infrastructure** +- **Text logs say "Build FAILED" with no detail — use binlog analysis** ## Scripts @@ -69,10 +78,14 @@ pwsh .github/skills/pr-build-status/scripts/Get-HelixLogs.ps1 -BuildId **Focus on the first error chronologically — later errors usually cascade from the root cause.** + ### Standard Build Failures 1. Get build IDs: `Get-PrBuildIds.ps1 -PrNumber XXXXX` + - If output shows ⚠️ with no build IDs, CI was not triggered — read the diagnostic message 2. For each build, get status: `Get-BuildInfo.ps1 -BuildId YYYYY -FailedOnly` 3. For failed builds, get errors: `Get-BuildErrors.ps1 -BuildId YYYYY` +4. If errors say "Build FAILED" with no detail, check for binlog artifacts (see below) ### Helix Test Failures 1. Get build IDs: `Get-PrBuildIds.ps1 -PrNumber XXXXX` @@ -80,6 +93,27 @@ pwsh .github/skills/pr-build-status/scripts/Get-HelixLogs.ps1 -BuildId Date: Wed, 4 Mar 2026 15:11:02 -0600 Subject: [PATCH 04/13] =?UTF-8?q?Rename=20skill:=20pr-build-status=20?= =?UTF-8?q?=E2=86=92=20azdo-build-investigator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Align with dotnet/android's naming convention for CI investigation skills. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/README-AI.md | 4 ++-- .github/copilot-instructions.md | 4 ++-- .../SKILL.md | 24 +++++++++---------- .../scripts/Get-BuildErrors.ps1 | 0 .../scripts/Get-BuildInfo.ps1 | 0 .../scripts/Get-HelixLogs.ps1 | 0 .../scripts/Get-PrBuildIds.ps1 | 0 .github/skills/pr-finalize/SKILL.md | 2 +- 8 files changed, 17 insertions(+), 17 deletions(-) rename .github/skills/{pr-build-status => azdo-build-investigator}/SKILL.md (81%) rename .github/skills/{pr-build-status => azdo-build-investigator}/scripts/Get-BuildErrors.ps1 (100%) rename .github/skills/{pr-build-status => azdo-build-investigator}/scripts/Get-BuildInfo.ps1 (100%) rename .github/skills/{pr-build-status => azdo-build-investigator}/scripts/Get-HelixLogs.ps1 (100%) rename .github/skills/{pr-build-status => azdo-build-investigator}/scripts/Get-PrBuildIds.ps1 (100%) diff --git a/.github/README-AI.md b/.github/README-AI.md index c703358dfade..4472fd913d75 100644 --- a/.github/README-AI.md +++ b/.github/README-AI.md @@ -250,7 +250,7 @@ Reusable skills in `.github/skills/` that agents can invoke: - **`verify-tests-fail-without-fix/`** - Verifies UI tests catch bugs (auto-detects mode based on git diff) - **`write-ui-tests/`** - Creates UI tests for issues following MAUI conventions - **`write-xaml-tests/`** - Creates XAML unit tests for parsing, XamlC, and source generation issues -- **`pr-build-status/`** - Retrieves Azure DevOps build status for PRs +- **`azdo-build-investigator/`** - Retrieves Azure DevOps build status for PRs ### Recent Improvements (January 2026) @@ -365,7 +365,7 @@ For issues or questions about the AI agent instructions: **Agent Files**: - 4 agent files (pr.md, pr/post-gate.md, sandbox-agent.md, write-tests-agent.md) -- 5 skills (try-fix, verify-tests-fail-without-fix, write-ui-tests, write-xaml-tests, pr-build-status) +- 5 skills (try-fix, verify-tests-fail-without-fix, write-ui-tests, write-xaml-tests, azdo-build-investigator) - All validated and consistent with consolidated structure **Automation**: diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 38e8d61152bb..1009f1ada927 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -47,7 +47,7 @@ This guidance assumes: - Setup: `az login && az extension add --name azure-devops` - Defaults: `az devops configure --defaults organization=https://dev.azure.com/dnceng-public project=public` - **Prefer `az` over raw `curl`/`Invoke-RestMethod`** when querying Azure DevOps APIs - - For structured CI queries, use the `pr-build-status` skill scripts in `.github/skills/pr-build-status/` + - For structured CI queries, use the `azdo-build-investigator` skill scripts in `.github/skills/azdo-build-investigator/` ## Project Structure @@ -294,7 +294,7 @@ Skills are modular capabilities that can be invoked directly or used by agents. - **Two modes**: Verify failure only (test creation) or full verification (test + fix) - **Used by**: After creating tests, before considering PR complete -8. **pr-build-status** (`.github/skills/pr-build-status/SKILL.md`) +8. **azdo-build-investigator** (`.github/skills/azdo-build-investigator/SKILL.md`) - **Purpose**: Retrieves Azure DevOps build information for PRs (build IDs, stage status, failed jobs) - **Trigger phrases**: "check build for PR #XXXXX", "why did PR build fail", "get build status" - **Used by**: When investigating CI failures diff --git a/.github/skills/pr-build-status/SKILL.md b/.github/skills/azdo-build-investigator/SKILL.md similarity index 81% rename from .github/skills/pr-build-status/SKILL.md rename to .github/skills/azdo-build-investigator/SKILL.md index 1c97100f79c3..a979f6eb3b9e 100644 --- a/.github/skills/pr-build-status/SKILL.md +++ b/.github/skills/azdo-build-investigator/SKILL.md @@ -1,5 +1,5 @@ --- -name: pr-build-status +name: azdo-build-investigator description: "Investigate CI failures for dotnet/maui PRs — build errors, Helix test logs, and binlog analysis. Use when asked about failing checks, CI status, test failures, 'why is CI red', 'build failed', 'what's failing on PR', Helix failures, or device test failures." metadata: author: dotnet-maui @@ -35,45 +35,45 @@ Optional for binlog analysis (MSBuild failures): ## Scripts -All scripts are in `.github/skills/pr-build-status/scripts/` +All scripts are in `.github/skills/azdo-build-investigator/scripts/` ### 1. Get Build IDs for a PR ```bash -pwsh .github/skills/pr-build-status/scripts/Get-PrBuildIds.ps1 -PrNumber +pwsh .github/skills/azdo-build-investigator/scripts/Get-PrBuildIds.ps1 -PrNumber ``` ### 2. Get Build Status ```bash -pwsh .github/skills/pr-build-status/scripts/Get-BuildInfo.ps1 -BuildId +pwsh .github/skills/azdo-build-investigator/scripts/Get-BuildInfo.ps1 -BuildId # For failed jobs only: -pwsh .github/skills/pr-build-status/scripts/Get-BuildInfo.ps1 -BuildId -FailedOnly +pwsh .github/skills/azdo-build-investigator/scripts/Get-BuildInfo.ps1 -BuildId -FailedOnly ``` ### 3. Get Build Errors and Test Failures ```bash # Get all errors (build errors + test failures) -pwsh .github/skills/pr-build-status/scripts/Get-BuildErrors.ps1 -BuildId +pwsh .github/skills/azdo-build-investigator/scripts/Get-BuildErrors.ps1 -BuildId # Get only build/compilation errors -pwsh .github/skills/pr-build-status/scripts/Get-BuildErrors.ps1 -BuildId -ErrorsOnly +pwsh .github/skills/azdo-build-investigator/scripts/Get-BuildErrors.ps1 -BuildId -ErrorsOnly # Get only test failures -pwsh .github/skills/pr-build-status/scripts/Get-BuildErrors.ps1 -BuildId -TestsOnly +pwsh .github/skills/azdo-build-investigator/scripts/Get-BuildErrors.ps1 -BuildId -TestsOnly ``` ### 4. Get Helix Console Logs ```bash # List all Helix work items and their status -pwsh .github/skills/pr-build-status/scripts/Get-HelixLogs.ps1 -BuildId +pwsh .github/skills/azdo-build-investigator/scripts/Get-HelixLogs.ps1 -BuildId # Filter by platform -pwsh .github/skills/pr-build-status/scripts/Get-HelixLogs.ps1 -BuildId -Platform Windows +pwsh .github/skills/azdo-build-investigator/scripts/Get-HelixLogs.ps1 -BuildId -Platform Windows # Show console log content for failed work items -pwsh .github/skills/pr-build-status/scripts/Get-HelixLogs.ps1 -BuildId -ShowConsoleLog +pwsh .github/skills/azdo-build-investigator/scripts/Get-HelixLogs.ps1 -BuildId -ShowConsoleLog # Filter by work item name and show more log lines -pwsh .github/skills/pr-build-status/scripts/Get-HelixLogs.ps1 -BuildId -WorkItem "*Lifecycle*" -ShowConsoleLog -TailLines 200 +pwsh .github/skills/azdo-build-investigator/scripts/Get-HelixLogs.ps1 -BuildId -WorkItem "*Lifecycle*" -ShowConsoleLog -TailLines 200 ``` ## Workflow diff --git a/.github/skills/pr-build-status/scripts/Get-BuildErrors.ps1 b/.github/skills/azdo-build-investigator/scripts/Get-BuildErrors.ps1 similarity index 100% rename from .github/skills/pr-build-status/scripts/Get-BuildErrors.ps1 rename to .github/skills/azdo-build-investigator/scripts/Get-BuildErrors.ps1 diff --git a/.github/skills/pr-build-status/scripts/Get-BuildInfo.ps1 b/.github/skills/azdo-build-investigator/scripts/Get-BuildInfo.ps1 similarity index 100% rename from .github/skills/pr-build-status/scripts/Get-BuildInfo.ps1 rename to .github/skills/azdo-build-investigator/scripts/Get-BuildInfo.ps1 diff --git a/.github/skills/pr-build-status/scripts/Get-HelixLogs.ps1 b/.github/skills/azdo-build-investigator/scripts/Get-HelixLogs.ps1 similarity index 100% rename from .github/skills/pr-build-status/scripts/Get-HelixLogs.ps1 rename to .github/skills/azdo-build-investigator/scripts/Get-HelixLogs.ps1 diff --git a/.github/skills/pr-build-status/scripts/Get-PrBuildIds.ps1 b/.github/skills/azdo-build-investigator/scripts/Get-PrBuildIds.ps1 similarity index 100% rename from .github/skills/pr-build-status/scripts/Get-PrBuildIds.ps1 rename to .github/skills/azdo-build-investigator/scripts/Get-PrBuildIds.ps1 diff --git a/.github/skills/pr-finalize/SKILL.md b/.github/skills/pr-finalize/SKILL.md index c1c8af7144de..4d0584906a5b 100644 --- a/.github/skills/pr-finalize/SKILL.md +++ b/.github/skills/pr-finalize/SKILL.md @@ -1,6 +1,6 @@ --- name: pr-finalize -description: Finalizes any PR for merge by verifying title/description match implementation AND performing code review for best practices. Use when asked to "finalize PR", "check PR description", "review commit message", before merging any PR, or when PR implementation changed during review. Do NOT use for extracting lessons (use learn-from-pr), writing tests (use write-tests-agent), or investigating build failures (use pr-build-status). +description: Finalizes any PR for merge by verifying title/description match implementation AND performing code review for best practices. Use when asked to "finalize PR", "check PR description", "review commit message", before merging any PR, or when PR implementation changed during review. Do NOT use for extracting lessons (use learn-from-pr), writing tests (use write-tests-agent), or investigating build failures (use azdo-build-investigator). --- # PR Finalize From 0ca160e10cb5964f0adc84d5e30e36ea50eeb705 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 15:16:52 -0600 Subject: [PATCH 05/13] Clarify az login is optional for dnceng-public (public org) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/copilot-instructions.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 1009f1ada927..108ee8903508 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -45,6 +45,7 @@ This guidance assumes: - **Azure CLI (`az`)** — **strongly recommended** for investigating CI builds, test failures, and pipeline status - Install: `brew install azure-cli` (macOS) / `winget install Microsoft.AzureCLI` (Windows) - Setup: `az login && az extension add --name azure-devops` + - Note: `dnceng-public` is publicly accessible — `az login` is optional for MAUI CI queries - Defaults: `az devops configure --defaults organization=https://dev.azure.com/dnceng-public project=public` - **Prefer `az` over raw `curl`/`Invoke-RestMethod`** when querying Azure DevOps APIs - For structured CI queries, use the `azdo-build-investigator` skill scripts in `.github/skills/azdo-build-investigator/` From 28c7f7b6dd73fcff09140bfba94bcb8a464c3b24 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 15:23:45 -0600 Subject: [PATCH 06/13] Minimize token usage in copilot-instructions.md (~51% reduction) Preserve all behavioral rules; cut prose, redundant examples, verbose descriptions, and bash code blocks that don't add instructional value. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/copilot-instructions.md | 310 +++++++++----------------------- 1 file changed, 81 insertions(+), 229 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 108ee8903508..e0ddd0ad47b8 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -4,113 +4,78 @@ description: "Guidance for GitHub Copilot when working on the .NET MAUI reposito # GitHub Copilot Development Environment Instructions -This document provides specific guidance for GitHub Copilot when working on the .NET MAUI repository. It serves as context for understanding the project structure, development workflow, and best practices. - ## Code Review Instructions -When performing a code review on PRs that change functional code, run the pr-finalize skill to verify that the PR title and description accurately match the actual implementation. This ensures proper documentation and helps maintain high-quality commit messages. +When performing a code review on PRs that change functional code, run the pr-finalize skill to verify that the PR title and description accurately match the actual implementation. ## Repository Overview -**.NET MAUI** is a cross-platform framework for creating mobile and desktop applications with C# and XAML. This repository contains the core framework code that enables development for Android, iOS, iPadOS, macOS, and Windows from a single shared codebase. +**.NET MAUI** is a cross-platform framework (Android, iOS, macOS, Windows) built with C# and XAML. ### Key Technologies -- **.NET SDK** - Version is **ALWAYS** defined in `global.json` at repository root - - **main branch**: Latest stable .NET version - - **net10.0 branch**: .NET 10 SDK - - **Feature branches**: Each feature branch (e.g., `net11.0`, `net12.0`) correlates to its respective .NET version -- **Cake build system** for compilation and packaging (`dotnet cake`) -- **MSBuild** with custom build tasks (must build `Microsoft.Maui.BuildTasks.slnf` first) -- **Testing frameworks**: - - **xUnit** - Unit tests (`*.UnitTests.csproj`) - - **NUnit** - UI tests (`TestCases.Shared.Tests`) - - **Appium WebDriver** - UI test automation +- **.NET SDK** — version always defined in `global.json`; each branch (`main`, `net10.0`, `net11.0`) maps to its .NET version +- **Cake build system** (`dotnet cake`); MSBuild build tasks (`Microsoft.Maui.BuildTasks.slnf` must be built first) +- **Testing**: xUnit (unit tests), NUnit (UI tests, `TestCases.Shared.Tests`), Appium WebDriver (UI automation) ## Development Environment Setup -This guidance assumes: -- Repository is already cloned and tools are restored (`dotnet tool restore` completed) -- Build tasks are compiled (`Microsoft.Maui.BuildTasks.slnf` built successfully) -- Correct .NET SDK version installed (verify with `dotnet --version` against `global.json`) - -### Platform-Specific Requirements +Assumes: tools restored (`dotnet tool restore`), build tasks compiled, correct SDK installed. -- **Android**: OpenJDK 17 + Android SDK (install via `android` command after `dotnet tool restore`) -- **iOS/macOS**: Xcode (current stable version) +- **Android**: OpenJDK 17 + Android SDK (`android` command after tool restore) +- **iOS/macOS**: Xcode (current stable) - **Windows**: Windows SDK ### Azure DevOps CI Access -- **Azure CLI (`az`)** — **strongly recommended** for investigating CI builds, test failures, and pipeline status +- **Azure CLI (`az`)** — preferred over `curl`/`Invoke-RestMethod` for CI queries - Install: `brew install azure-cli` (macOS) / `winget install Microsoft.AzureCLI` (Windows) - - Setup: `az login && az extension add --name azure-devops` - - Note: `dnceng-public` is publicly accessible — `az login` is optional for MAUI CI queries + - Setup: `az extension add --name azure-devops` (`az login` optional — `dnceng-public` is publicly accessible) - Defaults: `az devops configure --defaults organization=https://dev.azure.com/dnceng-public project=public` - - **Prefer `az` over raw `curl`/`Invoke-RestMethod`** when querying Azure DevOps APIs - For structured CI queries, use the `azdo-build-investigator` skill scripts in `.github/skills/azdo-build-investigator/` ## Project Structure -### Important Directories -- `src/Core/` - Core MAUI framework code -- `src/Controls/` - UI controls and components -- `src/Essentials/` - Platform APIs and essentials -- `src/TestUtils/` - Testing utilities and infrastructure -- `docs/` - Development documentation -- `eng/` - Build engineering and tooling -- `.github/` - GitHub workflows and configuration - -### Platform-Specific Code Organization -- **Android** specific code is inside folders labeled `Android` -- **iOS** specific code is inside folders labeled `iOS` -- **MacCatalyst** specific code is inside folders named `MacCatalyst` -- **Windows** specific code is inside folders named `Windows` +- `src/Core/` — core framework; `src/Controls/` — UI controls; `src/Essentials/` — platform APIs +- `src/TestUtils/` — test utilities; `docs/` — docs; `eng/` — build tooling; `.github/` — workflows -### Platform-Specific File Extensions +### Platform-Specific Code -Platform-specific files use naming conventions to control compilation: +Platform folders: `Android/`, `iOS/`, `MacCatalyst/`, `Windows/` -**File extension patterns**: -- `.windows.cs` - Windows TFM only -- `.android.cs` - Android TFM only -- `.ios.cs` - iOS and MacCatalyst TFMs (both) -- `.maccatalyst.cs` - MacCatalyst TFM only (does NOT compile for iOS) +File extensions: +- `.windows.cs` — Windows only; `.android.cs` — Android only +- `.ios.cs` — iOS **and** MacCatalyst; `.maccatalyst.cs` — MacCatalyst only (not iOS) -**Important**: Both `.ios.cs` and `.maccatalyst.cs` files compile for MacCatalyst. There is no precedence mechanism that excludes one when the other exists. - -**Example**: If you have both `CollectionView.ios.cs` and `CollectionView.maccatalyst.cs`, both will compile for MacCatalyst builds. The `.maccatalyst.cs` file won't compile for iOS, but the `.ios.cs` file will compile for both iOS and MacCatalyst. +⚠️ Both `.ios.cs` and `.maccatalyst.cs` compile for MacCatalyst — no precedence or exclusion between them. ### Sample Projects -- `src/Controls/samples/Maui.Controls.Sample` - Full gallery sample with all controls and features -- `src/Controls/samples/Maui.Controls.Sample.Sandbox` - Empty project for testing/reproduction -- `src/Essentials/samples/Essentials.Sample` - Essentials API demonstrations (non-UI MAUI APIs) -- `src/BlazorWebView/samples/` - BlazorWebView sample applications +- `src/Controls/samples/Maui.Controls.Sample` — full gallery +- `src/Controls/samples/Maui.Controls.Sample.Sandbox` — empty sandbox for testing/reproduction +- `src/Essentials/samples/Essentials.Sample` — Essentials API demos +- `src/BlazorWebView/samples/` — BlazorWebView samples ## Development Workflow ### Testing -Major test projects: -- **Core**: `src/Core/tests/UnitTests/Core.UnitTests.csproj` -- **Essentials**: `src/Essentials/test/UnitTests/Essentials.UnitTests.csproj` -- **Controls**: `src/Controls/tests/Core.UnitTests/Controls.Core.UnitTests.csproj` -- **XAML**: `src/Controls/tests/Xaml.UnitTests/Controls.Xaml.UnitTests.csproj` +- `src/Core/tests/UnitTests/Core.UnitTests.csproj` +- `src/Essentials/test/UnitTests/Essentials.UnitTests.csproj` +- `src/Controls/tests/Core.UnitTests/Controls.Core.UnitTests.csproj` +- `src/Controls/tests/Xaml.UnitTests/Controls.Xaml.UnitTests.csproj` -Find all tests: `find . -name "*.UnitTests.csproj"` +Find all: `find . -name "*.UnitTests.csproj"` ### CI Pipelines (Azure DevOps) -When referencing or triggering CI pipelines, use these current pipeline names: - | Pipeline | Name | Purpose | |----------|------|---------| | Overall CI | `maui-pr` | Full PR validation build | | Device Tests | `maui-pr-devicetests` | Helix-based device tests | | UI Tests | `maui-pr-uitests` | Appium-based UI tests | -**⚠️ Old pipeline names** (e.g., `MAUI-UITests-public`, `MAUI-public`) are **outdated** and should NOT be used. Always use the names above. +⚠️ Old names (`MAUI-UITests-public`, `MAUI-public`) are outdated — do not use. ### Code Formatting @@ -124,80 +89,48 @@ dotnet format Microsoft.Maui.sln --no-restore --exclude Templates/src --exclude- ### Handling Existing PRs for Assigned Issues -**🚨 CRITICAL REQUIREMENT: Always develop your own solution first, then compare with existing PRs.** +**🚨 Always develop your own solution first, then compare with existing PRs.** -1. **Develop your own solution first** - Analyze the issue independently and design your approach without looking at existing PRs -2. **Search for existing PRs** - After developing your solution, search for open PRs addressing the same issue -3. **Compare and evaluate** - Examine existing PR approaches and decide which solution better addresses the issue -4. **Document your decision** - In your PR description, compare your solution to existing PRs and explain why you chose your approach, including concerns with alternatives -5. **Improve either solution** - Whether using your solution or an existing one, enhance with better tests, code quality, error handling, or documentation +1. Develop your solution independently without looking at existing PRs +2. Search for existing PRs addressing the same issue +3. Compare approaches; choose the better solution +4. In PR description, explain your choice vs. alternatives +5. Enhance whichever solution you use (tests, quality, error handling, docs) ### Auto-Generated Files (Never Commit) -These files are auto-generated and must NOT be committed: -- `cgmanifest.json` - Generated during CI builds -- `templatestrings.json` - Auto-generated localization +- `cgmanifest.json` — generated during CI builds +- `templatestrings.json` — auto-generated localization -**For AI agents:** Always reset changes to these files before committing. +Always reset these files before committing. ### PublicAPI.Unshipped.txt File Management -When working with public API changes: -- **Never disable analyzers** to bypass PublicAPI.Unshipped.txt issues -- **Always add correct API entries** to PublicAPI.Unshipped.txt files -- **Use `dotnet format analyzers`** if having trouble -- **If files are incorrect**: Revert all changes, then add only the necessary new API entries +- Never disable analyzers to bypass issues +- Always add correct API entries; use `dotnet format analyzers` if needed +- If incorrect: revert all changes, then re-add only necessary entries ### Branching -- `main` - For bug fixes without API changes -- `net10.0` - For new features and API changes +- `main` — bug fixes without API changes +- `net10.0` — new features and API changes ### Git Workflow (Copilot CLI Rules) -**🚨 CRITICAL Git Rules for Copilot CLI:** - -1. **NEVER commit directly to `main`** - Always create a feature branch for your work. Direct commits to `main` are strictly prohibited. - -2. **When amending an existing PR, work on the PR's branch directly** - Do NOT create a separate branch off a PR branch. The PR branch already IS a feature branch. Creating a new branch off it means CI won't run on the original PR, defeating the purpose. Use `gh pr checkout` to switch to the PR branch, make your changes, commit, **then** ask before pushing so the user can review locally first. - -3. **Do NOT rebase, squash, or force-push** unless explicitly requested by the user. These operations rewrite git history and can cause problems for other contributors. Default behavior should be regular commits and pushes. - -**Safe Git Workflow:** -```bash -# Create a feature branch (NEVER work directly on main) -git checkout -b feature/issue-12345 - -# Make commits normally -git add . -git commit -m "Fix: Description of the change" - -# Push to remote (for new branches) -git push -u origin feature/issue-12345 +**🚨 Critical rules:** -# For subsequent pushes on the same branch -git push -``` - -**When asked to update an existing PR:** -```bash -# Check out the PR branch directly (do NOT create a new branch off it) -gh pr checkout 12345 +1. **Never commit directly to `main`** — always use a feature branch +2. **When amending a PR, check out its branch directly** (`gh pr checkout 12345`) — do NOT create a new branch off it; CI only runs on the original PR branch +3. **No rebase, squash, or force-push** unless explicitly requested -# Make fixes and commit to the PR branch -git add . -git commit -m "Fix: Description of the change" -``` -1. **STOP and ask the user** before pushing: "Changes are committed locally. Would you like me to push these changes to the PR?" -2. Exception: If the user's instructions explicitly include pushing, proceed without asking. +**Before pushing:** Always stop and ask the user first — unless their instructions explicitly include pushing. ### Documentation - Update XML documentation for public APIs -- Follow existing code documentation patterns -- Update relevant docs in `docs/` folder when needed +- Update `docs/` when relevant ### Opening PRs -All PRs are required to have this at the top of the description: +All PRs must include this at the top of the description (without surrounding block quotes): ``` @@ -206,125 +139,44 @@ All PRs are required to have this at the top of the description: > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ``` -Always put that at the top, without the block quotes. Without it, users will NOT be able to try the PR and your work will have been in vain! - - - ## Custom Agents and Skills -The repository includes specialized custom agents and reusable skills for specific tasks. - ### Skills vs Agents | Aspect | Skills | Agents | |--------|--------|--------| -| **Invoke** | `/skill-name` or direct request | Delegate to agent | -| **Output** | Analysis, recommendations | Actions, changes applied | -| **Interaction** | Interactive discussion | Autonomous workflow | -| **Example** | `/learn-from-pr` → recommendations | learn-from-pr agent → applies changes | +| Invoke | `/skill-name` or direct request | Delegate to agent | +| Output | Analysis, recommendations | Actions applied | +| Interaction | Interactive | Autonomous workflow | ### Available Custom Agents -1. **pr** - Sequential 4-phase workflow for reviewing and working on PRs - - **Use when**: A PR already exists and needs review or work, OR an issue needs a fix - - **Capabilities**: PR review, test verification, fix exploration, alternative comparison - - **Trigger phrases**: "review PR #XXXXX", "work on PR #XXXXX", "fix issue #XXXXX", "continue PR #XXXXX" - - **Do NOT use for**: Just running tests manually → Use `sandbox-agent` - -2. **write-tests-agent** - Agent for writing tests. Determines test type (UI vs XAML) and invokes the appropriate skill (`write-ui-tests`, `write-xaml-tests`) - - **Use when**: Creating new tests for issues or PRs - - **Capabilities**: Test type determination (UI and XAML), skill invocation, test verification - - **Trigger phrases**: "write tests for #XXXXX", "create tests", "add test coverage" - -3. **sandbox-agent** - Specialized agent for working with the Sandbox app for testing, validation, and experimentation - - **Use when**: User wants to manually test PR functionality or reproduce issues - - **Capabilities**: Sandbox app setup, Appium-based manual testing, PR functional validation - - **Trigger phrases**: "test this PR", "validate PR #XXXXX in Sandbox", "reproduce issue #XXXXX", "try out in Sandbox" - - **Do NOT use for**: Code review (use pr agent), writing automated tests (use write-tests-agent) - -4. **learn-from-pr** - Extracts lessons from PRs and applies improvements to the repository - - **Use when**: After complex PR, want to improve instruction files/skills based on lessons learned - - **Capabilities**: Analyzes PR, identifies failure modes, applies improvements to instruction files, skills, code comments - - **Trigger phrases**: "learn from PR #XXXXX and apply improvements", "improve repo based on what we learned", "update skills based on PR" - - **Output**: Applied changes to instruction files, skills, architecture docs, code comments - - **Do NOT use for**: Analysis only without applying changes → Use `/learn-from-pr` skill instead - -### Reusable Skills - -Skills are modular capabilities that can be invoked directly or used by agents. Located in `.github/skills/`: - -#### User-Facing Skills - -1. **issue-triage** (`.github/skills/issue-triage/SKILL.md`) - - **Purpose**: Query and triage open issues that need milestones, labels, or investigation - - **Trigger phrases**: "find issues to triage", "show me old Android issues", "what issues need attention" - - **Scripts**: `init-triage-session.ps1`, `query-issues.ps1`, `record-triage.ps1` - -2. **find-reviewable-pr** (`.github/skills/find-reviewable-pr/SKILL.md`) - - **Purpose**: Finds open PRs in dotnet/maui and dotnet/docs-maui that need review - - **Trigger phrases**: "find PRs to review", "show milestoned PRs", "find partner PRs" - - **Scripts**: `query-reviewable-prs.ps1` - - **Categories**: P/0, milestoned, partner, community, recent, docs-maui - -3. **pr-finalize** (`.github/skills/pr-finalize/SKILL.md`) - - **Purpose**: Verifies PR title and description match actual implementation, AND performs code review for best practices before merge. - - **Trigger phrases**: "finalize PR #XXXXX", "check PR description for #XXXXX", "review commit message" - - **Used by**: Before merging any PR, when description may be stale - - **Note**: Works on any PR - - **🚨 CRITICAL**: NEVER use `--approve` or `--request-changes` - only post comments. Approval is a human decision. - -4. **learn-from-pr** (`.github/skills/learn-from-pr/SKILL.md`) - - **Purpose**: Analyzes completed PR to identify repository improvements (analysis only, no changes applied) - - **Trigger phrases**: "what can we learn from PR #XXXXX?", "how can we improve agents based on PR #XXXXX?" - - **Used by**: After complex PRs, when agent struggled to find solution - - **Output**: Prioritized recommendations for instruction files, skills, code comments - - **Note**: For applying changes automatically, use the learn-from-pr agent instead - -5. **write-ui-tests** (`.github/skills/write-ui-tests/SKILL.md`) - - **Purpose**: Creates UI tests for GitHub issues and verifies they reproduce the bug - - **Trigger phrases**: "write UI tests for #XXXXX", "create UI test for issue", "add UI test coverage" - - **Output**: Test files that fail without fix, pass with fix - -6. **write-xaml-tests** (`.github/skills/write-xaml-tests/SKILL.md`) - - **Purpose**: Creates XAML unit tests for XAML parsing, compilation, and source generation - - **Trigger phrases**: "write XAML tests for #XXXXX", "test XamlC behavior", "reproduce XAML parsing bug" - - **Output**: Test files for Controls.Xaml.UnitTests - -7. **verify-tests-fail-without-fix** (`.github/skills/verify-tests-fail-without-fix/SKILL.md`) - - **Purpose**: Verifies UI tests catch the bug before fix and pass with fix - - **Two modes**: Verify failure only (test creation) or full verification (test + fix) - - **Used by**: After creating tests, before considering PR complete - -8. **azdo-build-investigator** (`.github/skills/azdo-build-investigator/SKILL.md`) - - **Purpose**: Retrieves Azure DevOps build information for PRs (build IDs, stage status, failed jobs) - - **Trigger phrases**: "check build for PR #XXXXX", "why did PR build fail", "get build status" - - **Used by**: When investigating CI failures - -8. **run-integration-tests** (`.github/skills/run-integration-tests/SKILL.md`) - - **Purpose**: Build, pack, and run .NET MAUI integration tests locally - - **Trigger phrases**: "run integration tests", "test templates locally", "run macOSTemplates tests", "run RunOniOS tests" - - **Categories**: Build, WindowsTemplates, macOSTemplates, Blazor, MultiProject, Samples, AOT, RunOnAndroid, RunOniOS - - **Note**: **ALWAYS use this skill** instead of manual `dotnet test` commands for integration tests - -#### Internal Skills (Used by Agents) - -9. **try-fix** (`.github/skills/try-fix/SKILL.md`) - - **Purpose**: Proposes ONE independent fix approach, applies it, tests, records result with failure analysis, then reverts - - **Used by**: pr agent Phase 3 (Fix phase) - rarely invoked directly by users - - **Behavior**: Reads prior attempts to learn from failures. Max 5 attempts per session. - - **Output**: Reports attempt results and failure analysis - -### Using Custom Agents - -**Delegation Policy**: When user request matches agent trigger phrases, **ALWAYS delegate to the appropriate agent immediately**. Do not ask for permission or explain alternatives unless the request is ambiguous. - -**Examples of correct delegation**: -- User: "Review PR #12345" → Immediately invoke **pr** agent -- User: "Test this PR" → Immediately invoke **sandbox-agent** -- User: "Fix issue #67890" (no PR exists) → Suggest using `/delegate` command -- User: "Write tests for issue #12345" → Immediately invoke **write-tests-agent** - -**When NOT to delegate**: -- User asks "What does PR #12345 do?" → Informational query, handle yourself -- User asks "How do I test PRs?" → Documentation query, handle yourself -- User has follow-up questions after agent completes → Continue the conversation yourself \ No newline at end of file +1. **pr** — PR review/fix workflow. Triggers: "review PR #XXXXX", "work on PR #XXXXX", "fix issue #XXXXX", "continue PR #XXXXX". Do NOT use for manual testing → use `sandbox-agent`. +2. **write-tests-agent** — Writes UI/XAML tests. Triggers: "write tests for #XXXXX", "create tests", "add test coverage". +3. **sandbox-agent** — Manual testing in Sandbox app. Triggers: "test this PR", "validate PR #XXXXX in Sandbox", "reproduce issue #XXXXX". Do NOT use for code review → use `pr` agent. +4. **learn-from-pr** — Extracts lessons and applies repo improvements. Triggers: "learn from PR #XXXXX and apply improvements", "update skills based on PR". For analysis only (no changes) → use `/learn-from-pr` skill instead. + +### Reusable Skills (`.github/skills/`) + +| Skill | Purpose | Trigger phrases | +|-------|---------|----------------| +| **issue-triage** | Triage open issues needing milestones/labels | "find issues to triage", "what issues need attention" | +| **find-reviewable-pr** | Find PRs needing review | "find PRs to review", "find partner PRs" | +| **pr-finalize** | Verify PR title/description match implementation; code review before merge. ⚠️ NEVER `--approve`/`--request-changes` | "finalize PR", "check PR description", "review commit message" | +| **learn-from-pr** | Analyze completed PR for repo improvements (analysis only, no changes) | "what can we learn from PR #XXXXX?" | +| **write-ui-tests** | Create UI tests that reproduce a bug | "write UI tests for #XXXXX", "add UI test coverage" | +| **write-xaml-tests** | Create XAML unit tests (parsing, XamlC, source gen) | "write XAML tests for #XXXXX", "test XamlC behavior" | +| **verify-tests-fail-without-fix** | Verify tests catch the bug before fix | After creating tests, before PR is complete | +| **azdo-build-investigator** | Investigate CI failures: build errors, Helix logs, binlog analysis | "check build for PR", "why did PR build fail", "get build status" | +| **run-integration-tests** | Run integration tests locally. **ALWAYS use instead of `dotnet test`** | "run integration tests", "run macOSTemplates tests", "run RunOniOS tests" | +| **try-fix** *(internal)* | One independent fix attempt; used by pr agent Phase 3. Max 5 attempts/session. | — | + +### Delegation Policy + +When a request matches agent trigger phrases, **immediately delegate — no permission needed.** + +- "Review PR #12345" → **pr** agent +- "Test this PR" → **sandbox-agent** +- "Fix issue #67890" (no PR exists) → suggest `/delegate` command +- "Write tests for #12345" → **write-tests-agent** +- Informational queries ("What does PR #12345 do?") → handle yourself \ No newline at end of file From 78d5ef2bc61ff047cd1824a7919a5f6448b5b80d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 16:28:23 -0600 Subject: [PATCH 07/13] Revert broad token reduction; keep only minimal az section changes Restore copilot-instructions.md to original content, keeping only the Azure DevOps CI Access section with minimal wording, skill rename, and az login clarification for dnceng-public. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/copilot-instructions.md | 304 +++++++++++++++++++++++--------- 1 file changed, 225 insertions(+), 79 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index e0ddd0ad47b8..588867757d8b 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -4,26 +4,40 @@ description: "Guidance for GitHub Copilot when working on the .NET MAUI reposito # GitHub Copilot Development Environment Instructions +This document provides specific guidance for GitHub Copilot when working on the .NET MAUI repository. It serves as context for understanding the project structure, development workflow, and best practices. + ## Code Review Instructions -When performing a code review on PRs that change functional code, run the pr-finalize skill to verify that the PR title and description accurately match the actual implementation. +When performing a code review on PRs that change functional code, run the pr-finalize skill to verify that the PR title and description accurately match the actual implementation. This ensures proper documentation and helps maintain high-quality commit messages. ## Repository Overview -**.NET MAUI** is a cross-platform framework (Android, iOS, macOS, Windows) built with C# and XAML. +**.NET MAUI** is a cross-platform framework for creating mobile and desktop applications with C# and XAML. This repository contains the core framework code that enables development for Android, iOS, iPadOS, macOS, and Windows from a single shared codebase. ### Key Technologies -- **.NET SDK** — version always defined in `global.json`; each branch (`main`, `net10.0`, `net11.0`) maps to its .NET version -- **Cake build system** (`dotnet cake`); MSBuild build tasks (`Microsoft.Maui.BuildTasks.slnf` must be built first) -- **Testing**: xUnit (unit tests), NUnit (UI tests, `TestCases.Shared.Tests`), Appium WebDriver (UI automation) +- **.NET SDK** - Version is **ALWAYS** defined in `global.json` at repository root + - **main branch**: Latest stable .NET version + - **net10.0 branch**: .NET 10 SDK + - **Feature branches**: Each feature branch (e.g., `net11.0`, `net12.0`) correlates to its respective .NET version +- **Cake build system** for compilation and packaging (`dotnet cake`) +- **MSBuild** with custom build tasks (must build `Microsoft.Maui.BuildTasks.slnf` first) +- **Testing frameworks**: + - **xUnit** - Unit tests (`*.UnitTests.csproj`) + - **NUnit** - UI tests (`TestCases.Shared.Tests`) + - **Appium WebDriver** - UI test automation ## Development Environment Setup -Assumes: tools restored (`dotnet tool restore`), build tasks compiled, correct SDK installed. +This guidance assumes: +- Repository is already cloned and tools are restored (`dotnet tool restore` completed) +- Build tasks are compiled (`Microsoft.Maui.BuildTasks.slnf` built successfully) +- Correct .NET SDK version installed (verify with `dotnet --version` against `global.json`) + +### Platform-Specific Requirements -- **Android**: OpenJDK 17 + Android SDK (`android` command after tool restore) -- **iOS/macOS**: Xcode (current stable) +- **Android**: OpenJDK 17 + Android SDK (install via `android` command after `dotnet tool restore`) +- **iOS/macOS**: Xcode (current stable version) - **Windows**: Windows SDK ### Azure DevOps CI Access @@ -36,46 +50,65 @@ Assumes: tools restored (`dotnet tool restore`), build tasks compiled, correct S ## Project Structure -- `src/Core/` — core framework; `src/Controls/` — UI controls; `src/Essentials/` — platform APIs -- `src/TestUtils/` — test utilities; `docs/` — docs; `eng/` — build tooling; `.github/` — workflows +### Important Directories +- `src/Core/` - Core MAUI framework code +- `src/Controls/` - UI controls and components +- `src/Essentials/` - Platform APIs and essentials +- `src/TestUtils/` - Testing utilities and infrastructure +- `docs/` - Development documentation +- `eng/` - Build engineering and tooling +- `.github/` - GitHub workflows and configuration + +### Platform-Specific Code Organization +- **Android** specific code is inside folders labeled `Android` +- **iOS** specific code is inside folders labeled `iOS` +- **MacCatalyst** specific code is inside folders named `MacCatalyst` +- **Windows** specific code is inside folders named `Windows` -### Platform-Specific Code +### Platform-Specific File Extensions -Platform folders: `Android/`, `iOS/`, `MacCatalyst/`, `Windows/` +Platform-specific files use naming conventions to control compilation: -File extensions: -- `.windows.cs` — Windows only; `.android.cs` — Android only -- `.ios.cs` — iOS **and** MacCatalyst; `.maccatalyst.cs` — MacCatalyst only (not iOS) +**File extension patterns**: +- `.windows.cs` - Windows TFM only +- `.android.cs` - Android TFM only +- `.ios.cs` - iOS and MacCatalyst TFMs (both) +- `.maccatalyst.cs` - MacCatalyst TFM only (does NOT compile for iOS) -⚠️ Both `.ios.cs` and `.maccatalyst.cs` compile for MacCatalyst — no precedence or exclusion between them. +**Important**: Both `.ios.cs` and `.maccatalyst.cs` files compile for MacCatalyst. There is no precedence mechanism that excludes one when the other exists. + +**Example**: If you have both `CollectionView.ios.cs` and `CollectionView.maccatalyst.cs`, both will compile for MacCatalyst builds. The `.maccatalyst.cs` file won't compile for iOS, but the `.ios.cs` file will compile for both iOS and MacCatalyst. ### Sample Projects -- `src/Controls/samples/Maui.Controls.Sample` — full gallery -- `src/Controls/samples/Maui.Controls.Sample.Sandbox` — empty sandbox for testing/reproduction -- `src/Essentials/samples/Essentials.Sample` — Essentials API demos -- `src/BlazorWebView/samples/` — BlazorWebView samples +- `src/Controls/samples/Maui.Controls.Sample` - Full gallery sample with all controls and features +- `src/Controls/samples/Maui.Controls.Sample.Sandbox` - Empty project for testing/reproduction +- `src/Essentials/samples/Essentials.Sample` - Essentials API demonstrations (non-UI MAUI APIs) +- `src/BlazorWebView/samples/` - BlazorWebView sample applications ## Development Workflow ### Testing -- `src/Core/tests/UnitTests/Core.UnitTests.csproj` -- `src/Essentials/test/UnitTests/Essentials.UnitTests.csproj` -- `src/Controls/tests/Core.UnitTests/Controls.Core.UnitTests.csproj` -- `src/Controls/tests/Xaml.UnitTests/Controls.Xaml.UnitTests.csproj` +Major test projects: +- **Core**: `src/Core/tests/UnitTests/Core.UnitTests.csproj` +- **Essentials**: `src/Essentials/test/UnitTests/Essentials.UnitTests.csproj` +- **Controls**: `src/Controls/tests/Core.UnitTests/Controls.Core.UnitTests.csproj` +- **XAML**: `src/Controls/tests/Xaml.UnitTests/Controls.Xaml.UnitTests.csproj` -Find all: `find . -name "*.UnitTests.csproj"` +Find all tests: `find . -name "*.UnitTests.csproj"` ### CI Pipelines (Azure DevOps) +When referencing or triggering CI pipelines, use these current pipeline names: + | Pipeline | Name | Purpose | |----------|------|---------| | Overall CI | `maui-pr` | Full PR validation build | | Device Tests | `maui-pr-devicetests` | Helix-based device tests | | UI Tests | `maui-pr-uitests` | Appium-based UI tests | -⚠️ Old names (`MAUI-UITests-public`, `MAUI-public`) are outdated — do not use. +**⚠️ Old pipeline names** (e.g., `MAUI-UITests-public`, `MAUI-public`) are **outdated** and should NOT be used. Always use the names above. ### Code Formatting @@ -89,48 +122,80 @@ dotnet format Microsoft.Maui.sln --no-restore --exclude Templates/src --exclude- ### Handling Existing PRs for Assigned Issues -**🚨 Always develop your own solution first, then compare with existing PRs.** +**🚨 CRITICAL REQUIREMENT: Always develop your own solution first, then compare with existing PRs.** -1. Develop your solution independently without looking at existing PRs -2. Search for existing PRs addressing the same issue -3. Compare approaches; choose the better solution -4. In PR description, explain your choice vs. alternatives -5. Enhance whichever solution you use (tests, quality, error handling, docs) +1. **Develop your own solution first** - Analyze the issue independently and design your approach without looking at existing PRs +2. **Search for existing PRs** - After developing your solution, search for open PRs addressing the same issue +3. **Compare and evaluate** - Examine existing PR approaches and decide which solution better addresses the issue +4. **Document your decision** - In your PR description, compare your solution to existing PRs and explain why you chose your approach, including concerns with alternatives +5. **Improve either solution** - Whether using your solution or an existing one, enhance with better tests, code quality, error handling, or documentation ### Auto-Generated Files (Never Commit) -- `cgmanifest.json` — generated during CI builds -- `templatestrings.json` — auto-generated localization +These files are auto-generated and must NOT be committed: +- `cgmanifest.json` - Generated during CI builds +- `templatestrings.json` - Auto-generated localization -Always reset these files before committing. +**For AI agents:** Always reset changes to these files before committing. ### PublicAPI.Unshipped.txt File Management -- Never disable analyzers to bypass issues -- Always add correct API entries; use `dotnet format analyzers` if needed -- If incorrect: revert all changes, then re-add only necessary entries +When working with public API changes: +- **Never disable analyzers** to bypass PublicAPI.Unshipped.txt issues +- **Always add correct API entries** to PublicAPI.Unshipped.txt files +- **Use `dotnet format analyzers`** if having trouble +- **If files are incorrect**: Revert all changes, then add only the necessary new API entries ### Branching -- `main` — bug fixes without API changes -- `net10.0` — new features and API changes +- `main` - For bug fixes without API changes +- `net10.0` - For new features and API changes ### Git Workflow (Copilot CLI Rules) -**🚨 Critical rules:** +**🚨 CRITICAL Git Rules for Copilot CLI:** + +1. **NEVER commit directly to `main`** - Always create a feature branch for your work. Direct commits to `main` are strictly prohibited. + +2. **When amending an existing PR, work on the PR's branch directly** - Do NOT create a separate branch off a PR branch. The PR branch already IS a feature branch. Creating a new branch off it means CI won't run on the original PR, defeating the purpose. Use `gh pr checkout` to switch to the PR branch, make your changes, commit, **then** ask before pushing so the user can review locally first. + +3. **Do NOT rebase, squash, or force-push** unless explicitly requested by the user. These operations rewrite git history and can cause problems for other contributors. Default behavior should be regular commits and pushes. + +**Safe Git Workflow:** +```bash +# Create a feature branch (NEVER work directly on main) +git checkout -b feature/issue-12345 + +# Make commits normally +git add . +git commit -m "Fix: Description of the change" + +# Push to remote (for new branches) +git push -u origin feature/issue-12345 -1. **Never commit directly to `main`** — always use a feature branch -2. **When amending a PR, check out its branch directly** (`gh pr checkout 12345`) — do NOT create a new branch off it; CI only runs on the original PR branch -3. **No rebase, squash, or force-push** unless explicitly requested +# For subsequent pushes on the same branch +git push +``` + +**When asked to update an existing PR:** +```bash +# Check out the PR branch directly (do NOT create a new branch off it) +gh pr checkout 12345 -**Before pushing:** Always stop and ask the user first — unless their instructions explicitly include pushing. +# Make fixes and commit to the PR branch +git add . +git commit -m "Fix: Description of the change" +``` +1. **STOP and ask the user** before pushing: "Changes are committed locally. Would you like me to push these changes to the PR?" +2. Exception: If the user's instructions explicitly include pushing, proceed without asking. ### Documentation - Update XML documentation for public APIs -- Update `docs/` when relevant +- Follow existing code documentation patterns +- Update relevant docs in `docs/` folder when needed ### Opening PRs -All PRs must include this at the top of the description (without surrounding block quotes): +All PRs are required to have this at the top of the description: ``` @@ -139,44 +204,125 @@ All PRs must include this at the top of the description (without surrounding blo > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ``` +Always put that at the top, without the block quotes. Without it, users will NOT be able to try the PR and your work will have been in vain! + + + ## Custom Agents and Skills +The repository includes specialized custom agents and reusable skills for specific tasks. + ### Skills vs Agents | Aspect | Skills | Agents | |--------|--------|--------| -| Invoke | `/skill-name` or direct request | Delegate to agent | -| Output | Analysis, recommendations | Actions applied | -| Interaction | Interactive | Autonomous workflow | +| **Invoke** | `/skill-name` or direct request | Delegate to agent | +| **Output** | Analysis, recommendations | Actions, changes applied | +| **Interaction** | Interactive discussion | Autonomous workflow | +| **Example** | `/learn-from-pr` → recommendations | learn-from-pr agent → applies changes | ### Available Custom Agents -1. **pr** — PR review/fix workflow. Triggers: "review PR #XXXXX", "work on PR #XXXXX", "fix issue #XXXXX", "continue PR #XXXXX". Do NOT use for manual testing → use `sandbox-agent`. -2. **write-tests-agent** — Writes UI/XAML tests. Triggers: "write tests for #XXXXX", "create tests", "add test coverage". -3. **sandbox-agent** — Manual testing in Sandbox app. Triggers: "test this PR", "validate PR #XXXXX in Sandbox", "reproduce issue #XXXXX". Do NOT use for code review → use `pr` agent. -4. **learn-from-pr** — Extracts lessons and applies repo improvements. Triggers: "learn from PR #XXXXX and apply improvements", "update skills based on PR". For analysis only (no changes) → use `/learn-from-pr` skill instead. - -### Reusable Skills (`.github/skills/`) - -| Skill | Purpose | Trigger phrases | -|-------|---------|----------------| -| **issue-triage** | Triage open issues needing milestones/labels | "find issues to triage", "what issues need attention" | -| **find-reviewable-pr** | Find PRs needing review | "find PRs to review", "find partner PRs" | -| **pr-finalize** | Verify PR title/description match implementation; code review before merge. ⚠️ NEVER `--approve`/`--request-changes` | "finalize PR", "check PR description", "review commit message" | -| **learn-from-pr** | Analyze completed PR for repo improvements (analysis only, no changes) | "what can we learn from PR #XXXXX?" | -| **write-ui-tests** | Create UI tests that reproduce a bug | "write UI tests for #XXXXX", "add UI test coverage" | -| **write-xaml-tests** | Create XAML unit tests (parsing, XamlC, source gen) | "write XAML tests for #XXXXX", "test XamlC behavior" | -| **verify-tests-fail-without-fix** | Verify tests catch the bug before fix | After creating tests, before PR is complete | -| **azdo-build-investigator** | Investigate CI failures: build errors, Helix logs, binlog analysis | "check build for PR", "why did PR build fail", "get build status" | -| **run-integration-tests** | Run integration tests locally. **ALWAYS use instead of `dotnet test`** | "run integration tests", "run macOSTemplates tests", "run RunOniOS tests" | -| **try-fix** *(internal)* | One independent fix attempt; used by pr agent Phase 3. Max 5 attempts/session. | — | - -### Delegation Policy - -When a request matches agent trigger phrases, **immediately delegate — no permission needed.** - -- "Review PR #12345" → **pr** agent -- "Test this PR" → **sandbox-agent** -- "Fix issue #67890" (no PR exists) → suggest `/delegate` command -- "Write tests for #12345" → **write-tests-agent** -- Informational queries ("What does PR #12345 do?") → handle yourself \ No newline at end of file +1. **pr** - Sequential 4-phase workflow for reviewing and working on PRs + - **Use when**: A PR already exists and needs review or work, OR an issue needs a fix + - **Capabilities**: PR review, test verification, fix exploration, alternative comparison + - **Trigger phrases**: "review PR #XXXXX", "work on PR #XXXXX", "fix issue #XXXXX", "continue PR #XXXXX" + - **Do NOT use for**: Just running tests manually → Use `sandbox-agent` + +2. **write-tests-agent** - Agent for writing tests. Determines test type (UI vs XAML) and invokes the appropriate skill (`write-ui-tests`, `write-xaml-tests`) + - **Use when**: Creating new tests for issues or PRs + - **Capabilities**: Test type determination (UI and XAML), skill invocation, test verification + - **Trigger phrases**: "write tests for #XXXXX", "create tests", "add test coverage" + +3. **sandbox-agent** - Specialized agent for working with the Sandbox app for testing, validation, and experimentation + - **Use when**: User wants to manually test PR functionality or reproduce issues + - **Capabilities**: Sandbox app setup, Appium-based manual testing, PR functional validation + - **Trigger phrases**: "test this PR", "validate PR #XXXXX in Sandbox", "reproduce issue #XXXXX", "try out in Sandbox" + - **Do NOT use for**: Code review (use pr agent), writing automated tests (use write-tests-agent) + +4. **learn-from-pr** - Extracts lessons from PRs and applies improvements to the repository + - **Use when**: After complex PR, want to improve instruction files/skills based on lessons learned + - **Capabilities**: Analyzes PR, identifies failure modes, applies improvements to instruction files, skills, code comments + - **Trigger phrases**: "learn from PR #XXXXX and apply improvements", "improve repo based on what we learned", "update skills based on PR" + - **Output**: Applied changes to instruction files, skills, architecture docs, code comments + - **Do NOT use for**: Analysis only without applying changes → Use `/learn-from-pr` skill instead + +### Reusable Skills + +Skills are modular capabilities that can be invoked directly or used by agents. Located in `.github/skills/`: + +#### User-Facing Skills + +1. **issue-triage** (`.github/skills/issue-triage/SKILL.md`) + - **Purpose**: Query and triage open issues that need milestones, labels, or investigation + - **Trigger phrases**: "find issues to triage", "show me old Android issues", "what issues need attention" + - **Scripts**: `init-triage-session.ps1`, `query-issues.ps1`, `record-triage.ps1` + +2. **find-reviewable-pr** (`.github/skills/find-reviewable-pr/SKILL.md`) + - **Purpose**: Finds open PRs in dotnet/maui and dotnet/docs-maui that need review + - **Trigger phrases**: "find PRs to review", "show milestoned PRs", "find partner PRs" + - **Scripts**: `query-reviewable-prs.ps1` + - **Categories**: P/0, milestoned, partner, community, recent, docs-maui + +3. **pr-finalize** (`.github/skills/pr-finalize/SKILL.md`) + - **Purpose**: Verifies PR title and description match actual implementation, AND performs code review for best practices before merge. + - **Trigger phrases**: "finalize PR #XXXXX", "check PR description for #XXXXX", "review commit message" + - **Used by**: Before merging any PR, when description may be stale + - **Note**: Works on any PR + - **🚨 CRITICAL**: NEVER use `--approve` or `--request-changes` - only post comments. Approval is a human decision. + +4. **learn-from-pr** (`.github/skills/learn-from-pr/SKILL.md`) + - **Purpose**: Analyzes completed PR to identify repository improvements (analysis only, no changes applied) + - **Trigger phrases**: "what can we learn from PR #XXXXX?", "how can we improve agents based on PR #XXXXX?" + - **Used by**: After complex PRs, when agent struggled to find solution + - **Output**: Prioritized recommendations for instruction files, skills, code comments + - **Note**: For applying changes automatically, use the learn-from-pr agent instead + +5. **write-ui-tests** (`.github/skills/write-ui-tests/SKILL.md`) + - **Purpose**: Creates UI tests for GitHub issues and verifies they reproduce the bug + - **Trigger phrases**: "write UI tests for #XXXXX", "create UI test for issue", "add UI test coverage" + - **Output**: Test files that fail without fix, pass with fix + +6. **write-xaml-tests** (`.github/skills/write-xaml-tests/SKILL.md`) + - **Purpose**: Creates XAML unit tests for XAML parsing, compilation, and source generation + - **Trigger phrases**: "write XAML tests for #XXXXX", "test XamlC behavior", "reproduce XAML parsing bug" + - **Output**: Test files for Controls.Xaml.UnitTests + +7. **verify-tests-fail-without-fix** (`.github/skills/verify-tests-fail-without-fix/SKILL.md`) + - **Purpose**: Verifies UI tests catch the bug before fix and pass with fix + - **Two modes**: Verify failure only (test creation) or full verification (test + fix) + - **Used by**: After creating tests, before considering PR complete + +8. **pr-build-status** (`.github/skills/pr-build-status/SKILL.md`) + - **Purpose**: Retrieves Azure DevOps build information for PRs (build IDs, stage status, failed jobs) + - **Trigger phrases**: "check build for PR #XXXXX", "why did PR build fail", "get build status" + - **Used by**: When investigating CI failures + +8. **run-integration-tests** (`.github/skills/run-integration-tests/SKILL.md`) + - **Purpose**: Build, pack, and run .NET MAUI integration tests locally + - **Trigger phrases**: "run integration tests", "test templates locally", "run macOSTemplates tests", "run RunOniOS tests" + - **Categories**: Build, WindowsTemplates, macOSTemplates, Blazor, MultiProject, Samples, AOT, RunOnAndroid, RunOniOS + - **Note**: **ALWAYS use this skill** instead of manual `dotnet test` commands for integration tests + +#### Internal Skills (Used by Agents) + +9. **try-fix** (`.github/skills/try-fix/SKILL.md`) + - **Purpose**: Proposes ONE independent fix approach, applies it, tests, records result with failure analysis, then reverts + - **Used by**: pr agent Phase 3 (Fix phase) - rarely invoked directly by users + - **Behavior**: Reads prior attempts to learn from failures. Max 5 attempts per session. + - **Output**: Reports attempt results and failure analysis + +### Using Custom Agents + +**Delegation Policy**: When user request matches agent trigger phrases, **ALWAYS delegate to the appropriate agent immediately**. Do not ask for permission or explain alternatives unless the request is ambiguous. + +**Examples of correct delegation**: +- User: "Review PR #12345" → Immediately invoke **pr** agent +- User: "Test this PR" → Immediately invoke **sandbox-agent** +- User: "Fix issue #67890" (no PR exists) → Suggest using `/delegate` command +- User: "Write tests for issue #12345" → Immediately invoke **write-tests-agent** + +**When NOT to delegate**: +- User asks "What does PR #12345 do?" → Informational query, handle yourself +- User asks "How do I test PRs?" → Documentation query, handle yourself +- User has follow-up questions after agent completes → Continue the conversation yourself \ No newline at end of file From 8b27d084d16a3d52489799d6a17617e06830ec71 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 17:15:54 -0600 Subject: [PATCH 08/13] skill: add az to tools, binlogtool reconstruct/doublewrites, error patterns table - Add az CLI as optional prereq for binlog artifact download - Add binlogtool reconstruct (full text log) and doublewrites (double-write detection) - Add Common Build Error Patterns table (CS/NU/XamlC/##[error]/TimeoutException/MT/BL) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../skills/azdo-build-investigator/SKILL.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.github/skills/azdo-build-investigator/SKILL.md b/.github/skills/azdo-build-investigator/SKILL.md index a979f6eb3b9e..001fbe09e28a 100644 --- a/.github/skills/azdo-build-investigator/SKILL.md +++ b/.github/skills/azdo-build-investigator/SKILL.md @@ -21,6 +21,7 @@ This skill uses `bash` together with `pwsh` (PowerShell 7+) to run the PowerShel - `pwsh`: https://aka.ms/install-powershell Optional for binlog analysis (MSBuild failures): +- `az` (Azure CLI): `brew install azure-cli` / `winget install Microsoft.AzureCLI`, then `az extension add --name azure-devops` - `binlogtool`: `dotnet tool install -g binlogtool` (https://www.nuget.org/packages/binlogtool) ## When to Use @@ -110,6 +111,12 @@ binlogtool search "/tmp/maui-binlog/*.binlog" "error NU" # NuGet binlogtool search "/tmp/maui-binlog/*.binlog" "XamlC" # XAML compiler binlogtool search "/tmp/maui-binlog/*.binlog" "XA" # Android build errors +# Reconstruct full text log (useful when you need context around an error) +binlogtool reconstruct "/tmp/maui-binlog/*.binlog" > /tmp/maui-build.log + +# Detect double-write errors (multiple tasks writing to the same output file) +binlogtool doublewrites "/tmp/maui-binlog/*.binlog" + # Clean up Remove-Item -Recurse -Force /tmp/maui-binlog ``` @@ -133,6 +140,18 @@ The `Get-HelixLogs.ps1` script retrieves the console logs which show: - Any crashes or errors - Infrastructure issues (timeouts, installation failures, etc.) +## Common Build Error Patterns + +| Pattern | Area | Notes | +|---------|------|-------| +| `error CS####` | C# compiler | Root cause; check file/line reference | +| `error NU1###` | NuGet restore | NU1301 = feed unreachable; NU11## = resolution failure | +| `XamlC` | XAML compiler | MAUI-specific; usually missing type or invalid binding | +| `##[error]` | ADO infrastructure | Pipeline-level error, not a build error | +| `System.TimeoutException` | Test infra | Infrastructure timeout; may be transient | +| `error MT####` | iOS/Mac linker | Linking failure; check build logs | +| `error BL####` | Build logic | MSBuild task failure | + ## Common Helix Failure Patterns | Pattern in Console Log | Meaning | From 99fb0b47c68abf368bddb21eebbbc16f910b148e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 11:19:35 -0500 Subject: [PATCH 09/13] Apply multi-model review feedback to azdo-build-investigator skill - Remove 'When to Use' section (duplicates front matter description) - Add pipeline investigation priority order (maui-pr > devicetests > uitests) - Add concrete binlog decision tree (when to use vs. skip) - Fix bash context: rm -rf instead of Remove-Item - Add --detect false to az pipelines command - Remove duplicate Prerequisites section Addresses feedback from Opus, Sonnet, and Codex reviews on PR #34335. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../skills/azdo-build-investigator/SKILL.md | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/.github/skills/azdo-build-investigator/SKILL.md b/.github/skills/azdo-build-investigator/SKILL.md index 001fbe09e28a..0787bd7b3766 100644 --- a/.github/skills/azdo-build-investigator/SKILL.md +++ b/.github/skills/azdo-build-investigator/SKILL.md @@ -24,16 +24,6 @@ Optional for binlog analysis (MSBuild failures): - `az` (Azure CLI): `brew install azure-cli` / `winget install Microsoft.AzureCLI`, then `az extension add --name azure-devops` - `binlogtool`: `dotnet tool install -g binlogtool` (https://www.nuget.org/packages/binlogtool) -## When to Use - -- User asks about CI/CD status for a PR -- User asks about failed checks or builds -- User asks "what's failing on PR #XXXXX" / "why is CI red" / "build failed" -- User wants to see test results -- **User asks about Helix failures (device tests, integration tests, etc.)** -- **User needs to debug why tests are failing on Helix infrastructure** -- **Text logs say "Build FAILED" with no detail — use binlog analysis** - ## Scripts All scripts are in `.github/skills/azdo-build-investigator/scripts/` @@ -81,6 +71,11 @@ pwsh .github/skills/azdo-build-investigator/scripts/Get-HelixLogs.ps1 -BuildId < > **Focus on the first error chronologically — later errors usually cascade from the root cause.** +**Multiple pipelines**: PRs trigger multiple builds. Investigate in priority order: +1. **`maui-pr`** (main build) — check first, most failures here +2. **`maui-pr-devicetests`** — if device test failures +3. **`maui-pr-uitests`** — if UI test failures + ### Standard Build Failures 1. Get build IDs: `Get-PrBuildIds.ps1 -PrNumber XXXXX` - If output shows ⚠️ with no build IDs, CI was not triggered — read the diagnostic message @@ -95,14 +90,22 @@ pwsh .github/skills/azdo-build-investigator/scripts/Get-HelixLogs.ps1 -BuildId < 4. For specific platform: `Get-HelixLogs.ps1 -BuildId YYYYY -Platform Windows -ShowConsoleLog` ### Binlog Analysis (MSBuild/XamlC/NuGet failures) -When text logs are inconclusive, `.binlog` artifacts contain the full MSBuild structured log. + +**When to use binlog analysis**: +- ✅ `Get-BuildErrors` returns generic "Build FAILED" with no error messages +- ✅ Errors mention MSBuild, XamlC, or NuGet restore issues +- ✅ Error says "See binlog for details" +- ❌ Helix test failures (use `Get-HelixLogs` instead) +- ❌ Clear error messages already visible in build logs + +`.binlog` artifacts contain the full MSBuild structured log. **Requires `binlogtool`** (`dotnet tool install -g binlogtool`). If not installed, tell the user and stop. ```bash # Download the binlog artifact az pipelines runs artifact download --run-id BUILD_ID --artifact-name "binlog" --path /tmp/maui-binlog \ - --org https://dev.azure.com/dnceng-public --project public + --org https://dev.azure.com/dnceng-public --project public --detect false # Search for errors (broad first, then narrow) binlogtool search "/tmp/maui-binlog/*.binlog" "error" @@ -118,7 +121,7 @@ binlogtool reconstruct "/tmp/maui-binlog/*.binlog" > /tmp/maui-build.log binlogtool doublewrites "/tmp/maui-binlog/*.binlog" # Clean up -Remove-Item -Recurse -Force /tmp/maui-binlog +rm -rf /tmp/maui-binlog ``` ## Understanding Helix Logs @@ -160,8 +163,3 @@ The `Get-HelixLogs.ps1` script retrieves the console logs which show: | "No test result files found" | Tests never ran or process crashed | | "error MT..." or "error BL..." | Build/linking error (check build logs instead) | | Exit code non-zero | Test failures or infrastructure issues | - -## Prerequisites - -- `gh` (GitHub CLI) - authenticated -- `pwsh` (PowerShell 7+) From 31511b28030c89b2ecb288ee0f31da6cfb9cba3e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 11:45:07 -0500 Subject: [PATCH 10/13] Fix binlog artifact download section - maui doesn't use 'binlog' artifact name maui-pr build artifacts use names like 'Windows_NT_Build Windows (Debug)_Attempt1' and are Container type (not PipelineArtifact). Update section to list artifacts first and use the correct download approach. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../skills/azdo-build-investigator/SKILL.md | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/.github/skills/azdo-build-investigator/SKILL.md b/.github/skills/azdo-build-investigator/SKILL.md index 0787bd7b3766..83436cc6c0cc 100644 --- a/.github/skills/azdo-build-investigator/SKILL.md +++ b/.github/skills/azdo-build-investigator/SKILL.md @@ -102,10 +102,26 @@ pwsh .github/skills/azdo-build-investigator/scripts/Get-HelixLogs.ps1 -BuildId < **Requires `binlogtool`** (`dotnet tool install -g binlogtool`). If not installed, tell the user and stop. +**Finding the artifact name**: maui builds do not use a standard `"binlog"` artifact name. First list available artifacts to find the right one: + +```bash +az pipelines runs artifact list --run-id BUILD_ID \ + --org https://dev.azure.com/dnceng-public --project public --detect false \ + --query "[].name" -o tsv +``` + +Build log artifacts are named like `Windows_NT_Build Windows (Debug)_Attempt1` or `Darwin_Build macOS (Debug)_Attempt1`. Download via the zip URL from the artifact's `downloadUrl` property: + ```bash -# Download the binlog artifact -az pipelines runs artifact download --run-id BUILD_ID --artifact-name "binlog" --path /tmp/maui-binlog \ - --org https://dev.azure.com/dnceng-public --project public --detect false +# Get the download URL for the artifact +az pipelines runs artifact list --run-id BUILD_ID \ + --org https://dev.azure.com/dnceng-public --project public --detect false \ + --query "[?contains(name, 'Build')]" -o json + +# Download the zip (requires auth token - use gh auth token or az account get-access-token) +# Then extract and search +mkdir -p /tmp/maui-binlog +cd /tmp/maui-binlog && unzip -q artifact.zip # Search for errors (broad first, then narrow) binlogtool search "/tmp/maui-binlog/*.binlog" "error" From 2ab2ed8bfdc1233afc8c4b82405f57a8ed54e00a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 13:06:02 -0500 Subject: [PATCH 11/13] Fix Get-BuildErrors: detect test failures in passing Helix jobs Helix work items can exit with code 0 while individual tests fail, reported only via ADO test results API (not in job logs). The script previously reported 0 failures for these builds. Add Section 3 that queries ResultSummaryByBuild (public, no auth needed) to cross-check ADO test results: - Warns with Get-HelixLogs guidance when failures exist but logs show clean - Quietly notes test failure count when build errors already explain them Verified against build 1325582 (8 test failures in passing Helix jobs). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../scripts/Get-BuildErrors.ps1 | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/.github/skills/azdo-build-investigator/scripts/Get-BuildErrors.ps1 b/.github/skills/azdo-build-investigator/scripts/Get-BuildErrors.ps1 index 2ad34c5e521e..0caa07f089fb 100644 --- a/.github/skills/azdo-build-investigator/scripts/Get-BuildErrors.ps1 +++ b/.github/skills/azdo-build-investigator/scripts/Get-BuildErrors.ps1 @@ -205,4 +205,29 @@ $testFailures = ($uniqueResults | Where-Object { $_.Type -eq "TestFailure" }).Co Write-Host "`nSummary: $buildErrors build error(s), $testFailures test failure(s)" -ForegroundColor Cyan +# --- SECTION 3: Cross-check ADO test results API for failures not visible in job logs --- +# Helix work items can exit with code 0 while individual tests fail (reported via ADO test results API). +# This section detects that scenario so the agent knows to use Get-HelixLogs.ps1 -ShowConsoleLog. +if (-not $ErrorsOnly) { + try { + $summaryUrl = "https://dev.azure.com/$Org/$Project/_apis/test/ResultSummaryByBuild?buildId=${BuildId}&api-version=7.1-preview" + $summary = Invoke-RestMethod -Uri $summaryUrl -Method Get -ErrorAction SilentlyContinue + $reportedFailed = $summary.aggregatedResultsAnalysis.resultsByOutcome.Failed.count + $reportedTotal = $summary.aggregatedResultsAnalysis.totalTests + $runsWithFailures = $summary.aggregatedResultsAnalysis.runSummaryByOutcome.Failed.runsCount + + if ($reportedFailed -gt 0 -and $testFailures -eq 0 -and $buildErrors -eq 0) { + Write-Host "`n⚠️ ADO test results show $reportedFailed failed test(s) across $runsWithFailures run(s) (out of $reportedTotal total)" -ForegroundColor Yellow + Write-Host " These failures are inside Helix work items that exited with code 0." -ForegroundColor Yellow + Write-Host " To see them, run: Get-HelixLogs.ps1 -BuildId $BuildId -ShowConsoleLog" -ForegroundColor Yellow + } + elseif ($reportedFailed -gt 0) { + Write-Host "`nℹ️ ADO test results: $reportedFailed failed / $reportedTotal total tests" -ForegroundColor Gray + } + } + catch { + # ResultSummaryByBuild is a preview API and may not always be available - silently skip + } +} + $uniqueResults From 0b377b19e865b55cfe5af3fc090934ea0b043e34 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 14:22:54 -0500 Subject: [PATCH 12/13] azdo-build-investigator: add Get-BuildBinlogs.ps1 for Container artifact binlog download Container-type build artifacts (e.g. Windows_NT_Build*) require auth and the ADO File Container API (5.0-preview) to download. az pipelines artifact download does not support them. - Add Get-BuildBinlogs.ps1 that uses Bearer token to list and download .binlog files from Container artifacts - Update SKILL.md binlog section to use the new script - Verified: 7 binlogs present in Windows device test Container artifact Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../skills/azdo-build-investigator/SKILL.md | 54 +++--- .../scripts/Get-BuildBinlogs.ps1 | 166 ++++++++++++++++++ 2 files changed, 196 insertions(+), 24 deletions(-) create mode 100644 .github/skills/azdo-build-investigator/scripts/Get-BuildBinlogs.ps1 diff --git a/.github/skills/azdo-build-investigator/SKILL.md b/.github/skills/azdo-build-investigator/SKILL.md index 83436cc6c0cc..5f24732726a6 100644 --- a/.github/skills/azdo-build-investigator/SKILL.md +++ b/.github/skills/azdo-build-investigator/SKILL.md @@ -98,46 +98,52 @@ pwsh .github/skills/azdo-build-investigator/scripts/Get-HelixLogs.ps1 -BuildId < - ❌ Helix test failures (use `Get-HelixLogs` instead) - ❌ Clear error messages already visible in build logs -`.binlog` artifacts contain the full MSBuild structured log. +`.binlog` files are MSBuild structured logs inside Container-type build artifacts (e.g., `Windows_NT_Build Windows (Debug)_Attempt1`). -**Requires `binlogtool`** (`dotnet tool install -g binlogtool`). If not installed, tell the user and stop. +**Requires**: +- `az` CLI logged in (`az login`) — needed to get Bearer token for Container artifact API +- `binlogtool` — `dotnet tool install -g binlogtool` (https://www.nuget.org/packages/binlogtool) -**Finding the artifact name**: maui builds do not use a standard `"binlog"` artifact name. First list available artifacts to find the right one: +If either is missing, tell the user and stop. +**Step 1: List available artifacts** (no auth needed): ```bash az pipelines runs artifact list --run-id BUILD_ID \ --org https://dev.azure.com/dnceng-public --project public --detect false \ - --query "[].name" -o tsv + --query "[].{name:name, type:resource.type}" -o table ``` -Build log artifacts are named like `Windows_NT_Build Windows (Debug)_Attempt1` or `Darwin_Build macOS (Debug)_Attempt1`. Download via the zip URL from the artifact's `downloadUrl` property: +Build log artifacts are Container-type and named like `Windows_NT_Build Windows (Debug)_Attempt1` or `Darwin_Build macOS (Debug)_Attempt1`. +**Step 2: Download binlogs from a Container artifact**: ```bash -# Get the download URL for the artifact -az pipelines runs artifact list --run-id BUILD_ID \ - --org https://dev.azure.com/dnceng-public --project public --detect false \ - --query "[?contains(name, 'Build')]" -o json +# Download all binlogs from the build (requires az login) +pwsh .github/skills/azdo-build-investigator/scripts/Get-BuildBinlogs.ps1 -BuildId BUILD_ID -# Download the zip (requires auth token - use gh auth token or az account get-access-token) -# Then extract and search -mkdir -p /tmp/maui-binlog -cd /tmp/maui-binlog && unzip -q artifact.zip +# Download from a specific artifact +pwsh .github/skills/azdo-build-investigator/scripts/Get-BuildBinlogs.ps1 -BuildId BUILD_ID -ArtifactName "*Windows*Build*" +# Custom output directory +pwsh .github/skills/azdo-build-investigator/scripts/Get-BuildBinlogs.ps1 -BuildId BUILD_ID -OutputDir /tmp/mybinlogs +``` + +**Step 3: Analyze with binlogtool**: +```bash # Search for errors (broad first, then narrow) -binlogtool search "/tmp/maui-binlog/*.binlog" "error" -binlogtool search "/tmp/maui-binlog/*.binlog" "error CS" # C# compiler -binlogtool search "/tmp/maui-binlog/*.binlog" "error NU" # NuGet -binlogtool search "/tmp/maui-binlog/*.binlog" "XamlC" # XAML compiler -binlogtool search "/tmp/maui-binlog/*.binlog" "XA" # Android build errors +binlogtool search "/tmp/maui-binlogs/*.binlog" "error" +binlogtool search "/tmp/maui-binlogs/*.binlog" "error CS" # C# compiler +binlogtool search "/tmp/maui-binlogs/*.binlog" "error NU" # NuGet +binlogtool search "/tmp/maui-binlogs/*.binlog" "XamlC" # XAML compiler +binlogtool search "/tmp/maui-binlogs/*.binlog" "XA" # Android build errors -# Reconstruct full text log (useful when you need context around an error) -binlogtool reconstruct "/tmp/maui-binlog/*.binlog" > /tmp/maui-build.log +# Reconstruct full text log (useful for context around an error) +binlogtool reconstruct "/tmp/maui-binlogs/*.binlog" > /tmp/maui-build.log -# Detect double-write errors (multiple tasks writing to the same output file) -binlogtool doublewrites "/tmp/maui-binlog/*.binlog" +# Detect double-write errors +binlogtool doublewrites "/tmp/maui-binlogs/*.binlog" -# Clean up -rm -rf /tmp/maui-binlog +# Clean up when done +rm -rf /tmp/maui-binlogs ``` ## Understanding Helix Logs diff --git a/.github/skills/azdo-build-investigator/scripts/Get-BuildBinlogs.ps1 b/.github/skills/azdo-build-investigator/scripts/Get-BuildBinlogs.ps1 new file mode 100644 index 000000000000..e6ff1ae9d64b --- /dev/null +++ b/.github/skills/azdo-build-investigator/scripts/Get-BuildBinlogs.ps1 @@ -0,0 +1,166 @@ +<# +.SYNOPSIS + Downloads .binlog files from an Azure DevOps build's Container artifacts. + +.DESCRIPTION + Container-type build artifacts (e.g., "Windows_NT_Build Windows (Debug)_Attempt1") + cannot be downloaded via `az pipelines runs artifact download`. This script uses + the ADO File Container API with a Bearer token to list and download .binlog files. + + Requires: az CLI logged in (`az login`) to get an access token. + +.PARAMETER BuildId + The Azure DevOps build ID. + +.PARAMETER OutputDir + Directory to download binlogs to. Defaults to /tmp/maui-binlogs. + +.PARAMETER ArtifactName + Filter to a specific artifact by name (supports wildcards). Defaults to all Container artifacts. + +.EXAMPLE + # Download all binlogs from a build + ./Get-BuildBinlogs.ps1 -BuildId 1325582 + + # Download from a specific artifact + ./Get-BuildBinlogs.ps1 -BuildId 1325582 -ArtifactName "*Windows*Build*" + + # Custom output directory + ./Get-BuildBinlogs.ps1 -BuildId 1325582 -OutputDir ~/Downloads/binlogs +#> +param( + [Parameter(Mandatory = $true)] + [int]$BuildId, + + [string]$OutputDir = "/tmp/maui-binlogs", + + [string]$ArtifactName = "*" +) + +$ErrorActionPreference = "Stop" + +$Org = "https://dev.azure.com/dnceng-public" +$Project = "public" +$ApiVersion = "7.1" +$ContainerApiVersion = "5.0-preview" + +# --- Get auth token --- +Write-Host "Getting auth token from az CLI..." +try { + $tokenJson = az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798 2>&1 + if ($LASTEXITCODE -ne 0) { throw "az account get-access-token failed" } + $token = ($tokenJson | ConvertFrom-Json).accessToken +} catch { + Write-Error @" + +ERROR: Could not get Azure DevOps access token. + +Make sure you are logged in to az CLI: + az login + az extension add --name azure-devops # optional + +Then retry. +"@ + exit 1 +} + +$authHeaders = @{ Authorization = "Bearer $token"; Accept = "application/json" } + +# --- List artifacts for the build --- +Write-Host "Listing artifacts for build $BuildId..." +$artifactsUrl = "$Org/$Project/_apis/build/builds/$BuildId/artifacts?api-version=$ApiVersion" +$artifacts = (Invoke-RestMethod -Uri $artifactsUrl -Headers $authHeaders).value + +if (-not $artifacts) { + Write-Warning "No artifacts found for build $BuildId" + exit 0 +} + +# Filter to Container-type artifacts matching the name filter +$containerArtifacts = $artifacts | Where-Object { + $_.resource.type -eq "Container" -and $_.name -like $ArtifactName +} + +if (-not $containerArtifacts) { + Write-Warning "No Container-type artifacts found matching '$ArtifactName'" + Write-Host "Available artifacts:" + $artifacts | ForEach-Object { Write-Host " [$($_.resource.type)] $($_.name)" } + exit 0 +} + +Write-Host "Found $($containerArtifacts.Count) Container artifact(s) to search for binlogs." + +# --- Process each container artifact --- +$downloadCount = 0 +foreach ($artifact in $containerArtifacts) { + $artifactNameClean = $artifact.name + Write-Host "`n=== $artifactNameClean ===" + + # Extract container ID from resource.data (format: #/CONTAINERID/) + $containerId = $artifact.resource.data -replace '^#/(\d+)/?$', '$1' + if (-not $containerId -or $containerId -eq $artifact.resource.data) { + Write-Warning " Could not parse container ID from: $($artifact.resource.data)" + continue + } + Write-Host " Container ID: $containerId" + + # List files in this container path + $listUrl = "$Org/_apis/resources/Containers/${containerId}?itemPath=$([Uri]::EscapeDataString($artifactNameClean))&api-version=$ContainerApiVersion" + try { + $containerItems = Invoke-RestMethod -Uri $listUrl -Headers $authHeaders + } catch { + Write-Warning " Failed to list container contents: $_" + continue + } + + $binlogFiles = $containerItems.value | Where-Object { $_.itemType -eq "file" -and $_.path -match '\.binlog$' } + + if (-not $binlogFiles) { + Write-Host " No .binlog files found in this artifact." + $containerItems.value | Where-Object { $_.itemType -eq "file" } | Select-Object -First 5 | ForEach-Object { + Write-Host " (sample) $($_.path)" + } + continue + } + + Write-Host " Found $($binlogFiles.Count) .binlog file(s)" + + # Download each binlog + foreach ($file in $binlogFiles) { + $fileName = Split-Path $file.path -Leaf + $outPath = Join-Path $OutputDir $fileName + + # Create output directory if needed + if (-not (Test-Path $OutputDir)) { + New-Item -ItemType Directory -Path $OutputDir | Out-Null + } + + $downloadUrl = "$Org/_apis/resources/Containers/${containerId}?itemPath=$([Uri]::EscapeDataString($file.path))&api-version=$ContainerApiVersion&`$format=file" + Write-Host " Downloading: $fileName" + + try { + Invoke-WebRequest -Uri $downloadUrl -Headers $authHeaders -OutFile $outPath + $sizeMB = [Math]::Round((Get-Item $outPath).Length / 1MB, 1) + Write-Host " -> $outPath ($sizeMB MB)" + $downloadCount++ + } catch { + Write-Warning " Failed to download $fileName : $_" + } + } +} + +Write-Host "" +if ($downloadCount -gt 0) { + Write-Host "Downloaded $downloadCount .binlog file(s) to: $OutputDir" + Write-Host "" + Write-Host "Analyze with binlogtool:" + Write-Host " binlogtool search `"$OutputDir/*.binlog`" `"error`"" + Write-Host " binlogtool search `"$OutputDir/*.binlog`" `"error CS`" # C# compiler errors" + Write-Host " binlogtool search `"$OutputDir/*.binlog`" `"error NU`" # NuGet errors" + Write-Host " binlogtool reconstruct `"$OutputDir/*.binlog`" > /tmp/build.log" + Write-Host "" + Write-Host "Clean up when done:" + Write-Host " rm -rf $OutputDir" +} else { + Write-Warning "No binlog files were downloaded." +} From f9d3fc977664faca6cf0bbce46d7d5098d94134f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 14:24:22 -0500 Subject: [PATCH 13/13] azdo-build-investigator: fix Get-BuildBinlogs.ps1 (regex + OctetStream format) - Fix container ID regex: resource.data format is '#/ID/ArtifactName', not '#/ID/' - Fix download format: use OctetStream (not 'file') for binary artifact download Verified: downloads all 7 binlogs from Windows device test Container artifact Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../scripts/Get-BuildBinlogs.ps1 | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/skills/azdo-build-investigator/scripts/Get-BuildBinlogs.ps1 b/.github/skills/azdo-build-investigator/scripts/Get-BuildBinlogs.ps1 index e6ff1ae9d64b..0fa98c8aa67c 100644 --- a/.github/skills/azdo-build-investigator/scripts/Get-BuildBinlogs.ps1 +++ b/.github/skills/azdo-build-investigator/scripts/Get-BuildBinlogs.ps1 @@ -96,9 +96,12 @@ foreach ($artifact in $containerArtifacts) { $artifactNameClean = $artifact.name Write-Host "`n=== $artifactNameClean ===" - # Extract container ID from resource.data (format: #/CONTAINERID/) - $containerId = $artifact.resource.data -replace '^#/(\d+)/?$', '$1' - if (-not $containerId -or $containerId -eq $artifact.resource.data) { + # Extract container ID from resource.data (format: #/CONTAINERID/ or #/CONTAINERID/ArtifactName) + $containerId = $null + if ($artifact.resource.data -match '^#/(\d+)') { + $containerId = $matches[1] + } + if (-not $containerId) { Write-Warning " Could not parse container ID from: $($artifact.resource.data)" continue } @@ -135,7 +138,7 @@ foreach ($artifact in $containerArtifacts) { New-Item -ItemType Directory -Path $OutputDir | Out-Null } - $downloadUrl = "$Org/_apis/resources/Containers/${containerId}?itemPath=$([Uri]::EscapeDataString($file.path))&api-version=$ContainerApiVersion&`$format=file" + $downloadUrl = "$Org/_apis/resources/Containers/${containerId}?itemPath=$([Uri]::EscapeDataString($file.path))&api-version=$ContainerApiVersion&`$format=OctetStream" Write-Host " Downloading: $fileName" try {