gtm
Go-to-market release workflow. Bumps the version, creates a release branch, pushes a GitHub release with auto-generated notes, and opens PRs into the base branch and main. Both PRs are auto-merged by default once all branch protection requirements (status checks, required reviews) are satisfied. Pass --no-auto-merge to skip auto-merge and leave PRs open for manual review.
Examples
Patch release from the default development branch:
/gtm --patchMinor release:
/gtm --minorMajor release:
/gtm --majorSpecify a different base branch:
/gtm --minor --base=developLeave PRs open for manual review instead of auto-merging:
/gtm --patch --no-auto-mergeStep 1 — Prerequisite check
Verify required tools are available:
command -v git >/dev/null 2>&1
command -v gh >/dev/null 2>&1If git is not found, print: git is not installed. Install it from https://git-scm.com and exit.
If gh is not found, print: GitHub CLI (gh) is not installed. Install it from https://cli.github.com and exit.
Verify gh is authenticated:
gh auth statusIf not authenticated, print: GitHub CLI is not authenticated. Run: gh auth login and exit.
Step 2 — Parse arguments and validate
Parse $ARGUMENTS for exactly one of: --patch, --minor, --major.
If none or more than one is provided, print:
Usage: /gtm --patch | --minor | --major [--base=<branch>] [--no-auto-merge]and exit.
Parse $ARGUMENTS for an optional --base=<branch> flag. If provided, use that value as BASE_BRANCH. If not provided, default to development.
Parse $ARGUMENTS for an optional --no-auto-merge flag. If present, set AUTO_MERGE=false; otherwise default to AUTO_MERGE=true.
Check the current branch:
git rev-parse --abbrev-ref HEADIf the current branch does not match BASE_BRANCH, automatically check it out:
git checkout <BASE_BRANCH>If the checkout fails, print:
Could not switch to branch <BASE_BRANCH>. Please resolve any issues and try again.and exit.
Verify the working tree is clean:
git status --porcelainIf there are uncommitted changes, print:
Working tree is not clean. Please commit or stash your changes before releasing.and exit.
Pull latest from remote to ensure we're up to date:
git pull --ff-onlyIf this fails (diverged history), print the error and exit.
Verify the version file exists at the project root:
test -f versionIf not found, print: No version file found in the project root. and exit.
Step 3 — Bump version and create release branch
Read the version file at the project root:
cat versionThe file contains a single line with a semantic version: MAJOR.MINOR.PATCH (e.g. 3.152.0).
Parse into components and apply the bump:
| Flag | Rule |
|---|---|
--patch | MAJOR.MINOR.(PATCH+1) |
--minor | MAJOR.(MINOR+1).0 |
--major | (MAJOR+1).0.0 |
Store the new version as NEW_VERSION (e.g. 3.153.0).
Display:
Bumping version: <OLD_VERSION> → <NEW_VERSION>Create and switch to the release branch:
git checkout -b release/v<NEW_VERSION>Write the new version to the version file:
echo "<NEW_VERSION>" > versionCommit and push:
git add version
git commit -m "Bump version to v<NEW_VERSION>"
git push -u origin release/v<NEW_VERSION>Display:
Branch release/v<NEW_VERSION> created and pushed.Step 4 — Create GitHub release
Find the most recent existing release tag to use as the comparison base:
gh release list --limit 1 --json tagName --jq '.[0].tagName'Create a new GitHub release targeting the release branch with auto-generated notes:
gh release create v<NEW_VERSION> \
--target release/v<NEW_VERSION> \
--title "v<NEW_VERSION>" \
--generate-notes \
--notes-start-tag <PREVIOUS_TAG>If there is no previous release, omit the --notes-start-tag flag.
If the release creation fails, print the error output and exit. Do not continue to PR creation if the release was not created successfully.
Display:
GitHub release v<NEW_VERSION> created.Step 5 — Create PR into base branch
gh pr create \
--base <BASE_BRANCH> \
--head release/v<NEW_VERSION> \
--title "Bump version to v<NEW_VERSION>" \
--body "Merge release branch back into <BASE_BRANCH> after v<NEW_VERSION> release."If PR creation fails (e.g. branch protection, permissions), print the error and continue to Step 6 — do not exit, as the main PR may still succeed.
Capture and display the PR URL:
PR created: <URL> (release → <BASE_BRANCH>)If AUTO_MERGE=true and the PR was created successfully, enable auto-merge:
gh pr merge <URL> --auto --mergeIf this fails, print the error as a warning but do not exit:
Warning: auto-merge could not be enabled for PR → <BASE_BRANCH>: <error>Step 6 — Create PR into main
gh pr create \
--base main \
--head release/v<NEW_VERSION> \
--title "Release v<NEW_VERSION>" \
--body "Production release of v<NEW_VERSION>."If PR creation fails, print the error and continue to Step 7.
Capture and display the PR URL:
PR created: <URL> (release → main)If AUTO_MERGE=true and the PR was created successfully, enable auto-merge:
gh pr merge <URL> --auto --mergeIf this fails, print the error as a warning but do not exit:
Warning: auto-merge could not be enabled for PR → main: <error>Step 7 — Summary
Print a summary:
+----------------------------------------------+
| Release v<NEW_VERSION> — Complete |
+---------------------+------------------------+
| Version | <OLD> → <NEW_VERSION> |
| Branch | release/v<NEW_VERSION> |
| GitHub Release | v<NEW_VERSION> |
| PR → <BASE_BRANCH> | <URL> |
| PR → main | <URL> |
| Auto-merge | enabled / disabled |
+---------------------+------------------------+If either PR failed, show FAILED instead of the URL in the summary. If AUTO_MERGE=true but auto-merge could not be enabled for a PR, show the URL followed by (auto-merge failed).
Switch back to the base branch:
git checkout <BASE_BRANCH>