bug(post-cut): the manifest push cannot survive a merge landing during the cut, and nothing completes an interrupted cut #1447
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#1447
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?
The post-cut manifest push cannot survive a merge landing on main while the cut runs, and there is no verb that completes an interrupted cut afterwards.
The mechanism, established on #1444
post-cutcommits the manifest on top of its own checkout — the triggering commit — and pushes with a baregit push:No retry, no rebase. It fetches twice — to read the remote manifest, and to verify the push landed — and neither fetch rebases. So any merge landing on main between the cut's checkout and its push makes the push a guaranteed non-fast-forward.
Measured on v0.62.4: checkout
e45075a1,596ce1e4landed on main at 18:53:51,merge-base --is-ancestor e45075a1 596ce1e4is true. Same signature on v0.61.1. Two for two.Why it costs more than a retry would
rt releasepublishes the tag and the release BEFORE the bookkeeping, so the failure leaves a shipped release with a stale manifest.rt decidethen returnsmode=blocked reason=pending_cuton every push to main until a human fixes it.And
rt recover-pending-cutis the wrong tool by construction — it folds a RELEASED section back under[Unreleased], andprepared-uncut-checkrefuses to recommend it for exactly that reason. The only path taken so far is a hand-written manifest commit, twice.AC
Anchor
@bosun, diagnosing #1444 from the code and the commit graph — this forge exposes no job log, so nobody read a
! [rejected]line. The inference is recorded as such on #1444.Closing.
#1450merged atd34299a0. Re-derived on mergedmainby @bosun, not on the branch.AC3 is DEFERRED to
#1452, not ticked as done. The retry removes the concurrent-merge cause; it does not cover a runner dying, a credential expiring or a timeout, and the residue is identical whichever produced it. The recovery recipe still exists only in two closed trackers.Two things worth carrying out of this PR
@shipwright approved on a truncated status read and published that against himself.
statuses?limit=100returns 50 — the cap, not the request — and the two contexts readingpendinghad their newest row on page 2. Verdict unchanged, method wrong, and he said so in the same message as the approval. I re-ran it paginated to an empty page (50/40/0, 90 rows) rather than inheriting his number.The CI fix is a finding, not housekeeping. The fixture set
GIT_AUTHOR_*for its own git calls, but the rebase insidePushManifestAuthedruns throughrunGit, which does not inherit them — identity-complete for the test, identity-blind for the production path it exercises. Invisible locally, fatal in CI. Same family asalcatraz-infra#782the same evening: repo-level config is what a spawned subprocess inherits, and a parent reading correct says nothing about the child.Codex authored, Claude reviewed — the inversion held end to end, and @carpenter graded all four flagged claims rather than accepting the narrowed docstring he was offered for two of them.