Add scripts/cut-release.sh to automate cutting a release - #562
Merged
Conversation
Until now, cutting a release meant: manually bumping Cargo.toml (in
practice, this got skipped for the last 8 releases -- v0.6.1 through
v0.6.8 were all cut with Cargo.toml still saying "0.6.0", which is
also why the SBOM's own recorded osm-diffs version has been stale
this whole time), then going to the GitHub web UI to pick a tag,
generate notes, and publish.
cut-release.sh automates the mechanical parts end to end:
1. Validates preconditions: on a clean, up-to-date main; the chosen
tag doesn't already exist; the version is actually newer than
Cargo.toml's current one; the latest CI run on main's current
HEAD is a successful "Execute unit and integration tests" run.
2. Bumps Cargo.toml's version (scoped to [package] only, doesn't
touch dependency "version = " fields) and syncs Cargo.lock's
self-entry via `cargo check`.
3. Opens a PR for that bump, enables auto-merge, and waits for it to
clear required checks and the merge queue -- main is protected
via a ruleset (pull_request + required_status_checks +
merge_queue), so this can't just push directly.
4. Once merged, creates the GitHub Release (tag + --generate-notes,
using the existing .github/release.yml categories) at the new
main HEAD.
That release tag is what triggers .github/workflows/release.yml
(build, SBOM, attest) -- completely unchanged by this script.
The only remaining manual step is deciding the version number itself
(major/minor/patch, based on whether the pipeline's output schema
changed) and running the script -- everything mechanical (the
Cargo.toml/tag/notes consistency that kept drifting) is now
enforced by construction instead of relied upon from memory.
Verified each risky piece of logic in isolation (not the full
live flow, which would create real PRs/tags/releases):
- tag-format validation against valid/invalid inputs
- the "is this version actually newer" guard, including the classic
9-vs-10 string-sort trap (0.9.0 -> 0.10.0)
- the Cargo.toml rewrite, scoped correctly to [package] only, on a
scratch copy of the real file
- `gh run list`'s JSON field names against the real repo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up from the release-process review/discussion (see #561 and the discussion around it).
Until now, cutting a release meant manually bumping
Cargo.toml(in practice this got skipped for the last 8 releases --v0.6.1throughv0.6.8were all cut withCargo.tomlstill saying0.6.0, which is also why the SBOM's own recordedosm-diffsversion has been stale this whole time), then going to the GitHub web UI to pick a tag, generate notes, and publish.cut-release.shautomates the mechanical parts end to end:main; the chosen tag doesn't already exist; the version is actually newer thanCargo.toml's current one; the latest CI run onmain's current HEAD is a successful "Execute unit and integration tests" run.Cargo.toml's version (scoped to[package]only -- doesn't touch dependencyversion =fields) and syncsCargo.lock's self-entry viacargo check.mainis protected via a ruleset (pull_request+required_status_checks+merge_queue), so it can't just push directly; confirmed this viagh api repos/.../rules/branches/main.--generate-notes, using the existing.github/release.ymlcategories) at the newmainHEAD.That release tag is what triggers
.github/workflows/release.yml(build, SBOM, attest) -- completely unchanged by this script.The only manual step left is deciding the version number itself (major/minor/patch, based on whether the pipeline's output schema changed) and running the script. Everything mechanical -- the
Cargo.toml/tag/notes consistency that kept drifting -- is now enforced by construction instead of relied on from memory. This also sets up baking the real release version into the binary later (Cargo.toml's version already becomesCARGO_PKG_VERSIONat compile time, so once that's wired into the CLI/output, it'll reflect the true release version for free).Testing
Verified each risky piece of logic in isolation, not the full live flow (which would create real PRs/tags/releases):
0.9.0->0.10.0)Cargo.tomlrewrite, scoped correctly to[package]only, on a scratch copy of the real file (dependencyversion =fields untouched)gh run list's JSON field names against the real repo🤖 Generated with Claude Code