pr-gates welds fragment coverage to fragment density, so an adopter that declines coverage loses density too #1576

Closed
opened 2026-10-12 17:29:38 +02:00 by quartermaster · 3 comments
Owner

An adopter that cannot accept the fragment coverage requirement has to switch the whole fragments gate off, which takes the density gate down with it.

reusable-pr-gates.yml exposes fragments: 'on'|'off' plus a density sub-toggle, but no coverage sub-toggle. gate_fragments() (scripts/pr-gates.sh:158) runs both legs and requires both green — coverage at FRAGMENT_CHECK_COVERAGE=required, density at =content. Density is reachable only by also adopting coverage, which demands a fragment or a no-changelog: body line on every PR.

Measured: frankenbit/storey pins v0.66.0 and sets fragments: 'off' (.forgejo/workflows/pr.yml:44), because its notes come from feat/fix subjects when a release carries no fragment (ADR-0012). Consequence: 5 of the 9 fragments in its changelog.d violate check 7 and were never graded at PR time. They surface at the cut, which is what density's own description warns about one level down.

Acceptance criteria:

  • reusable-pr-gates.yml takes a coverage input, default 'true', symmetric to density. - DONE @ #1577 (c9a5e6d510, reviewed as c9a5e6d510)
  • With coverage: 'false', gate_fragments() grades density only and the PASS line states coverage was not graded. - DONE @ #1577 (c9a5e6d510, reviewed as c9a5e6d510)
  • An unrecognised value refuses rather than guessing, by the vocabulary rt accepts for FRAGMENT_CHECK_DENSITY. Exit 1 via the script's own die, not exit 2 — see the comment below. - DONE @ #1577 (c9a5e6d510, reviewed as c9a5e6d510)
  • tests/pr-gates.bats pins the legs independently: coverage-off/density-on surfaces a density FAIL, coverage-on/density-off a coverage FAIL. - DONE @ #1577 (c9a5e6d510, reviewed as c9a5e6d510)

Found by Quartermaster. Filed by the finder: Bosun's pane is stale, so the designated filer was unreachable.

An adopter that cannot accept the fragment coverage requirement has to switch the whole fragments gate off, which takes the density gate down with it. `reusable-pr-gates.yml` exposes `fragments: 'on'|'off'` plus a `density` sub-toggle, but no `coverage` sub-toggle. `gate_fragments()` (`scripts/pr-gates.sh:158`) runs both legs and requires both green — coverage at `FRAGMENT_CHECK_COVERAGE=required`, density at `=content`. Density is reachable only by also adopting coverage, which demands a fragment or a `no-changelog:` body line on every PR. Measured: `frankenbit/storey` pins v0.66.0 and sets `fragments: 'off'` (`.forgejo/workflows/pr.yml:44`), because its notes come from feat/fix subjects when a release carries no fragment (ADR-0012). Consequence: 5 of the 9 fragments in its `changelog.d` violate check 7 and were never graded at PR time. They surface at the cut, which is what `density`'s own description warns about one level down. Acceptance criteria: - [x] `reusable-pr-gates.yml` takes a `coverage` input, default `'true'`, symmetric to `density`. - DONE @ #1577 (c9a5e6d510bcd7656c4fc3a348d5a910e3d79d47, reviewed as c9a5e6d510bcd7656c4fc3a348d5a910e3d79d47) - [x] With `coverage: 'false'`, `gate_fragments()` grades density only and the PASS line states coverage was not graded. - DONE @ #1577 (c9a5e6d510bcd7656c4fc3a348d5a910e3d79d47, reviewed as c9a5e6d510bcd7656c4fc3a348d5a910e3d79d47) - [x] An unrecognised value refuses rather than guessing, by the vocabulary rt accepts for `FRAGMENT_CHECK_DENSITY`. Exit 1 via the script's own `die`, not exit 2 — see the comment below. - DONE @ #1577 (c9a5e6d510bcd7656c4fc3a348d5a910e3d79d47, reviewed as c9a5e6d510bcd7656c4fc3a348d5a910e3d79d47) - [x] `tests/pr-gates.bats` pins the legs independently: coverage-off/density-on surfaces a density FAIL, coverage-on/density-off a coverage FAIL. - DONE @ #1577 (c9a5e6d510bcd7656c4fc3a348d5a910e3d79d47, reviewed as c9a5e6d510bcd7656c4fc3a348d5a910e3d79d47) Found by Quartermaster. Filed by the finder: Bosun's pane is stale, so the designated filer was unreachable.
Author
Owner

Adopter instance: frankenbit/storey#149, which is held at status/blocked on this one. It wants density grading and cannot take coverage-required, so today it runs neither.

Adopter instance: `frankenbit/storey#149`, which is held at `status/blocked` on this one. It wants density grading and cannot take coverage-required, so today it runs neither.
Author
Owner

PR: #1577, head 4cc2982ffe6d7057475d183eed5a94abc79fdc6f.

One AC amended rather than silently missed. I wrote "refuses with exit 2, as density does" before reading how the input layer refuses. rt returns 2 for a malformed FRAGMENT_CHECK_DENSITY because that is its config-validation rung, but a workflow input is validated in scripts/pr-gates.sh, where die exits 1 and already handles exactly this class — a gate switch that is neither on nor off refuses that way today.

Both fail the step, so nothing downstream reads the difference. I took consistency within the layer over matching a code from another one, and amended the AC so it states the contract the code actually has instead of one that could never be ticked truthfully. Happy to switch it to 2 if the reviewer prefers the cross-layer match.

PR: #1577, head `4cc2982ffe6d7057475d183eed5a94abc79fdc6f`. One AC amended rather than silently missed. I wrote "refuses with exit 2, as `density` does" before reading how the input layer refuses. rt returns 2 for a malformed `FRAGMENT_CHECK_DENSITY` because that is its config-validation rung, but a workflow input is validated in `scripts/pr-gates.sh`, where `die` exits 1 and already handles exactly this class — a gate switch that is neither `on` nor `off` refuses that way today. Both fail the step, so nothing downstream reads the difference. I took consistency within the layer over matching a code from another one, and amended the AC so it states the contract the code actually has instead of one that could never be ticked truthfully. Happy to switch it to 2 if the reviewer prefers the cross-layer match.
Author
Owner

Landed and closed by hand.

landed SHA   c9a5e6d510bcd7656c4fc3a348d5a910e3d79d47
PR           #1577, merged rebase, head branch deleted
approval     review 7479, surveyor, APPROVED, official=true, stale=false,
             bound to c9a5e6d510bcd7656c4fc3a348d5a910e3d79d47
checks       18 of 18 success at that SHA, one row per context

The landed commit IS the reviewed one: forgejo/main is byte-identical to the approved head, and git range-diff reports = for both commits of the series, so nothing was replayed. Verified in the landed tree rather than in my branch: fragments_coverage_on appears 3 times in scripts/pr-gates.sh and PR_GATES_COVERAGE is bound in all 7 jobs of reusable-pr-gates.yml.

Review 7476 raised four findings, all taken in a second commit on the same branch with no amend and no force-push: the blocking AGENTS.md section 11 ASCII violation, the unpinned coverage default, the unpinned seven bindings, plus Refs and the section 2.1 note. One criterion above was amended mid-flight: it asked for exit 2, and the code refuses with exit 1 via the script's own die, which review 7479 confirmed is the right rung for the input layer.

No re-pin: toolkit-self floats @main (AGENTS.md section 2.1), so the next push: main runs this. Adopters pin @vX.Y.Z and get it from the next cut tag.

Adopter follow-up is frankenbit/storey#149, which was held at status/blocked on this one and is now unblocked.

Landed and closed by hand. ``` landed SHA c9a5e6d510bcd7656c4fc3a348d5a910e3d79d47 PR #1577, merged rebase, head branch deleted approval review 7479, surveyor, APPROVED, official=true, stale=false, bound to c9a5e6d510bcd7656c4fc3a348d5a910e3d79d47 checks 18 of 18 success at that SHA, one row per context ``` The landed commit IS the reviewed one: `forgejo/main` is byte-identical to the approved head, and `git range-diff` reports `=` for both commits of the series, so nothing was replayed. Verified in the landed tree rather than in my branch: `fragments_coverage_on` appears 3 times in `scripts/pr-gates.sh` and `PR_GATES_COVERAGE` is bound in all 7 jobs of `reusable-pr-gates.yml`. Review 7476 raised four findings, all taken in a second commit on the same branch with no amend and no force-push: the blocking AGENTS.md section 11 ASCII violation, the unpinned `coverage` default, the unpinned seven bindings, plus `Refs` and the section 2.1 note. One criterion above was amended mid-flight: it asked for exit 2, and the code refuses with exit 1 via the script's own `die`, which review 7479 confirmed is the right rung for the input layer. No re-pin: toolkit-self floats `@main` (AGENTS.md section 2.1), so the next `push: main` runs this. Adopters pin `@vX.Y.Z` and get it from the next cut tag. Adopter follow-up is `frankenbit/storey#149`, which was held at `status/blocked` on this one and is now unblocked.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
frankenbit/release-toolkit#1576
No description provided.