一键导入
pr-monitor
Check CI status, analyze failures, and explain skips for a Dynamo PR
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Check CI status, analyze failures, and explain skips for a Dynamo PR
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | pr-monitor |
| description | Check CI status, analyze failures, and explain skips for a Dynamo PR |
| user-invocable | true |
| disable-model-invocation | true |
Perform a full health check on a Dynamo pull request. Takes a PR number as argument (e.g., /dynamo:pr-monitor 6554).
Gather PR metadata and determine what CI should look like for this PR.
gh pr view $PR_NUMBER --repo ai-dynamo/dynamo --json title,body,author,state,isDraft,additions,deletions,changedFiles,labels,reviewDecision,headRefName,baseRefName
gh pr diff $PR_NUMBER --repo ai-dynamo/dynamo --name-only
Check if full CI should be running. The dynamo repo has two tiers of CI:
pre-merge.yml): Triggers on all pull_request events. Runs pre-commit, copyright checks, DCO, and optionally rust-clippy/rust-tests (if rust filter matches). This always runs.pr.yaml, container-validation-dynamo.yml): Triggers on push to main or pull-request/[0-9]+ branches ONLY. This includes docker builds, GPU tests, deploy tests. It does NOT trigger on regular PR branches.To get full CI on a PR, a pull-request/$PR_NUMBER branch must exist (created by copy-pr-bot after an NVIDIA maintainer approves). Check:
gh api repos/ai-dynamo/dynamo/branches/pull-request/$PR_NUMBER 2>/dev/null
If the branch does not exist, full CI has not been triggered. Common reasons:
/ok to test <commit_sha> on the PR to create the branch and trigger full CI. This applies to both fork PRs and internal PRs from authors not yet in the approval list.Signed-off-by line missing). Check for a DCO bot comment. Fix: author signs their commits (see DCO.md).Verify which workflows actually ran against the PR's HEAD commit:
# Get the HEAD SHA
HEAD_SHA=$(gh pr view $PR_NUMBER --repo ai-dynamo/dynamo --json headRefOid --jq '.headRefOid')
# Check which workflow runs exist for this SHA
gh api "repos/ai-dynamo/dynamo/actions/runs?head_sha=$HEAD_SHA" --jq '.workflow_runs[] | {name: .name, status: .status, conclusion: .conclusion}'
Compare the workflows that ran against what's expected. If only Pre Merge, Copyright Checks, DCO Commenter, etc. appear but NOT PR or Dynamo Validation, then full CI was not triggered.
Determine which CI filters are active. If full CI ran, read the changed-files job output from the actual workflow run — this is the authoritative source for which filters are true:
# Find the PR workflow run ID
PR_RUN_ID=$(gh api "repos/ai-dynamo/dynamo/actions/runs?head_sha=$HEAD_SHA" --jq '.workflow_runs[] | select(.name == "PR") | .id')
# Get the changed-files job output (look for the filter results in the logs)
gh api "repos/ai-dynamo/dynamo/actions/runs/$PR_RUN_ID/jobs" --jq '.jobs[] | select(.name == "changed-files") | {id: .id, status: .status, conclusion: .conclusion}'
If full CI hasn't run, fall back to fetching filters.yaml and matching manually:
gh api repos/ai-dynamo/dynamo/contents/.github/filters.yaml --jq '.content' | base64 -d
Key rules for manual matching:
core being true triggers ALL framework pipelines (vllm, sglang, trtllm).*ci) — resolve these when reading.!**/*.md in a filter mean markdown-only changes do NOT trigger that filter.Jobs that always run in pr.yaml regardless of filters:
changed-files, deploy-operator, backend-status-check, clean-k8s-builder, cleanup — these run unconditionally or with if: always().Fetch all check runs. Note: gh pr checks returns non-zero exit codes when checks are pending or failed — this is normal, not an error.
gh pr checks $PR_NUMBER --repo ai-dynamo/dynamo
If no checks are returned at all, refer back to the Step 1 diagnosis (DCO, approval, draft status).
Ignore external CI checks (e.g., GitLab mirror ci/gitlab/*). These are NVIDIA-internal pipelines that cannot be inspected from GitHub. Only analyze GitHub Actions checks.
Distinguish two situations:
PR, Dynamo Validation): Analyze all jobs normally.Pre Merge and utility workflows only): Report this clearly. The filter predictions from Step 1 describe what would run once full CI triggers, but there's nothing to analyze yet beyond the lightweight checks.If full CI ran, identify the critical path — which checks are most relevant to this PR's changes based on the filter mapping from Step 1.
Produce a concise dashboard grouped by status:
For each failed GitHub Actions job, drill into the logs to extract root cause.
First, identify the failed jobs within each run:
gh api repos/ai-dynamo/dynamo/actions/runs/$RUN_ID/jobs --jq '.jobs[] | select(.conclusion == "failure") | {name: .name, id: .id, html_url: .html_url}'
Then fetch logs for specific failed jobs. The check URL format from gh pr checks is https://github.com/.../actions/runs/{RUN_ID}/job/{JOB_ID}. Extract the RUN_ID (first number):
gh run view $RUN_ID --repo ai-dynamo/dynamo --log-failed 2>&1 | tail -200
Note: --log-failed concatenates all failed job logs, which can be noisy. For multi-failure runs, prefer fetching per-job to isolate root causes.
For each failure, report:
gh run rerun $RUN_ID --repo ai-dynamo/dynamo --failedIf there are no failures, say so and move on.
For each failed job identified in Step 3, check if the same job also fails on main. This distinguishes PR-caused regressions from pre-existing flakes.
First, check how far behind the PR is from main:
gh api "repos/ai-dynamo/dynamo/compare/main...$HEAD_SHA" --jq '{behind_by: .behind_by, ahead_by: .ahead_by, status: .status}'
If the PR is significantly behind main (>20 commits), note this in the report — some failures may already be fixed on main, and some apparent "regressions" may just be the PR missing recent fixes.
Then, check recent main branch CI results:
# Get last 3 completed PR workflow runs on main
MAIN_RUNS=$(gh api "repos/ai-dynamo/dynamo/actions/workflows/pr.yaml/runs?branch=main&per_page=3&status=completed" --jq '[.workflow_runs[].id] | join(" ")')
# For each failed job name from Step 3, check if it also failed on main
for RUN_ID in $MAIN_RUNS; do
gh api "repos/ai-dynamo/dynamo/actions/runs/$RUN_ID/jobs?per_page=100&filter=latest" \
--jq ".jobs[] | select(.name == \"$FAILED_JOB_NAME\") | {run: $RUN_ID, conclusion: .conclusion}"
done
Classification:
[PR-CAUSED] — Fails on this PR but passes on all recent main runs → Likely a regression introduced by this PR. Needs attention.[PRE-EXISTING] — Also fails on recent main runs → Pre-existing flake, not caused by this PR. Suggest rerun.[UNCLEAR] — Mixed results on main (sometimes passes, sometimes fails) → Flaky test. Note flakiness and suggest rerun.[NEW JOB] — Job doesn't exist on main runs → New CI job added by this PR, can't compare.Important caveats to include in the report:
[PR-CAUSED] classification may be a false positive — the failure could already be fixed on main. Suggest: "Consider rebasing on main before investigating."This step is exception-based only. Do NOT enumerate expected skips — that's noise.
If full CI did not trigger, skip this step entirely — there are no jobs to analyze. The absence of full CI was already explained in Steps 1-2.
If full CI ran, compare the filter results from Step 1 against actual CI results from Step 2. Only report surprises:
true (files matched its paths) but the corresponding job was skipped or missingbackend-status-check, dynamo-status-check) was skipped — these use if: always() and should always runcore files changed (core should trigger all frameworks)Things that are NOT surprises (do not report):
false (e.g., docs jobs skipped when no docs changed)deploy-operator running despite operator=false — this job always runs in pr.yamlIf everything matches expectations, say "No unexpected skips or discrepancies" and move on.
Synthesize into a concise report:
PR Health: [PASSING | FAILING | PENDING | CI NOT TRIGGERED | PARTIAL — lightweight only]
If full CI not triggered:
/ok to test <sha> to create the pull-request/$PR_NUMBER branch."Blocking issues (PR-caused) — failures that pass on main but fail here:
backend-status-check or dynamo-status-check gate is failingPre-existing failures — also failing on main, not caused by this PR:
Non-blocking issues (if any):
[UNCLEAR] from Step 3b), infra timeouts, unexpected skipsCritical path status — the checks most relevant to this PR's changes:
Next steps — concrete actions ordered by priority:
/ok to test <sha>" if full CI hasn't triggeredgit commit --amend -s" for DCO failuresgh run rerun $RUN_ID --repo ai-dynamo/dynamo --failedIf any checks are still pending or in-progress, offer to monitor them.
List remaining checks:
gh pr checks $PR_NUMBER --repo ai-dynamo/dynamo | grep -E 'pending|queued|in_progress'
Report:
vllm-cuda12.9-amd64 / Test took 20m and vllm-cuda13.0-amd64 / Test is still running, estimate ~20m remaining)If the user wants to wait, poll periodically:
# Re-check status
gh pr checks $PR_NUMBER --repo ai-dynamo/dynamo | grep -cE 'pass|fail|skipped' # completed count
gh pr checks $PR_NUMBER --repo ai-dynamo/dynamo | grep -cE 'pending|queued|in_progress' # remaining count
When all checks complete, re-run the summary from Step 5 with final results. Report any checks that changed from pending to failed since the last check.
gh commands fail due to rate limiting, report what you could gather and suggest retrying later.pr.yaml, pre-merge.yml, and container-validation-dynamo.yml. Check all of them.pull-request/[0-9]+ branches: Created by copy-pr-bot after maintainer approval. Required for full CI — applies to both fork and internal PRs.external-contribution label: Fork PRs get this label automatically. Its presence confirms the PR is from an external contributor.ci/gitlab/* checks entirely. These are NVIDIA-internal and cannot be diagnosed from GitHub.Start a debugging session with worklog file
Maintain Dynamo Fern docs site -- add, update, move, or remove pages. Use for any documentation changes.
File a GitHub bug issue against ai-dynamo/dynamo using context from the current conversation.
Generate optimized tool call parsers for dynamo from HuggingFace model chat templates. Use this when you need to add support for a new model's tool calling format. Takes a HuggingFace model name, analyzes its chat template, compares with existing parsers, and either maps to existing parser or generates new Rust code with tests for the dynamo tool_calling library.