ci: rule 3 does not reach a run that carries no per-commit answer - #590
Merged
Merged
Conversation
Rule 3 states an absolute — "**Only a PR run is ever in a shared group**" —
and the family has three standing counterexamples, all in `hausfold.co`:
`deploy.yml`, `dns.yml` and `preview-sweep.yml`, each keying every run into
one constant group named for the workflow, each on purpose, and the doc said
nothing about any of them. An unstated exemption is what the next PR "fixes".
Census over the org's public repos at their `origin/main`: 27 workflows, 21
carrying a `concurrency:` block, exactly 3 with a constant top-level group.
The near misses are `scruff`'s `release.yml` (`release-${{ github.ref }}`) and
hausfold.co's `preview.yml` (keyed on the PR number), both correctly keyed.
`ops` is private and outside the sweep; it runs a scheduled `scoreboard` and
nothing on a push.
The property, written so the count is not load-bearing: what a gate loses when
an intermediate run is dropped is that commit's answer, which nothing else
will produce. These three converge something outside the repo instead — the
deployed site, the DNS zone, this repo's own preview Workers — and a converge
has no answer to lose, because the surviving run redoes the whole job from the
current state. For them the constant group is the point of the line, not a
cost of it: what it serializes is the resource.
The guard against reading that wider than it is: check for a `pull_request`
trigger first. None of the three has one, and `preview.yml` is the standing
example of a workflow that converges something external AND has a PR run, and
keys on the PR number anyway. The one other constant group in the family,
`pounce`'s job-level `bump-pin`, is in a release workflow and off this list by
the doc's own line; a reader who greps finds four and now knows why.
`cancel-in-progress` is a second and separate question, about what a stopped
run leaves behind, and the three do not share one reason. `deploy` cancels, a
newer build superseding an older outright. `dns` does not, because a converge
stopped between two tables leaves the zone half-way. The preview sweep does
not for a different reason entirely: its deletes are independent and a Worker
already gone counts as success, so nothing is half-written — there is just
nothing for a later run to supersede, and a `dry_run` dispatch would otherwise
take out a live sweep.
And the cost is stated rather than papered over. `dns`'s scheduled `check`
shares `group: dns` with `publish`, a *pending* run is cancelled outright when
a newer one joins whatever `cancel-in-progress` says, so a Monday check queued
behind a running converge can be dropped and that week's drift answer waits
seven days. One writer on the zone is worth more than one week's report. It is
a trade made once, for a converge, and not a reason to key a gate this way.
Follow-up to #587, which narrowed rule 3's endorsement of `hausfold.co` so the
paragraph could not be read as blessing these three, but left the exemption
itself unwritten.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UMUHVTxRfgADnACNXzc6Ef
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.
What
docs/ci.md, one insertion into rule 3 (41 added, 20 of them rewrites of nothing — pure addition againstmain). Docs only.Rule 3 bolds an absolute — "Only a PR run is ever in a shared group" — and the family has three standing counterexamples that the doc never mentioned. This writes the exemption.
Follow-up to #587, which narrowed rule 3's endorsement of
hausfold.coso the paragraph could not be read as blessing them, but deliberately left the exemption itself unwritten.Why
An unstated exemption is what the next PR "fixes". Three workflows key every run into one constant group with no
github.shain it, all inhausfold.co—deploy.yml,dns.yml,preview-sweep.yml— each on purpose and each commented (two of them) in its own file.The property is written so the count is not load-bearing: what a gate loses when an intermediate run is dropped is that commit's answer, which nothing else will produce. These three converge something outside the repo instead — the deployed site, the DNS zone, this repo's own preview Workers — and a converge has no answer to lose, because the surviving run redoes the whole job from current state. For them the constant group is the point of the line, not a cost of it.
Three things the text is careful about, each of which a review caught in the first draft:
pull_requestguard comes with a standing example, not a hypothetical.preview.ymlconverges something external and has a PR run, and keys on the PR number anyway — rule 3's ternary with only the PR arm left.cancel-in-progressreason.deploycancels (a newer build supersedes outright);dnsdoes not (a converge stopped between two tables leaves the zone half-way, its own words); the preview sweep does not for a completely different reason — its deletes are independent and an already-gone Worker counts as success, so nothing is half-written; there is simply nothing to supersede, and adry_rundispatch would otherwise take out a live sweep. The first draft gave the sweepdns's reason, which its own job body contradicts.dns's scheduledchecksharesgroup: dnswithpublish, and a pending run is cancelled outright when a newer one joins whatevercancel-in-progresssays — so a Monday check queued behind a running converge can be dropped, and that week's drift answer waits seven days. One writer on the zone is worth more than one week's report. That is a trade made once, for a converge, not a reason to key a gate this way.Verify
Census over every public repo in the org at its
origin/main, walking.github/workflows/*rather than trusting a list (opsis private and outside it; it runs a scheduledscoreboardand nothing on a push):concurrency:blockgroup:hausfold.codeploy.ymlgroup: deploy,cancel-in-progress: truedns.ymlgroup: dns,cancel-in-progress: falsepreview-sweep.ymlgroup: preview-sweep,cancel-in-progress: falsepull_request:triggerpush+dispatch,push+schedule+dispatch,schedule+dispatchNear misses, both correctly keyed and correctly excluded:
scruff'srelease.yml(release-${{ github.ref }}) andhausfold.co'spreview.yml(preview-${{ github.event.pull_request.number }}).The fourth constant group a reader's grep will find is
pounce's job-levelbump-pininrelease.yml. Release workflows are off this list by the doc's own line, and the text now says so in half a clause so the grep closes instead of reading stale.Reasons checked against the workflows themselves, not assumed:
deploy.ymlanddns.ymleach carry a comment stating theirs.preview-sweep.ymlcarries none — its reason here is read out of the job body (independent per-WorkerDELETEs, acontinueon per-Worker failure, Cloudflare10007treated as success, adry_rundispatch input).Pre-PR assurance pass run on the diff +
AGENTS.md. Nothing at 5; the one 4/5 (the sweep's invented reason) and all three 3/5s (the "is not a gate" opener colliding with this file's own gate table, thednsscheduled-check arm, the fourth constant group) are fixed in this commit. No test in this repo asserts ondocs/ci.md.Watch out
docs/ci.mdis hot — CI: one run per commit, nothing from apt, and the rules written down #578, ci: haus is five ubuntu jobs, the shell half four of them #580 through ci: a fifth rule — group parallel jobs by need, not by step count #585, and ci: hausfold.co fixed what rule 3's paragraph still calls out #587 all landed in it today. Rebase ontomain, never mergemainin.bench overlap, verbatim:The
⚠is on a file this branch does not touch.add-homebrew-formuladoes touchdocs/ci.md, but only at the gate table near the top, nowhere near this insertion.preview-sweep.ymlhas no comment on its concurrency block, so after this landsdocs/ci.mdis the only place itscancel-in-progress: falseis explained — the one fact here with no home in the repo that owns it. That is now ci: say why the sweep never cancels itself hausfold.co#348, which puts the reason in the file that owns it — land it first, or this doc is briefly the only copy.The doc's opener deliberately avoids the word "gate" for these three, because
docs/ci.md's own gate table lists Deploy, DNS and the preview sweep among hausfold.co's gates. "Produces no per-commit answer" is the operative test; "not a gate" would have made the file contradict itself.🤖 Generated with Claude Code
https://claude.ai/code/session_01UMUHVTxRfgADnACNXzc6Ef