fix(hybrid-gate): filter blobs from the two metadata-only checkouts - #33
Merged
Conversation
`check-trailer` and `ai-attribution` both clone full history under a 5-minute budget, but neither reads file content — one reads commit trailers and changed path names, the other scans commit messages and PR metadata. On a large adopting repo the unfiltered clone is effectively the whole job. When it overruns, the job reports `cancelled`, which the gate cannot distinguish from a supersede. The PR goes red with nothing wrong with it, and `full-gate-build` is skipped because it needs `check-trailer`. Measured in aletheia: two runs cancelled at exactly 5m04s and 5m02s, both inside this checkout step, on unrelated PRs whose own code was fine. `blob:none` keeps every commit and tree and leaves blobs unfetched. Git lazily fetches any blob a step turns out to need, so this cannot break a future step that does read content — it only stops paying for content nothing reads. `full-gate-build` keeps its unfiltered clone: it compiles the tree.
forkwright
added a commit
to forkwright/aletheia
that referenced
this pull request
Aug 13, 2026
## Why `check-trailer` in the shared hybrid gate clones full history under `timeout-minutes: 5`, but reads only commit trailers and changed path names — never file content. On a repo this size that clone **is** the job. When it overruns, the job reports `cancelled`. The gate cannot distinguish that from a supersede, so the PR goes red with nothing wrong with it — and because `full-gate-build` has `needs: check-trailer`, the build is *skipped* rather than run, which presents as a build failure. ## Evidence from this repo, today | run | job | duration | cancelled at | |---|---|---|---| | `31621077227` | `check-trailer` | **5m04s** | `actions/checkout` | | `31632599095` | `check-trailer` | **5m02s** | `actions/checkout` | Both land on the timeout to within seconds, both inside the checkout step, with sibling jobs in the same run succeeding — in the second, `ai-attribution` finished in 21 seconds while `check-trailer` sat in checkout for five minutes. This kept reappearing as four different-looking failures across unrelated PRs (#6721, #6723, #6731, #6737), which is what made it read as four independent breaks rather than one infrastructure timeout. It is a **different** root cause from #6701's concurrency keying: that cancelled whole runs via the concurrency group; this cancels a single job while its siblings succeed. ## What the bump brings forkwright/.github#33 adds `filter: blob:none` to `check-trailer`'s and `ai-attribution`'s checkouts. Full history and all trees are kept — so `git log`, trailer reads and `git diff --name-only` are unaffected — while blobs go unfetched. It is safe against future edits: a partial clone lazily fetches any blob a step turns out to need, so it cannot break a step that reads content. `full-gate-build` keeps its unfiltered clone, since it compiles the tree. `aed4ca519` → `963532686f7853fa3555aab434455693969b63a1`. Co-authored-by: Cody Kickertz <admin@forkwright>
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
check-trailerandai-attributioneach runactions/checkoutwithfetch-depth: 0undertimeout-minutes: 5. Neither job reads file content — one reads commit trailers and changed path names, the other scans commit messages and PR metadata. On a large adopting repo the unfiltered full-history clone is effectively the entire job.When it overruns the budget, the job reports
cancelled. The gate cannot distinguish that from a supersede, so the PR goes red with nothing wrong with it — and becausefull-gate-buildhasneeds: check-trailer, the build is skipped rather than run, which reads like a build problem.Evidence
Measured in
forkwright/aletheiatoday, on two unrelated PRs whose own code was fine:31621077227check-traileractions/checkout31632599095check-traileractions/checkoutBoth land on the timeout to within seconds, both inside the checkout step, with sibling jobs in the same run succeeding. In the second run,
ai-attributioncompleted in 21 seconds whilecheck-trailersat in checkout for five minutes.This is a different root cause from the concurrency-keying issue this workflow's existing WHY comments describe (aletheia#6701). That one cancelled whole runs via the concurrency group; this cancels a single job while its siblings succeed, which is what makes it look like a code problem.
Correction
Add
filter: blob:noneto those two checkouts. This keeps every commit and tree — sogit log, trailer reads, andgit diff --name-onlyare unaffected — while leaving blobs unfetched.It is also safe against future edits: a partial clone lazily fetches any blob a step turns out to need. The change cannot break a step that reads content; it only stops paying for content nothing reads.
full-gate-builddeliberately keeps its unfiltered clone — it compiles the tree.Blast radius
This is the fleet-shared reusable gate, so it affects every adopting repo. The change is confined to two checkout steps and removes work rather than adding any; the failure mode if
blob:nonewere wrong would be a step failing to read a file, which is loud rather than silent.Adopting repos pin this workflow by SHA, so nothing moves until each repo bumps its pin.