Skip to content

fix(release): rerun bin/release once when the release brings a newer one - #545

Merged
leemour merged 1 commit into
mainfrom
fix/release-rerun
Oct 16, 2026
Merged

leemour merged 1 commit into
mainfrom
fix/release-rerun

Conversation

@leemour

@leemour leemour commented Oct 16, 2026

Copy link
Copy Markdown
Collaborator

Task

Port WireCatLabs/cli-base#173 here. bin/release folds the changelog with cli-dev changelog fold --land. That call fast-forwards main, even when it has nothing to fold. If the update changes bin/release, sh goes on reading the file from the byte it had reached, so the rest of the run is a mix of old and new text.

What

  • bin/release hashes itself at start. After the fold, if the file changed, it re-execs ./bin/release with the same arguments.
  • WIRECAT_RELEASE_RERUN allows one re-exec. A second change stops the run with bin/release changed again while releasing — run it again.
  • The restart is ./bin/release, relative to the repository root the script has already cd'd to, not "$0": $0 is wrong after cd when the script was started from another folder by a relative path.
  • The release lock: the second run takes it again. exec keeps the PID and the inherited fd 9; wirecat_release_lock reopens fd 9 and calls flock again.
  • The same check runs after the version raise through land(), which also fast-forwards main.
  • The earlier restart after git merge --ff-only origin/main used exec "$0"; it now uses exec ./bin/release too.
  • The second run does no extra work: the fold finds nothing to fold, and scripts/next-version.mjs returns the version already raised, so land() is not called again.
  • CHANGELOG entry under Unreleased / Fixed.

Testing

  • sh -n bin/release; pnpm lint, pnpm docs:lint, pnpm standards:check, plus pnpm docs:check where the repository has it. No tests cover bin/release.
  • A stand-in script in a temp git repo uses this repository's real rerun_if_changed block and config/wirecat/release-lock.sh with flock. The stand-in fold fast-forwards one queued commit, and the run starts from elsewhere/deeper as ../../repo/bin/release --local:
    • bin/release changed once: exactly one re-exec, --local reaches the second run, the lock is taken again, and a separate flock -n is refused (exit 75);
    • changed again during the second run: it stops with exit 1;
    • only CHANGELOG.md changed: no re-exec;
    • the old exec "$0" form, same start: exec: ../../d/bin/release: not found, exit 127.
  • Not run: a real release.

🤖 Generated with Claude Code

The changelog fold (cli-dev changelog fold --land) fast-forwards main, and so
does the version raise through land() where the script has one. sh reads
bin/release as it goes, so a newer bin/release on main ran half old, half new.

bin/release now hashes itself at start and, after those steps, re-execs
./bin/release with the same arguments if the file changed. WIRECAT_RELEASE_RERUN
allows one re-exec; a second change stops with "run it again". The restart uses
./bin/release from the repository root, not "$0", which is wrong after cd when
the script was started from another folder by a relative path. The release lock
is taken again by the second run. Same fix as WireCatLabs/cli-base#173.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@leemour
leemour merged commit 64c628d into main Oct 16, 2026
12 checks passed
@leemour
leemour deleted the fix/release-rerun branch October 16, 2026 17:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant