Cut a release PR
SkillAI & modelsCut a Plumber release PR that merges `develop-v2` into `production`. Prompts the user to choose the version bump (patch / minor / major), bumps the version across the root workspace and every package via `npm version`, creates a single conventional `vX.Y.Z` commit + git tag locally, and prepares (or opens) the release PR whose body summarises the changes since the last release. Use when the user asks to cut/prepare a release, make a release PR, bump the version and release, or ship develop-v2 to production.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Cut a release PR skill
What this skill tells your AI
The instructions your AI receives, as published by opengovsg/plumber in .claude/skills/cut-release-pr/SKILL.md and read by ahel’s review.
Prepare a Plumber release: merge develop-v2 → production with a version bump.
Release model (fixed for this repo):
- Head branch =
develop-v2(the trunk). The release PR is opened fromdevelop-v2directly, not from a feature branch. - Base branch =
production. - PR title =
Release vX.Y.Z. PR body = a terse bulleted summary of the changes since the previous release (one bullet per meaningful commit, keeping the conventional-commit prefix, e.g.- chore: enable Datadog continuous profiling (#1805)). - Every release is a single commit named
vX.Y.Zthat bumps the version in the rootpackage.jsonand every workspacepackage.jsonpluspackage-lock.json, taggedvX.Y.Z.
Hard rules (non-negotiable)
- Never push, and never open the PR before the branch is pushed. Pushing
develop-v2+ the tag, and shipping a production release, are owned by the human. Print the exact push commands and let the user run them. Do not rungit pushyourself. - One clean bump commit. The final commit must touch exactly the root
package.json,package-lock.json, and everypackages/*/package.json, with messagevX.Y.Z(with thevprefix). Do not leave workspace bumps uncommitted — see the gotcha below. - Never
git reset --hard(it's blocked by a deny rule anyway). Undo with a mixed reset +git checkout -- .if you need to back out a bump. - Only run
gh pr createafter confirmingorigin/develop-v2already contains the release commit (i.e. the user has pushed).
Procedure
1. Preconditions
git fetch origin production develop-v2 --quiet
git branch --show-current # must be: develop-v2
git status --porcelain # must be empty (clean tree)
git rev-parse HEAD # must equal...
git rev-parse origin/develop-v2 # ...this (local fully synced with origin)
Abort and tell the user if: not on develop-v2, the tree is dirty, or local and
origin/develop-v2 diverge. A release must be cut from a clean, fully-synced
develop-v2.
2. Summarise the changes since the last release
git log --oneline --no-merges origin/production..origin/develop-v2
This is the set of changes the release ships. Condense each commit into one PR
bullet, keeping the conventional-commit type prefix and the (#PR) number.
Exclude any existing version-bump commits (messages matching vX.Y.Z).
If the list is empty or surprisingly small, surface that to the user before
continuing — it may mean other branches still need to merge into develop-v2.
3. Prompt for the bump type
Read the current version (node -p "require('./package.json').version") and
compute what each bump resolves to. Then use the AskUserQuestion tool to ask
which bump to apply, with three options — show the resulting version in each:
- patch —
X.Y.(Z+1)— bug fixes / chores only. - minor —
X.(Y+1).0— new features, backwards-compatible. - major —
(X+1).0.0— breaking changes.
Recommend a default by scanning the step-2 commits: any breaking change →
recommend major; any feat → recommend minor; otherwise patch. Put the
recommended option first and append " (Recommended)" to its label.
4. Bump, commit, tag
Use --no-git-tag-version so npm only rewrites the version files; you create
the commit + tag so it's a single, correctly-named commit (see gotcha). Replace
<bump> with the chosen patch/minor/major:
npm version <bump> --workspaces --include-workspace-root --no-git-tag-version
NEW=$(node -p "require('./package.json').version")
git add package.json package-lock.json packages/*/package.json
git commit -m "v$NEW"
git tag "v$NEW"
5. Verify
git show --stat HEAD # expect: root package.json + every packages/*/package.json + package-lock.json; message "vX.Y.Z"
git tag --points-at HEAD # expect: vX.Y.Z
git status --porcelain # expect: empty
If anything is off (e.g. workspace bumps missing, wrong message, stray tag),
back it out with a mixed reset and retry. Step 4 creates exactly one commit, so
the pre-bump commit is always HEAD~1:
git tag -d vX.Y.Z
git reset HEAD~1 && git checkout -- .
6. Hand the push to the user
Print these for the user to run — do not run them yourself:
git push origin develop-v2
git push origin vX.Y.Z
7. Open the PR (after the user has pushed)
Confirm the release commit is on origin, and that no release PR is already open:
git fetch origin develop-v2 --quiet
git merge-base --is-ancestor HEAD origin/develop-v2 && echo pushed || echo "NOT pushed yet"
git ls-remote --tags origin "v$NEW" | grep -q . && echo "tag pushed" || echo "TAG NOT pushed yet"
gh pr list --base production --head develop-v2 --state open
Once pushed and no open PR exists, create it:
gh pr create --base production --head develop-v2 \
--title "Release vX.Y.Z" \
--body "- <bullet 1>
- <bullet 2>"
Report the PR URL back to the user.
Gotcha: npm version --workspaces quirk
npm version <bump> --workspaces --include-workspace-root (with its default git
tagging) rewrites all the package.json files in the working tree but
commits only the root package.json + lockfile, leaving the workspace bumps
uncommitted — and a global message=%s config drops the conventional v
prefix. That's why step 4 uses --no-git-tag-version and does the git add /
git commit / git tag manually: it folds every version file into one commit
with the correct vX.Y.Z message, deterministically.
Signals
- GitHub stars
- 27
- Forks
- 15
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
cut-release-pr- Source
- github.com/opengovsg/plumber