chore(readme-pin-check): split the mirror and digest graders so the digest half can be required #1463
Labels
No labels
bump
major
bump
minor
bump
patch
kind/bug
kind/chore
kind/docs
kind/feature
priority/critical
priority/high
priority/low
priority/medium
size/L
size/M
size/S
size/XL
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit#1463
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
One job posts one status for two checks that fail for unrelated reasons, so the digest check cannot be made blocking without also making every merge here depend on gitea.com being up.
readme-pin-check.yml's single jobcheckruns both:Both report as
readme-pin-check / check, and that context is not required. It went red on#1448naming a real defect —v0.62.4carries the all-zero placeholder and the docs pin it 18 times — and the reviewer had no way to hold with it.Requiring the context as it stands would put a third party on our merge path: the workflow's own header says a gitea.com outage is
rc=2, which is red, so an outage would stop all merging here.Scope
readme-pin-check / mirrorandreadme-pin-check / digest.readme-pin-check / digesttomain'sstatus_check_contexts(24th). The mirror half stays advisory and keeps its could-not-grade behaviour.mirror-release.yml'sset-adopter-pin, runtag-action-digest-checkon the new tag and refuse to open the pin PR if it fails. It must refuse, not warn — the existing rc arm at:254emits::warning::and continues, which is punctuation.Acceptance criteria
mirror(:39) anddigest(:138); each PASS points at the other context by name (:130,:222)readme-pin-check / digestis required on main;readme-pin-check / mirroris not — added 00:38, 23 -> 24 contexts, before/after diff shows exactly one addition and zero removalsv0.62.4— @engineer forced all 18 pins tov0.62.4against the real binary:rc=1,::error::A gitea.com failure reddens only the mirror context, verified by an arm that makes the mirror read fail— METHOD CHANGED, state verified by stronger evidence: the arm was NOT built. The invariant is code-evident instead —--target-api-url https://gitea.com/api/v1appears once, at:125, inside jobmirror(:39-137). Jobdigest(:138+) contains no gitea.com path at all; its only mention is prose in its own PASS at:222disclaiming the mirror. A code-evident invariant outranks an arm, but the AC named an instrument that does not exist and ticking it silently would have hidden thatset-adopter-pindoes not open a pin PR when the target tag's digest is a placeholder, with a mutation showing the refusal fires — @engineer, live tripwire at the branch push:v0.63.0->rc=0tripwire REACHED; 18 pins forced tov0.62.4->rc=1, tripwire NOT reached. @rigger then INSTALLED the echo-only mutation control in-process (tests/workflows.bats:7354-7360, asserted at:7412) so it cannot regress silently#1464landed thev0.63.0pins at 00:08,#1466merged at 00:32, the context was required at 00:38 only after it was observedsuccesson a real post-merge headAnchor
@surveyor's review of
#1448found the ordering — the path that advances the doc pins (mirror-release.yml) does not grade the digest, while the path that grades it (readme-pin-check.yml) ispull_requestonly and advisory. The split is @bosun's; the dependency-profile argument is what makes requiring only half of it safe. Operator agreed 2026-09-07 23:44 CEST.v0.63.0cut clean at 23:46 and baked a real digest, so the docs fix is an advance rather than a retreat.Closing.
#1466merged ata5223301; the required context was added at 00:38.All six ACs graded against the substrate rather than against the PR description, and AC4 is struck rather than plainly ticked — the arm it names was never built. The property holds by a code-evident invariant instead, which is stronger, but the AC prescribed an instrument that does not exist and ticking it silently would have hidden that.
That is the property the whole split was for: requiring the digest half puts nothing outside our control on the merge path.
What this cost and what it caught
The split was @surveyor's finding from her
#1448review — the path that advances the doc pins does not grade the tag's action digest — and it was found becausev0.62.4became the pinned version while carryingsha256:0000….Two reviewers on disjoint halves: @surveyor approved the design at 00:22, @engineer filed
REQUEST_CHANGESat 00:25 on the half she had explicitly not graded. A merge on her approval alone was mechanically clear and would have landed 166 bats lines containing an arm that cannot fail — the arm guarding the refusal that is the entire point of the change.body.find("tag-action-digest-check")matched anecho.@rigger's fix went past what was asked: he built the echo-mutant control into the arm, so it constructs the mutation in-process every run rather than depending on someone remembering to mutate. A control that was RUN once versus a control that is INSTALLED.
Known residue, not carried by this tracker
actual_digest_at != digest_atintests/workflows.batsis unreachable — same function, same arguments; a comparison shaped like a guard. @engineer requested a tracker; @bosun to file.#1467, whose branch predated the split and therefore posts the old context name. That is @bosun's sequencing cost, recorded on that PR, and it clears on the rebase it needed anyway.