fix(ci): trailer-verify binds to the PR tip, not any ancestor (#2399) - #21
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Finding
gate-attestation.yml's verify step andhybrid-gate.yml'scheck-trailerstep both looped every PR commit (git log --format=%H origin/base..HEAD→for sha … breakon the firstGate-Passed:trailer). So an un-stamped tip could ride an ancestor's trailer: gate-attestation reports a false green on the actually-merged tree; hybrid-gate falsely setsfound=trueand skipsfull-gate-build(the real fmt/check/clippy/nextest). This is kanon#2399 — the dual of the false-DONE-GREEN class.Fix
Bind the trailer check to the PR tip (
github.event.pull_request.head.sha), not any ancestor. Step-only change: read the tip commit's own body via env-var indirection and check that.head.shais server-populated + content-addressed (un-spoofable) and is exactly the SHA branch-protection keys pass/fail to — a new push = a new SHA = a fresh unsatisfied requirement.fetch-depth: 0pull_requestcheckout (it is the second parent of the auto-merge commit), so the checkout is unchanged — which also keeps hybrid-gate'sdocs_onlydetection (it needs thebase..HEADhistory from the same checkout) working.PR_HEAD_SHA) satisfies the expression-injection rule, matching the siblingPR_AUTHOR/PR_HEAD_REFpattern already in these files.Unchanged: the 3-way automation waiver (
dependabot[bot]/release-please[bot]/startsWith(head_ref, 'release-please--branches--')), theactions/checkout@v7.0.1pin,fetch-depth: 0,persist-credentials: false, and hybrid-gate'sfoundoutput routing (never exits 1 → routes tofull-gate-build).Consumers pick this up automatically on
@main— no pin bump. kanon's own inlinegate-attestation.ymlcopy carries the same loop and is fixed separately (batched with a kanon train); therelease-please--branches--*waiver being an unauthenticated bypass is a distinct security issue (kanon#2628).Cross-validated (3 lenses): hole closed, no false-RED, actionlint clean.
Refs #2399