Release Process
This document explains how to create releases for mcpbr, both manually and via automation.
Table of Contents
- Automated Release (Recommended)
- Manual Release
- For AI Agents
- Version Management
- What Happens on Release
- Troubleshooting
Release Process (Recommended)
Workflow Overview
mcpbr uses GitHub's release drafter and automatic version bumping:
- Release Drafter automatically creates draft releases from merged PRs
- You manually publish the release in the GitHub UI
- Post-release workflow automatically bumps the version on main
Step-by-Step
1. Review the Draft Release
As you merge PRs to main, Release Drafter automatically:
- Creates/updates a draft release
- Categorizes changes (features, fixes, breaking changes)
- Generates release notes from PR titles and labels
Navigate to Releases to see the current draft.
2. Prepare the Version (if needed)
For patch releases (bug fixes, minor improvements):
- No preparation needed! The current version in
pyproject.tomlis already correct.
For minor releases (new features) or major releases (breaking changes):
- Manually update the version in
pyproject.tomlbefore publishing:
# For minor bump (0.4.1 → 0.5.0)
sed -i 's/^version = "0.4.1"/version = "0.5.0"/' pyproject.toml
python3 scripts/sync_version.py
git add pyproject.toml package.json .claude-plugin/
git commit -m "chore: Bump version to 0.5.0"
git push origin main
# For major bump (0.5.0 → 1.0.0)
# Same process, update to "1.0.0"
3. Publish the Release
In the Releases page:
- Click "Edit" on the draft release
- Set the tag to match the version in
pyproject.toml(e.g.,v0.4.1) - Review the auto-generated release notes
- Add any additional context or breaking change warnings
- Click "Publish release"
4. Automatic Version Bump
After you publish the release, the Post-Release Version Bump workflow automatically:
- ✅ Bumps to next patch version (e.g.,
0.4.1→0.4.2) - ✅ Syncs version across all files
- ✅ Commits and pushes to main
- ✅ Triggers PyPI and npm publication
Main branch is now ready for the next release!
Version Bump Strategy
- Patch (automatic after release): Bug fixes, minor improvements (0.4.1 → 0.4.2)
- Minor (manual before release): New features, enhancements (0.4.2 → 0.5.0)
- Major (manual before release): Breaking changes (0.5.0 → 1.0.0)
Manual Release
If you need to create a release manually, follow the same pattern as the automated workflow:
1. Tag and release the current version
# Get current version from pyproject.toml
CURRENT_VERSION=$(python -c "import tomllib; f=open('pyproject.toml','rb'); data=tomllib.load(f); print(data['project']['version'])")
# Create and push tag
git tag -a "v${CURRENT_VERSION}" -m "Release v${CURRENT_VERSION}"
git push origin "v${CURRENT_VERSION}"
# Create GitHub release
gh release create "v${CURRENT_VERSION}" \
--title "v${CURRENT_VERSION}" \
--generate-notes \
--latest
2. Bump to next version
After the release is published, bump to the next patch version:
# Calculate next version (assuming CURRENT_VERSION is set from above)
IFS='.' read -r major minor patch <<< "$CURRENT_VERSION"
NEXT_VERSION="${major}.${minor}.$((patch + 1))"
# Update pyproject.toml
sed -i "s/^version = \".*\"/version = \"$NEXT_VERSION\"/" pyproject.toml
# Sync versions across all files
python3 scripts/sync_version.py
# Commit and push
git add pyproject.toml package.json .claude-plugin/
git commit -m "chore: Bump version to ${NEXT_VERSION}"
git push origin main
This keeps the repository ready for the next release.
--notes "Release notes here"
--latest
Or use the GitHub UI at:
https://github.com/greynewell/mcpbr/releases/new
## For AI Agents
**AI agents should use the automated workflow whenever possible.** Here's the recommended workflow:
### Quick Release Workflow
```bash
# 1. Trigger the release workflow (choose patch/minor/major)
gh workflow run release.yml -f version_bump=patch
# 2. Wait for the workflow to complete (~2 minutes)
sleep 120
# 3. Verify the release was created
gh release view --json tagName,publishedAt,assets
# 4. Confirm publication to PyPI and npm
# PyPI: https://pypi.org/project/mcpbr/
# npm: https://www.npmjs.com/package/@greynewell/mcpbr
Determining Version Bump Type
Choose the bump type based on the changes:
patch: Bug fixes, documentation updates, dependency updates
- Example: Fix Docker TypeError (#290)
- Example: Update README with new examples
minor: New features, enhancements (backward compatible)
- Example: Add new benchmark support
- Example: Add CSV export functionality
major: Breaking changes, API changes
- Example: Redesign CLI interface
- Example: Remove deprecated features
Checking Current Version
# From pyproject.toml
grep '^version' pyproject.toml
# From git tags
git describe --tags --abbrev=0
# From latest release
gh release view --json tagName -q '.tagName'
Version Management
Version Sync Script
The scripts/sync_version.py script ensures all package files have the same version:
- Source of truth:
pyproject.toml - Synced files:
package.json(npm CLI package).claude-plugin/plugin.json.claude-plugin/package.json(Claude plugin).claude-plugin/marketplace.json
Pre-commit Hook
The version sync runs automatically on commit via .pre-commit-config.yaml:
- id: sync-version
name: Sync version across project files
entry: python3 scripts/sync_version.py
language: system
pass_filenames: false
files: pyproject.toml
stages: [pre-commit]
What Happens on Release
When a release is published (tag pushed or GitHub release created):
1. PyPI Publication (publish.yml)
- Builds Python package
- Publishes to https://pypi.org/project/mcpbr/
2. npm Publication (publish-npm.yml)
Publishes 4 packages:
@greynewell/mcpbr- Scoped CLI packagemcpbr-cli- Unscoped CLI package@greynewell/mcpbr-claude-plugin- Scoped Claude pluginmcpbr-claude-plugin- Unscoped Claude plugin
3. Release Drafter
- Automatically generates release notes based on merged PRs
- Groups changes by type (features, fixes, docs, etc.)
- Credits contributors
GitHub Actions Limitation
Important: When the release workflow creates a release using GITHUB_TOKEN, it doesn't automatically trigger the PyPI and npm publish workflows. This is a GitHub Actions security feature to prevent recursive workflow triggers.
Workaround: After running the release workflow, manually trigger the publish workflows:
# After release workflow completes
gh workflow run publish.yml -f tag=v0.3.25
gh workflow run publish-npm.yml -f tag=v0.3.25
Alternative: Use a Personal Access Token (PAT) in the release workflow instead of GITHUB_TOKEN (not implemented yet, but possible future enhancement).
Troubleshooting
Version Mismatch Error
If you see "version does not match release tag" during npm publish:
# Sync versions
python3 scripts/sync_version.py
# Verify all versions match
grep '"version"' package.json .claude-plugin/package.json
grep '^version' pyproject.toml
Failed PyPI Upload
If PyPI upload fails:
- Check if the version already exists on PyPI
- Bump to the next version
- Delete the failed release and tag
- Retry with new version
# Delete failed release
gh release delete v0.3.25 --yes
# Delete tag locally and remotely
git tag -d v0.3.25
git push origin :refs/tags/v0.3.25
# Bump version and retry
Failed npm Upload
If npm upload fails:
- Check npm token is valid
- Verify package names are available
- Check package.json structure
# Test npm package locally
cd /tmp
npm pack /path/to/mcpbr
tar -tzf greynewell-mcpbr-*.tgz
Release Draft Not Found
The automated workflow looks for a draft release created by Release Drafter. If none exists:
- The workflow will create a release with basic notes
- You can add custom notes via the
release_notesinput
Git Push Permission Denied
If the workflow fails to push:
- Ensure
GITHUB_TOKENhascontents: writepermission - Check branch protection rules allow the bot to push
Best Practices
- Always use semantic versioning: MAJOR.MINOR.PATCH
- Use automated workflow to avoid manual errors
- Test releases on TestPyPI/npm dry-run first (if critical)
- Update CHANGELOG.md if maintained separately
- Verify publications after release completes
- Never delete published releases unless absolutely necessary
Examples
Example 1: Bug Fix Release
# PR #290 fixed a Docker TypeError - this is a patch
gh workflow run release.yml -f version_bump=patch
# Result: 0.3.24 → 0.3.25
Example 2: New Feature Release
# Added SWE-Bench Lite support - this is a minor feature
gh workflow run release.yml -f version_bump=minor
# Result: 0.3.24 → 0.4.0
Example 3: Breaking Change Release
# Redesigned CLI interface - breaking change
gh workflow run release.yml \
-f version_bump=major \
-f release_notes="⚠️ Breaking: CLI commands have been reorganized. See migration guide."
# Result: 0.3.24 → 1.0.0
Quick Reference
| Task | Command |
|---|---|
| Check current version | grep '^version' pyproject.toml |
| Sync versions | python3 scripts/sync_version.py |
| Patch release | gh workflow run release.yml -f version_bump=patch |
| Minor release | gh workflow run release.yml -f version_bump=minor |
| Major release | gh workflow run release.yml -f version_bump=major |
| View latest release | gh release view |
| List all releases | gh release list |
| Delete release | gh release delete v0.3.25 --yes |
For questions or issues, please open an issue on GitHub.