fix(standard.mk): gates accumulate instead of aborting at the first red one - #19
Merged
Conversation
`gates` declared GATES_DEPS as prerequisites, so make stopped at the first failure and every gate ordered behind it never ran. That reads as an ordinary failure while a third of the set was silently skipped. Measured in doppler: `glibc-check` cannot pass on a modern dev box BY DESIGN, sits mid-list, and made the six targets behind it structurally unreachable -- a broken `coverage` hid there for weeks. `gates` now re-invokes its list with `-k`. Not a weakening: the sub-make still exits non-zero if any gate failed, so the run fails and `ALL PASS` cannot print, and under `-j` the gates still schedule in parallel -- which a shell loop over the list would have serialised. `--no-print-directory` keeps the recursion from adding Entering/Leaving noise. AND the part the issue expected to be free: `gates-check` breaks. It builds its closure by walking PREREQUISITES out of make's database (`sed -n "s/^$$t:[ ]*//p"`), so moving the list into the recipe leaves it walking an empty edge -- every CI target then reports as uncovered, and since `gates-check` hangs off `lint`, that is every adopter's `make lint` going red on the same fetch. Measured, not reasoned: the patch as proposed fails gates-check in a fixture. So the closure is seeded from `$(GATES_DEPS)` itself. That makes the check independent of HOW gates invokes its list, which is what it was always asserting. CI proves four properties, because three of them are what make the current form safe and a fix that drops one is not a fix: every gate runs, a red gate still fails the run, ALL PASS cannot print while one is red, and a clean run still passes. Sabotage-checked in both directions -- reverting to prerequisites fails on `behind1 never ran`, and applying `-k` WITHOUT the closure seeding fails on `gates-check cannot see GATES_DEPS any more`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This was referenced Aug 11, 2026
Merged
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.
Closes #18.
Reproduced the report exactly, in a fixture with a red gate mid-list:
firstandredrun,behind1andbehind2never do.The proposed patch works on three of its four claims
ALL PASScannot print with one redgates-checkis unaffectedgates-checkbuilds its closure by walking prerequisites out of make's database:Move
$(GATES_DEPS)into the recipe and that edge no longer exists, so the closure comes back empty and every CI target reports as uncovered.gates-checkhangs offlint, so that is every adopter'smake lintgoing red on the same fetch — the exact cost this repo's CI comment says only this job can catch.Fixed by seeding the closure from
$(GATES_DEPS)itself, which makes the check independent of howgatesinvokes its list — what it was always trying to assert.Also addressed from the issue's open questions
-j: verified.make -j4 gatesruns all four and still exits 2. The-kre-invocation keeps them schedulable in parallel; a shell loop over the list (the other obvious shape, and the one that would give a nicer failure summary) would have serialised them, which matters for doppler where gates include coverage and docker.--no-print-directory, or every run gainsEntering directory/Leaving directoryaround the gate output.Gate
New CI step asserting all four properties, sabotage-checked in both directions:
behind1 never ran-kwithout the closure seeding → fails withgates-check cannot see GATES_DEPS any moreExisting standard.mk CI steps re-run locally against the edited file and all still pass — including the
#13recursion guard, since-rpnstill targets.std-db-goaland never runs thegatesrecipe.Before merging — this publishes
Pages serves this file, and adopters compare against it on every
make lintwith no cache. The moment this lands,standard-checkfails in every subscriber until each re-vendors. Known adopters: just-makeit (re-vendor PR ready to follow immediately) and doppler (a different working lane — needs its own re-vendor, andmake lintthere is red in between).Happy to hold this until that ordering suits.
Not addressed, per the issue
glibc-checkfailing by design on every dev box is left alone — separable, as the issue says, and with-kit can stay honestly red without taking six gates down with it.