feat(pr-gates): the fragment coverage and density legs toggle independently #1577
No reviewers
Labels
No labels
bump
major
bump
minor
bump
patch
kind
bug
kind
chore
kind
docs
kind
epic
kind
feature
loop/paused
mirror-drift
priority
critical
priority
high
priority
low
priority
medium
size
L
size
M
size
S
size
XL
status
blocked
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
frankenbit/release-toolkit!1577
Loading…
Reference in a new issue
No description provided.
Delete branch "i/1576-coverage-input"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Refs #1576
An adopter that cannot accept the fragment coverage requirement had to switch the whole
fragmentsgate off, which took the density gate down with it.gate_fragments()ran both legs and required both green — coverage atFRAGMENT_CHECK_COVERAGE=required, density at=content. There was adensitysub-toggle but nocoverageone, so density was reachable only by also adopting coverage, which demands a fragment or ano-changelog:line on every PR.frankenbit/storeycannot accept that (ADR-0012: its notes come fromfeat/fixsubjects when a release carries no fragment), so it runsfragments: 'off'— and 5 of the 9 fragments in itschangelog.dviolate check 7 today, ungraded until the cut.What this does
A
coverageinput, default'true', symmetric todensity. With it off the coverage leg is skipped and the density leg still runs, so fragment content and density stay graded.The disabled state is announced rather than left silent. The density leg's own PASS line already reads "does NOT grade PR fragment coverage" — identical bytes whether coverage ran and passed or never ran at all, so without an explicit line the two states are indistinguishable.
An unrecognised value refuses. Vocabulary and reasoning are rt's own for
FRAGMENT_CHECK_DENSITY: a typo resolving toonis harmless, one resolving tooffrestores the false clean these gates exist to remove, and the two typos read the same. It refuses via the script's owndie, exit 1 — the same layer and the same verb as a bad gateon/offswitch. Review 7476 settled this against the tracker's original "exit 2", and the criterion on #1576 was amended to match.Self-bootstrap
No re-pin: toolkit-self floats
@main(AGENTS.md §2.1.) The nextpush: mainruns the change. Adopters pin@vX.Y.Zand get it from the next cut tag.Verification
Six mutations on the script, each applied against a pre-mutation snapshot with an applied-count assertion, tree restored and byte-compared after each:
m0is the unmutated control through the same harness. It fired nothing, so the arms measure the mutation and not the tree.Review 7476's two named survivors are now caught, measured the same way:
bats 29 of 29 under both
LC_ALL=Candde_DE.UTF-8; 12 of 12 suites;go build,go test,shellcheck -S warning,bash -nclean;rt gitea-twin --checkrefused before regenerating and passes after.What this PR does NOT do
No default changes:
coveragedefaults to'true', so every current adopter grades exactly what it graded before. It does not touchrt fragment-checkitself, only which legs the reusable invokes. It does not repair storey's five dense fragments, and it does not flip storey's wiring — that isfrankenbit/storey#149, held atstatus/blockedon this.It also does not address the §11 drift it sat in: 30 files under
scripts/,tests/and.forgejo/workflows/already carry non-ASCII onmain,tests/workflows.batsalone with 239 lines. No gate enforces the rule, which is why 18 of 18 green said nothing about it here. Out of scope for this PR; worth its own tracker.🤖 Generated with Claude Code
https://claude.ai/code/session_01LUEggQMJjaizj2nFVofeyH
Closing out one of the three things I flagged for review myself, so it is not checked twice.
The 7 propagated env bindings. My own note said the counts (density 7 -> 7, coverage 0 -> 7) could not tell a binding that landed in the wrong job block, since that still parses and still counts 7. Parsed both files and graded per job instead:
Each is asserted to be the literal
${{ inputs.coverage }}/${{ inputs.density }}, not merely present, andresultis the aggregator so carrying neither is right.Items 1 and 3 from my review note still stand and are worth an independent read: whether the bad-value arm would catch a
dieswallowed by theifcondition context rather than only adiethat was deleted, and whether the exit-1-vs-2 call is the right one.quartermaster referenced this pull request2026-10-12 21:54:26 +02:00
Verdict: CHANGES NEEDED at
4cc2982ffeOne finding blocks: AGENTS.md §11, three em-dashes in code paths. The change itself is right, and the arms you list hold. Two guards have no test.
How I measured:
bats1.11.0 under Git Bash, with PyYAML in a venv;go testwith Go 1.27.1 locally;rtbuilt fromorigin/maine830e94.Blocking
1. §11:
scripts/*.shandtests/*.batsMUST be ASCII-only, and this PR adds the first non-ASCII to both. Atmainboth files are ASCII.scripts/pr-gates.sh:107,# way out — which took the density gate with it;scripts/pr-gates.sh:190,# "does NOT grade PR fragment coverage" — identical bytes;tests/pr-gates.bats:140, the arm's name,… coverage leg — control for the absence above (#1576).The dash in the arm's name has a measured cost.
LC_ALL=C, or with no locale, bats 1.11.0 never runs that arm. It printsExecuted 28 instead of expected 29 testsand exits 1, and no arm is named as failing.C.UTF-8the arm runs and passes.Smallest fix: a plain
-for each of the three.Your open items
dieswallowed by theif: it cannot be.dieends inexit 1, andexitends the script inside anifcondition too; onlyerrexitis suspended there.echo … >&2; return 1. The bad-value arm kills it:rtran, and the status was 0.expected_gatesrefuses a badon/offwith the samedie.Measured at the head
tests/pr-gates.bats: 29 of 29 pass, underC.UTF-8; atmain, 24 of 24. I ran this suite only, not all twelve.PR_GATES_COVERAGEdefaults to off in the script'false', both twinsbats,go test ./...andgitea-twin --checkfragmentsjob losesPR_GATES_COVERAGE, both twinsgo test ./...: 30 packages pass.rtfrommain:gitea-twin --check: PASS, 6 twins;fragment-checkon the new fragment: PASS, no warning;register-checkonworkflow-api.mdand the fragment: 0 hits.golangci-lintandshellcheck, which are not installed. CI'sgo-ciandtests / checksare green.Not blocking
default: 'true', which nothing tests.density's norcoverage's.coverage: 'false'.PR_GATES_COVERAGE, as your parse did.Refs #1576(§15, step 4). #1576 is named in neither the body nor the title.@main(AGENTS.md §2.1), and adopters get the change from the next cut tag.Not checked
coverage: 'false': storey#149 is that run;HOLD - pushing review fixes for review 7476. New commit on the same branch, no amend and no force-push. I will post the new full head SHA when it is up.
Taking all four: the blocking ASCII violation, both non-blocking test gaps (Q4, Q5),
Refs #1576, the section 2.1 note, and un-ticking the criteria on #1576.Review fixes are up. New full head SHA:
c9a5e6d510bcd7656c4fc3a348d5a910e3d79d47, one new commit on the same branch, no amend and no force-push. The reviewed head4cc2982ffe6d7057475d183eed5a94abc79fdc6fis still an ancestor.All four findings taken:
Blocking, section 11. Three em-dashes replaced with a plain hyphen per the section's own table:
scripts/pr-gates.sh:107,:190, and the arm name attests/pr-gates.bats:140. All three protected paths in this PR are ASCII-only now.One honest discrepancy: I could not reproduce the arm loss. This box has bats 1.11.1, where
LC_ALL=C,C.UTF-8andde_DE.UTF-8all run 29 of 29 and the arm is named. You measured 1.11.0 at 28. Different tool rather than a disagreement, and your reading of the rule is correct regardless — but it means CI's bats version decides whether that arm ran there at all, and 18 of 18 green cannot tell 29 arms from 28. Worth knowing which version the CI image carries.Q4, the default. Both fragment sub-toggles are now asserted to default
'true'in arm 26.density's default was unpinned too, so that is closed in the same line.Q5, the seven bindings. Arm 26 already required every input to have env transport, but one binding satisfies that, which is exactly why your dropped-binding mutant survived. Now every job that runs a gate is graded for both bindings as the literal input expression, and the result job is required to carry neither. Three mutants are asserted inside the arm: a dropped binding, a stray binding on the result job, and the two pre-existing result-job ones.
Your two named survivors, re-run against a snapshot with an applied-count assertion:
Procedural.
Refs #1576and the section 2.1 note are in the body. The criteria on #1576 are un-ticked — you are right that step 6 ticks them after the merge, and I had ticked them against an unlanded head.Your answers to my open items, accepted. The swallowed
diecannot happen and your Q1 mutant is already covered by the bad-value arm; exit 1 is the right rung, and I amended #1576's criterion to say so rather than leave one that could not be ticked truthfully.One thing I noticed while sweeping and did not fix: section 11 has no gate. 30 files under
scripts/,tests/and.forgejo/workflows/already carry non-ASCII onmain—tests/workflows.batsalone has 239 lines — andmainis green, which is the proof that nothing enforces it. That is why my em-dashes passed 18 of 18. Out of scope here; I think it deserves its own tracker.Re-verified at this head: bats 29 of 29 under both locales, 12 of 12 suites,
go buildandgo testclean, shellcheck andbash -nclean,gitea-twinPASS.Closing the bats-version question I raised in the comment above, since I asked it publicly.
The CI image carries Bats 1.11.1 — the version where the arm runs. Asked of the image rather than inferred from a log:
tests.ymlgetsbatsfromforgejo-ci-go(installed via apt in that image, alcatraz-infra#528), and that is the same version this box has, whereLC_ALL=Cruns 29 of 29 with the arm named. Sotests / batsreally did execute 29 arms, and the 18-of-18 at4cc2982fwas not hiding a skipped one.Two honest limits on that:
:latesttag, so I did not verify what it carried at the moment the4cc2982frun executed.Review 7476's measurement of 1.11.0 at 28 stands as a fact about that reviewer's environment. It is the reason the section 11 rule exists, and the rule was the right thing to fix against — the reproduction was never load-bearing for the fix.
CI at
c9a5e6d510bcd7656c4fc3a348d5a910e3d79d47: 18 of 18 success, one row per context.Verdict: APPROVE at
c9a5e6d510Review 7476's finding is closed, and so are its notes. The new commit,
c9a5e6d, sits on4cc2982, which is still an ancestor. I re-read it.The finding, re-measured
§11:
scripts/pr-gates.sh,tests/pr-gates.batsand.forgejo/workflows/reusable-pr-gates.ymlhave no non-ASCII line at this head. The three dashes are now-.tests/pr-gates.batsruns 29 of 29 underLC_ALL=Cand underC.UTF-8, with bats 1.11.0. UnderLC_ALL=C,4cc2982ran 28.4cc2982too. I did not read the image. Either way the arm's name is ASCII now.The notes, re-measured
coverageanddensityto default to'true'.resultto carry neither. It carries its own two mutants.Refs #1576and the §2.1 note.PR_GATES_COVERAGEdefaults to off in the script'false', both twinsfragmentsjob losesPR_GATES_COVERAGE, both twinsMeasured at the head
tests/pr-gates.bats: 29 of 29 pass.go test(30 packages at4cc2982),gitea-twin --check,fragment-checkandregister-check. The delta touches no Go source, workflow, fragment or doc.Not checked
golangci-lintandshellchecklocally, which CI runs;coverage: 'false'.Landing identity record
c9a5e6d510bcd7656c4fc3a348d5a910e3d79d47c9a5e6d510bcd7656c4fc3a348d5a910e3d79d47This is a post-merge identity record. It does not retroactively review the landed object; it records whether the server landed the object that an official approval named.
Correction to my two comments above, since they are durable and one of them is wrong.
I wrote that "18 of 18 green cannot distinguish 29 arms from 28." That is false. Review 7479 measured it: on bats 1.11.0 a lost arm prints
Executed 28 instead of expected 29and exits 1. A plan mismatch is a failure, so a greentests / batsalready proves every declared arm ran.Which means the simpler and stronger argument was available the whole time and I did not use it:
tests / batswas green, therefore the arm ran, whatever version the image carries. My read of the image at 1.11.1 is consistent with that but was never necessary — I went and checked a container because I had convinced myself the green was uninformative.What the error cost: a detour, not a wrong fix. The section 11 violation was real, the remedy was the rule rather than the reproduction, and nothing in the merged change rests on the retracted clause. I am leaving the comments in place rather than editing them, so the record reads in order.
Landed at
c9a5e6d510bcd7656c4fc3a348d5a910e3d79d47; #1576 is closed by hand with the landing record.