Analyze CI build and test status from Azure DevOps and Helix for dotnet repository PRs. Use when checking CI status, investigating failures, determining if a PR is ready to merge, or given URLs containing dev.azure.com or helix.dot.net. Also use when asked "why is CI red", "test failures", "retry CI", "rerun tests", "is CI green", "build failed", "checks failing", or "flaky tests".
Analyze CI build status and test failures in Azure DevOps and Helix for dotnet repositories (runtime, sdk, aspnetcore, roslyn, and more).
🚨 NEVER use
gh pr review --approveor--request-changes. Only--commentis allowed. Approval and blocking are human-only actions.
📝 AI-generated content disclosure: When posting any content to GitHub (PR comments, retry commands, analysis summaries) under a user's credentials — i.e., the account is not a dedicated "copilot" or "bot" account/app — you MUST include a concise, visible note (e.g. a
> [!NOTE]alert) indicating the content was AI/Copilot-generated. Skip this if the user explicitly asks you to omit it.
Workflow: Gather PR context (Step 0) → run the script → read the human-readable output + JSON → synthesize recommendations yourself. The script collects data; you generate the advice. For supplementary investigation beyond the script, MCP tools (AzDO, Helix, GitHub) provide structured access when available; the script and CLI work independently when they're not.
[CI_ANALYSIS_SUMMARY]ghUse this skill when:
dev.azure.com, helix.dot.net, or GitHub PR links with failing checksThe Get-CIStatus.ps1 script targets Azure DevOps + Helix infrastructure specifically. It won't help with:
However, the analysis patterns in this skill (interpreting failures, correlating with PR changes, distinguishing infrastructure vs. code issues) apply broadly even outside AzDO/Helix.
# Analyze PR failures (most common) - defaults to dotnet/runtime
./scripts/Get-CIStatus.ps1 -PRNumber 123445 -ShowLogs
# Analyze by build ID
./scripts/Get-CIStatus.ps1 -BuildId 1276327 -ShowLogs
# Query specific Helix work item
./scripts/Get-CIStatus.ps1 -HelixJob "4b24b2c2-..." -WorkItem "System.Net.Http.Tests"
# Other dotnet repositories
./scripts/Get-CIStatus.ps1 -PRNumber 12345 -Repository "dotnet/aspnetcore"
./scripts/Get-CIStatus.ps1 -PRNumber 67890 -Repository "dotnet/sdk"
./scripts/Get-CIStatus.ps1 -PRNumber 11111 -Repository "dotnet/roslyn"
| Parameter | Description |
|---|---|
-PRNumber | GitHub PR number to analyze |
-BuildId | Azure DevOps build ID |
-ShowLogs | Fetch and display Helix console logs |
-Repository | Target repo (default: dotnet/runtime) |
-MaxJobs | Max failed jobs to show (default: 5) |
-SearchMihuBot | Search MihuBot for related issues |
The script operates in three distinct modes depending on what information you have:
| You have... | Use | What you get |
|---|---|---|
| A GitHub PR number | -PRNumber 12345 | Full analysis: all builds, failures, known issues, structured JSON summary |
| An AzDO build ID | -BuildId 1276327 | Single build analysis: timeline, failures, Helix results |
| A Helix job ID (optionally a specific work item) | -HelixJob "..." [-WorkItem "..."] | Deep dive: list work items for the job, or with -WorkItem, focus on a single work item's console logs, artifacts, and test results |
❌ Don't guess the mode. If the user gives a PR URL, use
-PRNumber. If they paste an AzDO build link, extract the build ID. If they reference a specific Helix job, use-HelixJob.
-PRNumber)refs/pull/{PR}/merge branch)-ShowLogs)[CI_ANALYSIS_SUMMARY] JSON block with all key facts for the agent to reason overAfter the script runs, you (the agent) generate recommendations. The script collects data; you synthesize the advice. See Generating Recommendations below.
-BuildId)[CI_ANALYSIS_SUMMARY] JSON.-HelixJob [and optional -WorkItem])-HelixJob alone: enumerates work items for the job and summarizes their status-HelixJob and -WorkItem: queries the specific work item for status and artifactsKnown Issues section: Failures matching existing GitHub issues - these are tracked and being investigated.
Build Analysis check status: The "Build Analysis" GitHub check is green only when every failure is matched to a known issue. If it's red, at least one failure is unaccounted for — do NOT claim "all failures are known issues" just because some known issues were found. You must verify each failing job is covered by a specific known issue before calling it safe to retry.
Canceled/timed-out jobs: Jobs canceled due to earlier stage failures or AzDO timeouts. Dependency-canceled jobs don't need investigation. Timeout-canceled jobs may have all-passing Helix results — the "failure" is just the AzDO job wrapper timing out, not actual test failures. To verify: use hlx_status on each Helix job in the timed-out build (include passed work items). If all work items passed, the build effectively passed.
❌ Don't dismiss timed-out builds. A build marked "failed" due to a 3-hour AzDO timeout can have 100% passing Helix work items. Check before concluding it failed.
PR Change Correlation: Files changed by PR appearing in failures - likely PR-related.
Build errors: Compilation failures need code fixes.
Helix failures: Test failures on distributed infrastructure.
Local test failures: Some repos (e.g., dotnet/sdk) run tests directly on build agents. These can also match known issues - search for the test name with the "Known Build Error" label.
Per-failure details (failedJobDetails in JSON): Each failed job includes errorCategory, errorSnippet, and helixWorkItems. Use these for per-job classification instead of applying a single recommendationHint to all failures.
Error categories: test-failure, build-error, test-timeout, crash (exit codes 139/134/-4), tests-passed-reporter-failed (all tests passed but reporter crashed — genuinely infrastructure), unclassified (investigate manually).
⚠️
crashdoes NOT always mean tests failed. Exit code -4 often means the Helix work item wrapper timed out after tests completed. Always checktestResults.xmlbefore concluding a crash is a real failure. See Recovering Results from Crashed/Canceled Jobs.
⚠️ Be cautious labeling failures as "infrastructure." Only conclude infrastructure with strong evidence: Build Analysis match, identical failure on target branch, or confirmed outage. Exception:
tests-passed-reporter-failedis genuinely infrastructure.
❌ Missing packages on flow PRs ≠ infrastructure. Flow PRs can cause builds to request different packages. Check which package and why before assuming feed delay.
When an AzDO job is canceled (timeout) or Helix work items show Crash (exit code -4), the tests may have actually passed. Follow this procedure:
Find the Helix job IDs — Read the AzDO "Send to Helix" step log and search for lines containing Sent Helix Job. Extract the job GUIDs.
Check Helix job status — Get pass/fail summary for each job. Look at failedCount vs passedCount.
For work items marked Crash/Failed — Check if tests actually passed despite the crash. Try structured test results first (TRX parsing), then search for pass/fail counts in result files without downloading, then download as last resort:
total, passed, failed attributes on the <assembly> elementfailed=0 and passed > 0, the tests passed — the "crash" is the wrapper timing out after test completionVerdict:
failed > 0 in testResults.xml → Real test failures. Investigate those specific tests.This pattern is common with long-running test suites (e.g., WasmBuildTests) where tests complete but the Helix work item wrapper exceeds its timeout during result upload or cleanup.
After the script outputs the [CI_ANALYSIS_SUMMARY] JSON block, you synthesize recommendations. Do not parrot the JSON — reason over it.
Read recommendationHint as a starting point, then layer in context:
| Hint | Action |
|---|---|
BUILD_SUCCESSFUL | No failures. Confirm CI is green. |
KNOWN_ISSUES_DETECTED | Known tracked issues found — but this does NOT mean all failures are covered. Check the Build Analysis check status: if it's red, some failures are unmatched. Only recommend retry for failures that specifically match a known issue; investigate the rest. |
LIKELY_PR_RELATED | Failures correlate with PR changes. Lead with "fix these before retrying" and list correlatedFiles. |
POSSIBLY_TRANSIENT | Failures could not be automatically classified — does NOT mean they are transient. Use failedJobDetails to investigate each failure individually. |
REVIEW_REQUIRED | Could not auto-determine cause. Review failures manually. |
MERGE_CONFLICTS | PR has merge conflicts — CI won't run. Tell the user to resolve conflicts. Offer to analyze a previous build by ID. |
NO_BUILDS | No AzDO builds found (CI not triggered). Offer to check if CI needs to be triggered or analyze a previous build. |
Then layer in nuance the heuristic can't capture:
canceledJobNames is non-empty, mention that canceled jobs may have passing Helix results (see "Recovering Results from Crashed/Canceled Jobs").lastBuildJobSummary.pending > 0, note that more failures may appear.builds has >1 entry, lastBuildJobSummary reflects only the last build — use totalFailedJobs for the aggregate count.knownIssues and prCorrelation won't be populated. Say "Build Analysis and PR correlation not available in BuildId mode."/azp run {pipeline-name} on the PR (e.g., /azp run dotnet-sdk-public)/azp run to retry all failing pipelinesBe direct. Lead with the most important finding. Structure your response as:
/azp run commands.Synthesize from: JSON summary (structured facts) + human-readable output (details/logs) + Step 0 context (PR type, author intent).
Before running the script, read the PR to understand what you're analyzing. Context changes how you interpret every failure.
| PR Type | How to detect | Interpretation shift |
|---|---|---|
| Code PR | Human author, code changes | Failures likely relate to the changes |
| Flow/Codeflow PR | Author is dotnet-maestro[bot], title mentions "Update dependencies" | Missing packages may be behavioral, not infrastructure (see anti-pattern below) |
| Backport | Title mentions "backport", targets a release branch | Failures may be branch-specific; check if test exists on target branch |
| Merge PR | Merging between branches (e.g., release → main) | Conflicts and merge artifacts cause failures, not the individual changes |
| Dependency update | Bumps package versions, global.json changes | Build failures often trace to the dependency, not the PR's own code |
❌ Don't skip Step 0. Running the script without PR context leads to misdiagnosis — especially for flow PRs where "package not found" looks like infrastructure but is actually a code issue.
Run with -ShowLogs for detailed failure info.
canceledJobNames is empty-BuildId if the user can provide the earlier build ID from AzDO.Before stating a failure's cause, verify your claim:
[ActiveIssue] attributes for known skipped tests-SearchMihuBot for semantic search of related issuesgh pr checks --json valid fields: bucket, completedAt, description, event, link, name, startedAt, state, workflow — no conclusion field, state has SUCCESS/FAILURE directly