Release Management
GitHub release workflow with semantic versioning, changelogs, and release automation using gh CLI. Use when creating releases, tagging versions, or publishing changelogs.
Auto-activated — this skill loads automatically when Claude detects matching context.
Release Management
Automate releases with gh release, semantic versioning, and changelog generation.
CRITICAL: Task Management is MANDATORY (CC 2.1.16)
BEFORE doing ANYTHING else, create tasks to track progress:
# 1. Create main task IMMEDIATELY
TaskCreate(
subject="Release: {version}",
description="Creating release with semantic versioning and changelog",
activeForm="Releasing {version}"
)
# 2. Create subtasks for each release phase
TaskCreate(subject="Version & changelog", activeForm="Determining version and generating changelog")
TaskCreate(subject="Create release", activeForm="Creating GitHub release")
TaskCreate(subject="Verify & announce", activeForm="Verifying release and announcing")
# 3. Set dependencies for sequential phases
TaskUpdate(taskId="3", addBlockedBy=["2"])
TaskUpdate(taskId="4", addBlockedBy=["3"])
# 4. Before starting each task, verify it's unblocked
task = TaskGet(taskId="2") # Verify blockedBy is empty
# 5. Update status as you progress
TaskUpdate(taskId="2", status="in_progress") # When starting
TaskUpdate(taskId="2", status="completed") # When doneQuick Reference
Create Release
# Auto-generate notes from PRs
gh release create v1.2.0 --generate-notes
# With custom title
gh release create v1.2.0 --title "Version 1.2.0: Performance Update" --generate-notes
# Draft release (review before publishing)
gh release create v1.2.0 --draft --generate-notes
# Pre-release (beta, rc)
gh release create v1.2.0-beta.1 --prerelease --generate-notes
# With custom notes
gh release create v1.2.0 --notes "## Highlights
- New auth system
- 50% faster search"
# From notes file
gh release create v1.2.0 --notes-file RELEASE_NOTES.mdList & View Releases
# List all releases
gh release list
# View specific release
gh release view v1.2.0
# View in browser
gh release view v1.2.0 --web
# JSON output
gh release list --json tagName,publishedAt,isPrereleaseVerify Releases (gh CLI 2.86.0+)
# Verify release attestation (sigstore)
gh release verify v1.2.0
# Verify specific asset
gh release verify-asset v1.2.0 ./dist/app.zip
# Verify with custom trust policy
gh release verify v1.2.0 --owner myorgManage Releases
# Edit release
gh release edit v1.2.0 --title "New Title" --notes "Updated notes"
# Delete release
gh release delete v1.2.0
# Upload assets
gh release upload v1.2.0 ./dist/app.zip ./dist/app.tar.gzSemantic Versioning
MAJOR.MINOR.PATCH
│ │ │
│ │ └── Bug fixes (backwards compatible)
│ └──────── New features (backwards compatible)
└────────────── Breaking changes
Examples:
1.0.0 → 1.0.1 (patch: bug fix)
1.0.1 → 1.1.0 (minor: new feature)
1.1.0 → 2.0.0 (major: breaking change)
Pre-release:
2.0.0-alpha.1 (early testing)
2.0.0-beta.1 (feature complete)
2.0.0-rc.1 (release candidate)Release Workflows
Standard and hotfix release procedures using git tags and gh release.
Load Read("${CLAUDE_SKILL_DIR}/references/release-workflows.md") for step-by-step standard and hotfix release workflows.
Changelog Generation
Auto-generated from PRs, custom .github/release.yml templates, and manual CHANGELOG.md format.
Load Read("${CLAUDE_SKILL_DIR}/references/changelog-generation.md") for changelog template examples and Keep-a-Changelog format.
Release Automation & Checklist
GitHub Actions workflow for tag-triggered releases, version bumping script, and pre/post-release checklist.
Load Read("${CLAUDE_SKILL_DIR}/references/release-automation.md") for CI workflow, bump script, and release checklist.
Best Practices
- Use semantic versioning - Communicate change impact
- Draft releases first - Review notes before publishing
- Generate notes from PRs - Accurate, automatic history
- Close milestone on release - Track completion
- Tag main only - Never tag feature branches
- Announce breaking changes - Prominent in release notes
Related Skills
ork:github-operations: Milestones, issues, and CLI referenceork:github-operations: Branch management and git operations
References
Load on demand with Read("$\{CLAUDE_SKILL_DIR\}/references/<file>"):
| File | Content |
|---|---|
semver.md | Semantic versioning rules and decision tree |
release-workflows.md | Standard and hotfix release procedures |
changelog-generation.md | Auto-generated, template, and manual changelog formats |
release-automation.md | GitHub Actions workflow, bump script, and checklist |
Rules (2)
Changelog must document all breaking changes with migration instructions — HIGH
Changelog Must Include All Breaking Changes
Why
Developers read changelogs before upgrading. If a breaking change is missing from the changelog, they upgrade without migration steps and hit runtime errors. After one bad experience, teams stop upgrading and fall behind on security patches.
Rule
Before publishing a release:
- Cross-reference all commits with the changelog
- Every commit with
!orBREAKING CHANGEmust appear in the changelog - Breaking changes must include migration instructions
- The Breaking Changes section must appear first in the changelog
Incorrect — incomplete changelog missing breaking changes
# Changelog
## [2.0.0] - 2026-03-10
### Added
- Bulk export endpoint (#234)
- Dark mode support (#236)
### Fixed
- Date parser null handling (#235)Problems:
- Version is 2.0.0 (major) but no breaking changes listed
- The commit
feat!: remove /v1/users endpoint (#230)is missing - The commit
refactor!: rename User model to Account (#232)is missing - No migration instructions for breaking changes
Correct — complete changelog with migration instructions
# Changelog
## [2.0.0] - 2026-03-10
### BREAKING CHANGES
- **Removed `/v1/users` endpoint** (#230): The deprecated v1 users
API has been removed. Migrate to `/v2/users` which supports
cursor-based pagination.
```diff
- GET /v1/users?page=2&limit=20
+ GET /v2/users?cursor=abc123&limit=20-
Renamed
Usermodel toAccount(#232): All database tables and API responses now useAccount. Run the migration:npm run migrate:upUpdate imports:
- import \{ User \} from "./models/user"; + import \{ Account \} from "./models/account";
Added
- Bulk export endpoint (#234)
- Dark mode support (#236)
Fixed
- Date parser null handling (#235)
## Verification Script
```bash
#!/bin/bash
LAST_TAG=$(gh release view --json tagName -q .tagName)
# Find all breaking change commits
BREAKING=$(git log "$LAST_TAG"..HEAD --oneline --format="%s" \
| grep -E '!:|BREAKING CHANGE')
if [ -z "$BREAKING" ]; then
echo "No breaking changes found"
exit 0
fi
echo "Breaking changes to verify in CHANGELOG.md:"
echo "$BREAKING" | while IFS= read -r commit; do
# Extract PR number if present
PR=$(echo "$commit" | grep -oE '#[0-9]+' | head -1)
if [ -n "$PR" ] && ! grep -q "$PR" CHANGELOG.md; then
echo " MISSING: $commit"
else
echo " OK: $commit"
fi
doneChangelog Section Order
| Section | Required When | Position |
|---|---|---|
| BREAKING CHANGES | Any ! or BREAKING CHANGE commit | First |
| Deprecated | Deprecation notices | Second |
| Added | New features | Third |
| Changed | Behavior changes | Fourth |
| Fixed | Bug fixes | Fifth |
| Security | CVE patches | Sixth |
Validate that semantic version bump matches the actual scope of changes — HIGH
Validate Version Bump Matches Change Scope
Why
Semantic versioning is a contract with consumers. A breaking API change shipped as a patch version (1.2.3 -> 1.2.4) causes runtime failures for anyone pinned to ^1.2.3. A bug fix shipped as major (1.2.3 -> 2.0.0) forces unnecessary migration work.
Rule
Before tagging a release:
- List all commits since the last release
- Classify each commit as patch/minor/major based on its impact
- The version bump must match the highest-impact commit
- Breaking changes require major bump — no exceptions
Incorrect — bump version without checking changes
# Blindly bump patch without reviewing commits
CURRENT="1.2.3"
NEW="1.2.4" # Assumed patch
git tag -a "v$NEW" -m "Release v$NEW"
git push origin "v$NEW"
gh release create "v$NEW" --generate-notes
# But commits since v1.2.3 include:
# - "feat!: remove deprecated /v1/users endpoint" (BREAKING)
# - "feat: add /v2/users with pagination" (MINOR)
# - "fix: correct date parsing" (PATCH)
# Correct bump should have been MAJOR (2.0.0)Correct — classify commits then determine bump
#!/bin/bash
LAST_TAG=$(gh release view --json tagName -q .tagName)
echo "Commits since $LAST_TAG:"
# Classify commits
MAJOR=0; MINOR=0; PATCH=0
while IFS= read -r msg; do
if echo "$msg" | grep -qE '^(feat|fix|refactor)(\(.+\))?!:|^BREAKING'; then
MAJOR=$((MAJOR + 1))
echo " MAJOR: $msg"
elif echo "$msg" | grep -qE '^feat(\(.+\))?:'; then
MINOR=$((MINOR + 1))
echo " MINOR: $msg"
else
PATCH=$((PATCH + 1))
echo " PATCH: $msg"
fi
done < <(git log "$LAST_TAG"..HEAD --oneline --format="%s")
# Determine correct bump
if [ "$MAJOR" -gt 0 ]; then
echo "Required bump: MAJOR ($MAJOR breaking changes)"
elif [ "$MINOR" -gt 0 ]; then
echo "Required bump: MINOR ($MINOR new features)"
else
echo "Required bump: PATCH ($PATCH fixes)"
fiClassification Guide
| Commit Pattern | Bump | Example |
|---|---|---|
fix: | PATCH | fix: handle null in date parser |
docs:, chore:, ci: | PATCH | docs: update API reference |
feat: | MINOR | feat: add bulk export endpoint |
feat!: or BREAKING CHANGE: | MAJOR | feat!: remove v1 API endpoints |
refactor!: | MAJOR | refactor!: rename User to Account |
Pre-Release Validation
# Before creating the release, verify:
echo "=== Pre-Release Checklist ==="
echo "1. Last release: $LAST_TAG"
echo "2. Commits since: $(git rev-list "$LAST_TAG"..HEAD --count)"
echo "3. Breaking changes: $MAJOR"
echo "4. New features: $MINOR"
echo "5. Fixes/chores: $PATCH"
echo "6. Proposed version: v$NEW"
echo ""
if [ "$MAJOR" -gt 0 ] && ! echo "$NEW" | grep -qE '^[0-9]+\.0\.0'; then
echo "ERROR: Breaking changes found but version is not a major bump"
exit 1
fiReferences (4)
Changelog Generation
Changelog Generation
Auto-Generated (from PRs)
# GitHub auto-generates from merged PRs
gh release create v1.2.0 --generate-notes
# Output includes:
# ## What's Changed
# * feat: Add user auth by @dev in #123
# * fix: Login redirect by @dev in #124
# * docs: Update README by @dev in #125Custom Changelog Template
Create .github/release.yml:
changelog:
categories:
- title: "Breaking Changes"
labels:
- "breaking"
- title: "New Features"
labels:
- "enhancement"
- "feature"
- title: "Bug Fixes"
labels:
- "bug"
- "fix"
- title: "Documentation"
labels:
- "documentation"
- title: "Other Changes"
labels:
- "*"Manual CHANGELOG.md
# Changelog
## [1.3.0] - 2026-01-15
### Added
- User authentication system (#123)
- Dark mode support (#125)
### Changed
- Improved search performance (#126)
### Fixed
- Login redirect loop (#124)
### Security
- Updated dependencies for CVE-2026-1234Release Automation
Release Automation
GitHub Actions Release Workflow
# .github/workflows/release.yml
name: Release
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: npm run build
- name: Create Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release create ${{ github.ref_name }} \
--generate-notes \
./dist/*.zipVersion Bumping Script
#!/bin/bash
# bump-version.sh
CURRENT=$(gh release view --json tagName -q .tagName | sed 's/v//')
IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT"
case $1 in
major) NEW="$((MAJOR + 1)).0.0" ;;
minor) NEW="$MAJOR.$((MINOR + 1)).0" ;;
patch) NEW="$MAJOR.$MINOR.$((PATCH + 1))" ;;
*) echo "Usage: $0 [major|minor|patch]"; exit 1 ;;
esac
echo "Bumping $CURRENT -> $NEW"
git tag -a "v$NEW" -m "Release v$NEW"
git push origin "v$NEW"
gh release create "v$NEW" --generate-notesUsage:
./bump-version.sh patch # 1.2.3 -> 1.2.4
./bump-version.sh minor # 1.2.4 -> 1.3.0
./bump-version.sh major # 1.3.0 -> 2.0.0Release Checklist
## Release v1.3.0 Checklist
### Pre-Release
- [ ] All PRs merged to main
- [ ] CI/CD passing on main
- [ ] Version numbers updated in package.json/pyproject.toml
- [ ] CHANGELOG.md updated
- [ ] Documentation updated
- [ ] Milestone closed
### Release
- [ ] Tag created and pushed
- [ ] GitHub release created
- [ ] Release notes reviewed
- [ ] Assets uploaded (if applicable)
### Post-Release
- [ ] Deployment verified
- [ ] Announcement posted (if applicable)
- [ ] Next milestone createdRelease Workflows
Release Workflows
Standard Release
# 1. Ensure main is up to date
git checkout main
git pull origin main
# 2. Determine version bump
# Check commits since last release
gh release view --json tagName -q .tagName # Current: v1.2.3
git log v1.2.3..HEAD --oneline
# 3. Create and push tag
git tag -a v1.3.0 -m "Release v1.3.0"
git push origin v1.3.0
# 4. Create GitHub release
gh release create v1.3.0 \
--title "v1.3.0: Feature Name" \
--generate-notes
# 5. Close milestone if used
gh api -X PATCH repos/:owner/:repo/milestones/5 -f state=closedHotfix Release
# 1. Branch from release tag
git checkout -b hotfix/v1.2.4 v1.2.3
# 2. Fix and commit
git commit -m "fix: Critical security patch"
# 3. Tag and release
git tag -a v1.2.4 -m "Hotfix: Security patch"
git push origin v1.2.4
gh release create v1.2.4 --title "v1.2.4: Security Hotfix" \
--notes "Critical security fix for authentication bypass"
# 4. Merge fix to main
git checkout main
git cherry-pick <commit-sha>
git push origin mainSemver
Semantic Versioning Guide
Standard versioning for software releases.
Version Format
MAJOR.MINOR.PATCH[-PRERELEASE][+BUILD]
Examples:
1.0.0
2.1.3
3.0.0-alpha.1
3.0.0-beta.2+build.123When to Bump
PATCH (x.x.X)
Bug fixes, backwards compatible:
1.0.0 -> 1.0.1- Fix typo in error message
- Fix edge case bug
- Security patch (no API change)
- Performance improvement (no API change)
MINOR (x.X.0)
New features, backwards compatible:
1.0.1 -> 1.1.0- Add new function/method
- Add new optional parameter
- Deprecate (but don't remove) feature
- Add new event/hook
MAJOR (X.0.0)
Breaking changes:
1.1.0 -> 2.0.0- Remove function/method
- Change function signature
- Change return type
- Rename public API
- Change default behavior
Pre-release Versions
2.0.0-alpha.1 # Early development
2.0.0-alpha.2
2.0.0-beta.1 # Feature complete
2.0.0-beta.2
2.0.0-rc.1 # Release candidate
2.0.0-rc.2
2.0.0 # Final releasePrecedence
1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-beta < 1.0.0-rc.1 < 1.0.0Decision Tree
Is it a breaking change?
├── Yes → MAJOR bump
└── No
└── Is it a new feature?
├── Yes → MINOR bump
└── No → PATCH bumpExamples
| Change | Version Bump | Reason |
|---|---|---|
| Fix null pointer crash | 1.0.0 → 1.0.1 | Bug fix |
Add sort parameter | 1.0.1 → 1.1.0 | New feature |
Change sort to required | 1.1.0 → 2.0.0 | Breaking |
| Improve performance 2x | 1.0.0 → 1.0.1 | No API change |
| Remove deprecated method | 1.5.0 → 2.0.0 | Breaking |
| Add new endpoint | 1.0.0 → 1.1.0 | New feature |
Commands
# View current version
cat package.json | jq '.version'
# Bump with npm
npm version patch # 1.0.0 -> 1.0.1
npm version minor # 1.0.1 -> 1.1.0
npm version major # 1.1.0 -> 2.0.0
# With git tag
npm version patch -m "Release %s"
# Manual
git tag -a v1.2.3 -m "Release v1.2.3"
git push origin v1.2.30.x.x Versions
For pre-1.0 development:
- API is unstable
- MINOR can include breaking changes
- PATCH for any fixes/features
0.1.0 Initial development
0.2.0 Breaking changes OK
0.9.0 Approaching stable
1.0.0 First stable releaseRelease Checklist
Validates release readiness with gated checklist — build, test, count validation, changelog, version bump. Use when preparing a release.
Release Sync
Sync release content to NotebookLM and HQ Knowledge Base after tagging a new version. Reads CHANGELOG, CLAUDE.md, and hook README, then updates notebook sources and ingests to knowledge base.
Last updated on