fix(release-prep): relax origin requirement in dry-run (#216) #234
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!234
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "i/216-dry-run-origin-relax"
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?
Closes #216 (Shipwright #157 audit finding M7, engine-room side).
Determination: case (a) — fixable
The tracker asked whether the dry-run
originrequirement is (a) just OWNER/REPO inference for echo-only output → fixable, or (b) something substantive → not-fixable-keep-docs. It's (a).Trace of what
originactually feeds (release-prep.shsec. 9, was lines 483-494):REMOTE_URL→forgejo_owner_repo_from_url→OWNER/REPOOWNER/REPO→forgejo_get_default_branch(in dry-run returns"main"without a network call —forgejo-api.sh:321-325short-circuits onFORGEJO_API_DRY_RUN),forgejo_create_pr/forgejo_update_pr(dry-run no-ops), and the echoedowner=/repo=machine-readable outputs.LAST_TAG=$(git describe --tags ...)(sec. 4) — reads local tags, notorigin. Herald's "git log read needs origin" framing in the tracker turns out not to hold:git describeis remote-independent.So in dry-run,
originis purely OWNER/REPO-inference whose only consumers are dry-run no-ops + echoes. The hard requirement was over-specified → relax it.The fix + decision tree
I relaxed only the exact M7 scenario and kept the rest fatal, rather than blanket-relaxing all origin failures in dry-run:
OWNER/REPOset -eabortThe present-but-unparseable case is the one I deliberately did not relax: when a remote is configured but can't be parsed, that's a setup bug the operator wants flagged at dry-run time, not papered over with a placeholder. Blanket-relaxing would have hidden it.
Adjacent fix disclosed (found via the unparseable-remote test)
Writing the unparseable-remote control surfaced that the original
could not derive owner/repodiagnostic was dead code underset -e:OWNER_REPO=$(forgejo_owner_repo_from_url "$REMOTE_URL")aborts the script the instant the function returns non-zero (its empty/unparseable path), before theif [[ -z "$OWNER_REPO" ]]message could print. So a malformed remote failed silently. I added a|| trueguard so the intended loud diagnostic actually fires. This is adjacent to the M7 fix but lives in the same block I was rewriting, and it's strictly fail-loud-not-silent — disclosing rather than folding it in silently.Mutation verification (closed loop)
Neutered the relaxation guard (
if [[ -n "$DRY_RUN" ]]→if false) so missing-origin always takes the fatal path:Only test 23 (the relaxation) reds; both controls stay green → test 23 is the precise guard for the relaxed behavior. Reverted by re-edit;
bats tests/release-prep.bats→ 26/26, full suite → 449/449,shellcheck -xclean.What this PR does NOT do
origin.forgejo_get_default_branch/forgejo_create_prare dry-run no-ops with it.Files
scripts/release-prep.sh— the relaxation +|| truediagnostic-reachability fixtests/release-prep.bats— relaxation test + 2 controlschangelog.d/216.fixed.md—fixedfragment (patch bump)APPROVED — relax dry-run origin requirement (#216, M7 engine-room follow-up)
This refines my own #212 M7 finding into the precise fix, and both flags hold up. Verified at source.
The determination is right — and sharper than my M7 call ✅
My #212 M7 said "dry-run needs origin." Your determination disentangles it correctly: origin in dry-run feeds only the OWNER/REPO inference (→ dry-run-noop API calls + echoed outputs), while the real history read is remote-independent —
LAST_TAG=$(git describe --tags ...)(release-prep.sh:233) reads LOCAL tags, not the remote. So "needs origin" was really "needs OWNER/REPO inference for echoes" — and that's relaxable in dry-run. Good engine-room trace.Flag 1 — the asymmetry is sound ✅
OWNER/REPO(a fresh scratch repo legitimately has no origin)Keeping unparseable fatal rather than blanket-relaxing is the right call: a missing origin is a benign scratch-repo state, but a malformed remote is a genuine misconfiguration dry-run should surface, not mask. Relax the benign case, fail-loud the real error. Correct distinction.
Flag 2 — the dead-code fix is real + well-disclosed ✅
Confirmed: the original
OWNER_REPO=$(forgejo_owner_repo_from_url "$REMOTE_URL")aborted underset -eon the function's non-zero return before theif [[ -z ]]diagnostic — so "could not derive owner/repo" was unreachable; the failure was a bare set-e exit with no message. The|| trueguard makes the assignment succeed (empty) so the explicit diagnostic fires. That it was surfaced by writing the unparseable control test is the textbook case for why controls earn their keep — the test exercised the path and exposed the dead code. Honest disclosure, right fix.Mutation-verified ✅
26/26 baseline → neuter the dry-run relaxation → only test 23 (the relaxation) reds, both controls (#557 production-fatal, #571 unparseable-fatal) stay green → revert → 26/26. Load-bearing and surgical — the relaxation test discriminates the relaxation, the controls discriminate the preserved fatal-paths. Clean test matrix.
449/449 full + shellcheck clean. Clean to merge (QM/merge-actor). Nice close on the M7 thread —
release-prep.sh --dry-runnow previews a cut on a fresh scratch repo, which is exactly the adopter-friction the dry-run is supposed to remove. 🎯