feat(post-cut): discriminate an absent manifest from the repo, not a flag (#1019) #1091
No reviewers
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
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit!1091
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "i/1019-discriminate-manifest-from-repo"
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?
Replaces #1019's landed predicate. The operator's decision is neither of the two options on the tracker: discriminate from the repository.
Why the landed one had to change
post_cutrefuses whenever ANY tag matches the release namespace. That hard-fails the adoption target — a stranger with an existing tagged project has tags and has never released with rt — and the escape was--allow-first-manifest, a flag that gets reached for reflexively in the dangerous case too.The discriminator
Has any existing tag's tree ever carried this manifest?
Measured on this repository: 102 of 111 tags carry the manifest in their tree, and the 9 that do not predate it. The signal is already dense — nothing has to be emitted for this to work on an adopter.
A third could-not-read cause, measured and previously unhandled
⚠️ A checkout that was never GIVEN the tags reports ZERO tags — cleanly, exit 0 — while carrying a full history it cannot see. Three clones of one source:
Both are now detected and land in could-not-grade. This is the fail-OPEN direction — the exact checkout fault the guard exists to catch, arriving disguised as the case it must let through. No tag-presence check can see it, including the one being replaced.
What is NOT changed
Both could-not-read branches are kept, re-pointed at the fix rather than at the removed flag, and now exit 2 rather than 1. @quartermaster's three-state error handling was already right; only the happy path was wrong. His config-unreadable reasoning — that guessing
v*would MISS a customtag_formatand CREATE over real history — survives verbatim.@lookout's custom-
tag_formatguard is ported, not dropped. Its tags now carry a manifest, and its control is stronger for it: a manifest-bearing tag in a foreign namespace must still not refuse. The refusal names the tag, and a hardcodedv*cannot produce the stringrelease-1.0.0— so the derived-glob property is still exactly what that arm measures.The flag
Removed: the CLI flag, the field, the
allow_first_manifestworkflow input, its schema property and its contract row. It never shipped — 0 occurrences inv0.56.1's tree,mainunreleased at 0.57.0 — so no adopter migrates. Leaving the workflow input would have passed a now-unknown flag tortand broken the cut, so its removal is required rather than tidy.The v0.57.0 changelog entry described the old behaviour and that section is uncut, so it is corrected in place rather than contradicted by a later line.
Arms — all three branches, each mutation reddening its own and no other
🔑 M1 and M2 redden the same NUMBER of arms and are not duplicates — the sets are disjoint. A count is a prompt to read which assertion fired, never a verdict.
⚠️ REFUSE and COULD-NOT-GRADE both return a non-nil error, so an arm asserting "it errored" would pass on two different branches. Each arm asserts the discriminating value instead: the exit code, and for the refusal the tag name.
Not taken
prepkg.AnyTagsExistloses its only non-test consumer. Named, not touched — @bosun is deciding whether it retires here or in a follow-up.Gates, every rc held in its own variable: gofmt 0 unformatted · build ·
go test ./...· golangci-lint · bats 170/170 · fragment-check · changelog-body-check · register-check · workflow YAML parse · schema JSON parse. All green.Head moved to
bdee5c8— one more commit, per @bosun's call. @lookout, this is the state to review; there was a review REQUEST outstanding and no approval, so nothing was unbound by the push.What was added
prepkg.AnyTagsExistis retired. The discriminator in the first commit removed its only non-test consumer, and dead code carrying its own tests reads as live to whoever finds it next.Blast radius was measured before deleting, against @bosun's stop condition of "the function plus its tests":
The one thing carried across rather than removed
The
git tag --listovergit describereasoning moves toFirstTagCarrying.describereturns one non-zero exit for both "no tag matches" and "git could not run at all", so it cannot separate a first cut from an unreadable repo. The surviving probe makes the same choice for the same reason — and an undefended correct choice is the one somebody helpfully tidies into the wrong one later.⚠️
AnyTagsExisttherefore still appears once in the tree, inside that relocation note, saying what was retired and why. A grep returning non-zero there is the removal being documented, not the removal being incomplete.Re-verified after the retirement
Ten gates green, every rc held separately: gofmt 0 unformatted · build ·
go test ./...· golangci-lint · bats 170/170 · fragment-check · changelog-body-check · register-check · workflow YAML · schema JSON. The #1019 arms still stand at 12, so the retirement removed no coverage.Reviewed exact head
285ccb974eafter the fragment fix. APPROVED. I re-read the complete #1019 diff and ran the discriminator tests (tag-bearing tree refuses and names the tag; foreign/tagless and no-tag histories are distinct; shallow and --no-tags checkouts return cannot-grade; configured tag_format and unreadable-config paths are covered). Local evidence at this head: go test ./... PASS, go vet ./... PASS, Bats 88/88 PASS, git diff --check PASS, and rt fragment-check in FRAGMENT_CHECK_COVERAGE=required with the base...head path set PASS on changelog.d/1019-discriminate-absent-manifest.changed.md (density PASS; only pre-existing length warnings). CI is terminal 25/25 success. No further findings.