Skip to content

chore: harden the release script - #159

Merged
twk3 merged 2 commits into
mainfrom
chore/harden-release-script
Oct 28, 2026
Merged

twk3 merged 2 commits into
mainfrom
chore/harden-release-script

Conversation

@twk3

@twk3 twk3 commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

script/release here is the stock actions/typescript-action template, and nothing references it — not the README, not an npm script, not a workflow. This ports the version currents-dev/cancel-run-gh-action arrived at after three review rounds (its PR), and adds a Releases section to the README so it stops being an orphan.

What changes

  • The version is read, not typed. The template prompts for a tag, then asks the operator to confirm by eye that package.json agrees. The version now comes out of package.json, so the tag cannot disagree with the manifest.
  • Pre-flight checks the template leaves to the operator: clean tree, on main, level with the remote, tags fetched, version is X.Y.Z — and a version that is not above the last release is refused, rather than force-moving the major tag backwards onto older code.
  • One atomic push for both tags. Separately, a rejected major tag left vX.Y.Z published with @vN still pointing at old code.
  • Reruns resume. A run that dies after tagging can be repeated: an existing tag on the current HEAD is treated as an unfinished run and the remaining steps resumed — including a releases/vN branch the remote is missing. A tag on any other commit still aborts.
  • Publishes a GitHub release with generated notes. This repo has tags but no releases today, so consumers get no changelog.

The releases/vN snapshot is kept — releases/v1 in this repo came from it — guarded against the first-release case where the template expands an empty variable into git branch releases/.

One claim worth not overstating

Latest-tag selection moves to git tag --list 'v[0-9]*.[0-9]*.[0-9]*' --sort=-v:refname. The template's git describe --abbrev=0 --match='v[0-9].[0-9].[0-9]*' is not currently broken here — v1.0.10 and v1.0.11 still match it, since the trailing * absorbs the extra digit. It breaks when a minor reaches two digits (v1.10.0), which this repo hasn't hit. Included for robustness, not to fix a live bug.

Verified

Run against a throwaway remote carrying this repo's tag layout (v1.0.9, v1.0.10, v1.0.11, v1.1.0, v1.1.5, v2.0.0, v2.1.0, moving v1/v2, and an existing releases/v1): the 2.1.0 → 2.1.1 patch release tags v2.1.1, moves v2 to it, and leaves releases/v1 untouched.

The refusal paths and the partial-failure reproductions (pre-receive hooks rejecting refs/tags/v1 and refs/heads/releases/v1) were exercised in the source PR. npx prettier@3.9.10 --check README.md passes, and the new link definition sits inside the existing markdownlint-disable MD013 block.

Relationship to #158

Independent. #158 bumps the version to 2.1.1; this changes the tooling that cuts the release. Either can merge first — they touch different files. If this lands first, #158's release is cut with the hardened script.


Generated by Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

script/release was the stock actions/typescript-action template, and nothing
referenced it - not the README, not an npm script, not a workflow. This ports
the version currents-dev/cancel-run-gh-action arrived at, after three rounds
of review there, and documents it in the README so it stops being an orphan.

What changes:

- The version comes from package.json instead of being typed at a prompt and
  confirmed by eye, so the tag cannot disagree with the manifest.
- Pre-flight checks the template leaves to the operator: clean tree, on main,
  level with the remote, tags fetched, version is X.Y.Z, and a version that
  is not above the last release is refused rather than force-moving the major
  tag backwards.
- The release tag and the major tag go up in one atomic push. Separately, a
  rejected major tag left vX.Y.Z published with @vn still on old code.
- A run that died after tagging can be repeated: an existing tag on the
  current HEAD is treated as an unfinished run and the remaining steps
  resumed, including a releases/vN branch the remote is missing. A tag on any
  other commit still aborts.
- A GitHub release is published with generated notes; this repo has tags but
  no releases today.
- Latest-tag selection uses `git tag --sort=-v:refname`, which keeps working
  once a minor reaches two digits. The template's glob still handles the
  v1.0.10 and v1.0.11 already in this repo's history; v1.10.0 is where it
  would report a stale latest.

The releases/vN snapshot the template performs is kept - releases/v1 in this
repo came from it - guarded against the first-release case where the template
expands an empty tag into `git branch releases/`.

Verified against a throwaway remote carrying this repo's tag layout, v1.0.10
and v1.0.11 included: the 2.1.0 -> 2.1.1 patch release tags v2.1.1, moves v2,
and leaves releases/v1 untouched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AfXo7y92vCvoKLLaVgj5XM
@baz-reviewer

baz-reviewer Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Review this PR on Baz

Baz Summary

Harden script/release to derive versions from package.json, validate repository state and release ordering, resume interrupted runs, and publish tags atomically with generated GitHub release notes. Document the release workflow, moving major tags, resumability, and patchable releases/vN branches in the README.

Topics

TopicDetails
Release documentation Document how to run releases, update major tags, recover failed runs, and access action versioning guidance.
Modified files (1)
  • README.md
Latest Contributors(2)
UserCommitDate
noreply@anthropic.comchore: harden the rele...October 27, 2026
dj@currents.devfeat: Add discovery ou...May 14, 2026
Release automation Harden script/release with pre-flight validation, semantic version ordering, atomic tag pushes, resumable failures, major-release branch handling, and GitHub release creation.
Modified files (1)
  • script/release
Latest Contributors(2)
UserCommitDate
noreply@anthropic.comfix: harden the releas...October 28, 2026
vCaisimInitial commitSeptember 30, 2024


Merger  Activate to get a short verdict whether this PR is good to go or not

Skills  Activate Skill Maintainer to keep your skills up to date

Planner  This PR would have been improved with Baz Planner - Try it now

Comment thread script/release Resolved
Comment thread script/release Resolved
Comment thread script/release Resolved
Three findings from review, all verified against a throwaway remote before
and after:

- A release candidate blocked its own final. sort -V ranks v2.1.1-rc.1
  above v2.1.1, and the glob admitted it, so a stray rc left on any branch
  became latest_tag and the monotonic check refused 2.1.1 as "behind the
  released v2.1.1-rc.1". Only exact vX.Y.Z counts as a release now.

- A release landing while this one sat at the prompt was silently rolled
  back: the forced major-tag push clobbered it with the older commit
  fetched before the prompt. The push now carries
  --force-with-lease against the value read just before the prompt, so it
  is rejected instead, and --atomic holds the release tag back with it.

  The major tag's refspec deliberately lost its '+'. A '+' forces
  unconditionally and silently bypasses the lease - keeping it would have
  left this guard doing nothing at all.

- A local releases/vN branch was pushed as the previous major's
  maintenance line without checking it was that major. It now has to be at
  the tag, or the run stops and says so, rather than publishing some
  unrelated branch that happens to carry the name. The tags are already up
  by that point, so the fix is to correct the branch and rerun.

Not taken: restricting the scan to tags reachable from HEAD. Reachability
is what this moved away from, and a release cut from a maintenance branch
would then go uncounted - the one case the monotonic check exists to catch.

shellcheck clean, as the version before it was.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AfXo7y92vCvoKLLaVgj5XM
Comment thread script/release Resolved
@twk3
twk3 merged commit 9a79a0a into main Oct 28, 2026
27 checks passed
@twk3
twk3 deleted the chore/harden-release-script branch October 28, 2026 15:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants