← Back to Blog

The release PR: how a version bump goes to review

·7 min read

Releasing pyRPC is a pull request. The version bump, the lockfile sync, and the changelog entry ride a branch through the same review pipeline as any feature, because main rejects direct pushes. The release is a merge, and only then does a tag turn it into a publication.

Why a PR for a version bump

The protection on main is the load-bearing wall of the release process. It forces every change (including release machinery itself) through review and through CI. For a release, that means:

  • The bump is inspected: eleven versions, every internal range, two lockfiles, the changelog.
  • CI runs the test workflow on the bumped tree, proving the release candidate passes before it can be tagged.
  • The merge history records the release as a first-class event (Merge pull request #118 from pyrpc/release/v0.12.0) searchable and attributable.

The branch name is the plan

git checkout -b release/v0.12.0
node scripts/release.mjs 0.12.0
uv lock          # refresh uv.lock
npm install      # refresh package-lock.json
# add changelog entry
# run the test suites
git push -u origin release/v0.12.0
gh pr create ...

The branch name encodes the intent, the script does the mechanical work, the lockfile sync closes the resolution gap, and the changelog documents the user-facing meaning. The ordering matters: scripts before locks, locks before commit, tests before push.

The two-commit shape

The release branch typically lands as two commits with distinct concerns: chore: bump all packages to v0.12.0 for the mechanical version work, and docs(release): add v0.12.0 changelog entry for the prose. Separating them keeps the diff reviewable: a reviewer can verify the bump is purely mechanical and the changelog is purely editorial, each in isolation.

After merge: the tag

Merging the release PR does not publish anything. The act that triggers publication is the tag, pushed after main contains the bump:

git tag v0.12.0 origin/main
git push origin v0.12.0   # fires the publish workflow

The tag is pinned to the merged commit, so the pipeline builds exactly what was reviewed. The review gate and the publish trigger are separated in time and mechanism, you can merge without publishing, but you cannot publish without merging. That asymmetry is the safety property.

Why this scales beyond releases

Treating publication as "the tail of a reviewed merge" works because it needs no special permissions, no manual deploy step, and no human-in-the-loop at publish time, only at review time, where humans belong. Any project that publishes from tags inherits the same property: the review gate is where thought happens, and the trigger is where trust happens.

The takeaway

A release is two events, deliberately decoupled: a merge that changes the repository state, and a tag that announces it. The PR review sits on the first; the pipeline runs on the second. Version bumps deserve review not because they are complex, but because they are irreversible, and a reviewable release is a reversible mistake.