ci(evidence): warning-only recipe-evidence drift gate for PRs#1065
Conversation
Adds the PR-side recipe-evidence gate: - recipe-evidence.yaml — `pull_request` workflow that runs in the untrusted PR context, computes the current recipe digest via `aicr evidence digest`, compares it to the signed predicate fetched through `aicr evidence verify`, and uploads a result artifact. - recipe-evidence-comment.yaml — `workflow_run` companion that consumes the artifact under the elevated default-token context and posts/updates the drift summary on the PR. The split (verify in `pull_request`, comment in `workflow_run`) is the standard GitHub pattern for keeping write-scoped tokens out of the untrusted PR workflow.
Moves the leaf-discovery + per-recipe evidence check pipeline out of recipe-evidence.yaml and into .github/scripts/recipe-evidence-check.sh. - Verify workflow shrinks to: checkout, build aicr, run script, upload artifact. The 280-line inline shell block in YAML is now a real file with shellcheck-able structure. - Same script runs locally for contributor self-preview — the header documents the AICR/BASE_SHA/HEAD_SHA/REPORT_OUT/REPO_URL contract, and `make build && bash .github/scripts/recipe-evidence-check.sh` reproduces what CI produces. - Future work (registry allow-list for `aicr evidence verify`, mixin-aware discovery) edits the script, not the workflow YAML. Two-workflow split (verify on `pull_request` → comment on `workflow_run`) is preserved — still the standard pattern for keeping write-scoped tokens out of the untrusted PR job.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Enterprise Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThis PR adds a non-blocking evidence verification gate for recipe overlays. It introduces a Bash script that discovers affected leaf overlays from the PR diff and verifies their signed-digest evidence with the aicr CLI, a "Recipe Evidence: Verify" workflow that builds aicr, runs the script, and uploads a report artifact, and a "Recipe Evidence: Comment" workflow that downloads the report and creates/updates a sticky PR comment with the Markdown results. Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 3 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/scripts/recipe-evidence-check.sh:
- Around line 96-105: The while loop that walks spec.base can hang on cyclic
chains because it has no termination guard; update the traversal (the loop using
current, parent, changed_files and setting include) to detect cycles by tracking
visited nodes (e.g., a visited set of parent names) or by enforcing a max-depth
counter and breaking if exceeded, and apply the same defensive check to the
other ancestor walk later in the script (the second while that similarly updates
current/parent/include) so both traversals cannot loop indefinitely.
In @.github/workflows/recipe-evidence-comment.yaml:
- Around line 83-90: The current logic uses head -1 to pick pr_number from pulls
which can silently choose the wrong PR; modify the selection to collect all
matching PR numbers (from the jq expression that filters by HEAD_OWNER), count
them, and only set pr_number when there is exactly one match; if count != 1,
emit the existing warning (using HEAD_SHA and HEAD_OWNER), set "skip=true" to
GITHUB_OUTPUT and exit 0. Update references to pr_number/pr matches accordingly
so subsequent posting only happens when a single PR was resolved.
In @.github/workflows/recipe-evidence.yaml:
- Around line 61-91: The workflow recipe-evidence.yaml must explicitly install
and pin yq and jq before running recipe-evidence-check.sh: add steps prior to
the "Run evidence check" step that install a specific yq and jq release (or call
a pinned composite action) so the script's invocations of yq and jq are
deterministic; ensure the step names are clear (e.g., "Install yq" and "Install
jq" or a single "Setup yq and jq" step), verify the tools are on PATH, and fail
the job if installation fails so recipe-evidence-check.sh won't silently proceed
without yq/jq available.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 61efe81e-c0aa-4407-9cda-ceb082499bd6
📒 Files selected for processing (3)
.github/scripts/recipe-evidence-check.sh.github/workflows/recipe-evidence-comment.yaml.github/workflows/recipe-evidence.yaml
mchmarny
left a comment
There was a problem hiding this comment.
Shape of the two-workflow split mirrors fern-docs-preview-* cleanly and the trusted-source PR re-derivation (commits//pulls + head-repo owner cross-check) is the right defense against the workflow_run trust boundary. Known limitations are honestly enumerated in the script header.
Four non-blocking inline comments: a substring-vs-line-equality issue in the three grep -qF rules (false positives on .bak/.orig/etc.), missing wall-clock timeout on aicr evidence verify/digest (PR-controlled pointer URL can hang to the job cap), and two nits — double-marker on truncation and 2>/dev/null swallowing stderr in the digest/verify warning paths.
Gate is warning-only and CI is green; nothing here blocks merge.
|
Actionable comments posted: 0 |
…S inference Commit signed recipe-evidence v1 pointers generated from live conformance validation on two H100 inference clusters, to exercise the warning-only recipe-evidence drift gate (NVIDIA#1065). - h100-gke-cos-inference-dynamo → ghcr.io/nvidia/aicr-evidence@sha256:6a59465f… (Rekor 1706764289) - h100-eks-ubuntu-inference-dynamo → ghcr.io/nvidia/aicr-evidence@sha256:da9d8838… (Rekor 1706788485) Both bundles built via 'aicr validate --phase conformance --emit-attestation' on aicr-demo5 (GKE/COS) and aicr3 (EKS/Ubuntu), signed + pushed via 'aicr evidence publish' (Sigstore keyless). Refs NVIDIA#1160
Summary
Adds a warning-only PR gate that surfaces stale or missing recipe-evidence bundles. For each leaf overlay touched by the diff, the gate computes the current canonical digest, compares it to the signed
predicate.recipe.digest(viaaicr evidence verify), and posts a sticky comment.Motivation / Context
PR #1055 landed
aicr evidence digest, giving us a cheap local way to detect drift between a signed evidence pointer and the current recipe. This PR wires it into CI so contributors are nudged — not blocked — to refresh evidence when they touch a recipe.The gate is intentionally warning-only because regenerating evidence requires a cluster matching the recipe's
criteria, and most contributors don't have that hardware on hand. Surfacing the drift in the PR comment makes it visible for reviewers and gives the maintainer-with-hardware a chance to refresh before merge.Fixes: #751
Related: ADR-007, follow-up to #1055
Type of Change
Component(s) Affected
.github/)Implementation Notes
Three files:
.github/scripts/recipe-evidence-check.sh— shared gate logic. Discovers leaf overlays touched by theBASE_SHA...HEAD_SHAdiff, runsaicr evidence digest+aicr evidence verifyagainst each, builds a Markdown report. Runnable locally..github/workflows/recipe-evidence.yaml—pull_requesttrigger, read-only token, buildsaicr, invokes the script, uploads the report as an artifact..github/workflows/recipe-evidence-comment.yaml—workflow_runtrigger, downloads the artifact, posts/updates the sticky PR comment under the standard write-scoped token. PR association is re-derived fromworkflow_run.head_sha(not the artifact, which is fork-attacker-controllable).Why the two-workflow split: standard GitHub pattern (matches the existing
fern-docs-preview-build+fern-docs-preview-comment). Keeps the PR-comment write token out of the untrusted PR-branch job.Leaf discovery rules:
spec.basechain changed.valuesFilereferenced by this overlay (or any ancestor) changed.Plus a broad-impact path: if
recipes/registry.yamlorrecipes/overlays/base.yamlchanged, every leaf is potentially affected and the report flags the breadth.Local invocation (same code paths CI uses):
Known limitations (tracked as follow-ups in the script header):
basename overlay .yaml, butaicr validate --emit-attestationuses the criteria-derived slug fromRecipeNameFor. Non-canonical overlay names will be reported as missing-pointer until they're aligned.spec.baseancestors but notspec.mixins; mixin/check/component edits outside literalvaluesFilerefs aren't promoted. Parity with the existing kwok-recipes Tier 2 classifier.aicr evidence verifyfetches OCI artifacts from PR-controlled URLs — an allow-list of trusted registries is a follow-up.Example reports
These cover the three most representative response states. All render under the bot identity as a sticky comment (marker
<!-- recipe-evidence-gate -->).Clean — no recipes touched
Single recipe, evidence on file, digest drifted (the marquee case)
Broad-impact change (
registry.yamlorbase.yamltouched)Beyond
MAX_ROWS(default 80), a truncation row replaces the rest:… +N more (truncated; raise MAX_ROWS or split the PR).Testing
Ran the script locally against two SHA ranges on this branch:
merge-base..HEAD(current branch — no overlay edits)8b493978^..8b493978(PR #977 — single leaf)gb200-eks-ubuntu-inference-dynamo)Pointer-present + verify branch wasn't exercised live —
recipes/evidence/doesn't exist in the tree yet. Path traced by inspection inrecipe-evidence-check.sh(lines 205-246).make qualify: not run (YAML/shell-only change, no Go).yamllintandactionlintrun in CI.Risk Assessment
pull-requests: writeis on the comment workflow only, posted body is verbatim script output, no failing exit code blocks the merge queue.Rollout notes: Gate activates automatically on PRs touching⚠️ missing rows — that's expected and serves as a backlog of what to generate.
recipes/**. No pre-existing pointers means most early PRs will showChecklist
fern-docs-preview-*)git commit -S)