ci(trailers): the trailer gate cannot see a release promotion — fixed fetch-depth 100 vs 808 commits #16931
Description
Activity
github-actions commented
on Sep 19, 2026 on Sep 19, 2026 – with GitHub ActionsContributorMore actionsChunking triage — a proposal, not an assignment
- Proposed priority:
priority: high— not applied. Setting it is the milestone owner's call. - triage(v0.9.0): release criticality of the 123 open issues — 26 blocking, 36 small, 18 umbrellas, 41 misfiled, 2 undetermined #17639 criterion met: a release-pipeline defect — the trailer gate could not scan a full main->release promotion
- triage(v0.9.0): release criticality of the 123 open issues — 26 blocking, 36 small, 18 umbrellas, 41 misfiled, 2 undetermined #17639 bucket: 1 — genuinely blocking a v0.9.0 release
- Umbrella / container: no.
- Pre-filter: ⚠ a merged commit references this issue —
4c6879080d test(ci): evaluate the trailer gate's fetch-depth expression. A reference is not a delivery: verify AC coverage before putting it in a chunk, and consider a closure pass first. - Basis: triage(v0.9.0): release criticality of the 123 open issues — 26 blocking, 36 small, 18 umbrellas, 41 misfiled, 2 undetermined #17639's per-issue row, reused rather than re-derived — "Release gate: the trailer check could not scan a full main->release promotion. Per-PR fetch-depth fix on main (PR fix(ci): size the trailer gate's fetch to the PR so a release is scanned whole (#16931) #16932); no promotion run observed."
Nothing was relabelled, moved or closed by this pass.
- Proposed priority:
Closure pass — all four criteria met. Closing.
Evidence at
origin/main7adaca8c29; workflow.github/workflows/no-commit-trailers.yml.AC1 — #16801 passes
No commit trailershaving scanned all its commits — MET, observed.gh pr checks 16801reportsNo commit trailers pass 44s(run 35862044000). The scanned-count equality is what the guard itself enforces::94fails whenscanned != EXPECTED_COMMITSwith "the checkout is too shallow and the oldest commits would go unexamined". So a pass on a 682-commit promotion is the full scan — the guard cannot pass on a truncated range.AC2 — an ordinary PR still checks out at depth 100 — MET.
:61:fetch-depth: ${{ (github.event_name == 'merge_group' || github.event.pull_request.commits > 90) && '0' || '100' }}
Full history only for a merge group or a PR deeper than 90 commits. The comment at
:55-60records why the threshold is 90 rather than arithmetic — "Expressions have comparison but no arithmetic" — and that depth 100 is guaranteed to fail anyway for that set, so the #16207 saving is never spent on a PR that would have passed.AC3 — the truncation guard unchanged and still failing an unreachable range — MET. Both halves survive: the endpoint-presence check ("is not present in the checkout — this PR is deeper than the checkout") and the scanned-vs-reported count check. Its comment records the case it exists for: at depth 100 both endpoints can be present while
git rev-listsilently returns fewer commits.AC4 — the error message no longer hardcodes "fetch-depth 100" — MET. Both messages now read "Raise fetch-depth in this workflow" and "Raise fetch-depth (#16207)", with no depth named, which is correct now that the depth is chosen per PR.
Landed via PR#16932 /
4c6879080d. All four met — closing.
Finding
The release promotion #16801 (
main→release) failsNo commit trailers— not because any commit carries a banned trailer, but because the gate cannot see the whole release:.github/workflows/no-commit-trailers.ymlchecks out at a fixedfetch-depth: 100. #16801 carries 808 commits, so 254 of them were never examined, and the gate correctly refuses to report a truncated range as clean.This is the guard working, and its own comment predicted it
The depth was set by #16207 with a measured rationale: a full clone is ~12,900 commits on
main, cost 13s of git for 1s of work (93% of the job) on every PR, and the deepest PR among the last 40 merged was 30 commits — so 100 was over 3x the observed maximum. The comment then adds:A release promotion is the future it was guarding against. Every
main→releasePR carries every commit since the last release, so it will always exceed any fixed depth chosen for ordinary PRs. The next release will fail the same way, and the one after.The release would pass once the gate can see it
Checked locally against all 808 commits in
release..main, applying the gate's own rule to each commit's final block:Co-authored-by: github-actions[bot](two address forms)[bot]identities are exempt by rule (#13654)Co-authored-by: dependabot[bot]Co-authored-by: t <…>— placeholder author leaked from test fixtures (#16124).github/commit-trailer-baseline.txtSo the depth is the only thing between #16801 and a green gate.
Fix
Size the fetch to the PR instead of guessing once for all of them:
GitHub Actions expressions support comparison but not arithmetic, which is why this is a threshold rather than
commits + N.Acceptance criteria
No commit trailers, having scanned all of its commits — the scanned count equals GitHub's reported count