Files
beads/RELEASING.md
Steve Yegge fc71d4e192 Add integration tests and release documentation for npm package
Integration Tests:
- Comprehensive test suite covering all major functionality
- 5 test scenarios: installation, binary functionality, workflow,
  Claude Code for Web simulation, platform detection
- Tests JSONL import/export across sessions
- Tests all major commands (init, create, list, show, update, close, ready)
- All tests passing 

Testing Documentation:
- TESTING.md with complete test documentation
- Describes unit vs integration tests
- Manual testing scenarios
- CI/CD recommendations
- Troubleshooting guide

Release Documentation:
- RELEASING.md with comprehensive release process
- Covers all distribution channels: GitHub, Homebrew, PyPI, npm
- Step-by-step instructions for each channel
- Version numbering and release cadence
- Hotfix and rollback procedures
- Automation opportunities with GitHub Actions

npm Package Updates:
- Added test:integration and test:all scripts
- Integration tests validate real-world usage patterns
- Tests simulate Claude Code for Web SessionStart hooks

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 11:54:37 -08:00

12 KiB

Release Process for Beads

This document describes the complete release process for beads, including GitHub releases, Homebrew, PyPI (MCP server), and npm packages.

Table of Contents

Overview

A beads release involves multiple distribution channels:

  1. GitHub Release - Binary downloads for all platforms
  2. Homebrew - macOS/Linux package manager
  3. PyPI - Python MCP server (beads-mcp)
  4. npm - Node.js package for Claude Code for Web (@beads/bd)

Prerequisites

Required Tools

  • git with push access to steveyegge/beads
  • goreleaser for building binaries
  • npm with authentication (for npm releases)
  • python3 and twine (for PyPI releases)
  • gh CLI (GitHub CLI, optional but recommended)

Required Access

  • GitHub: Write access to repository and ability to create releases
  • Homebrew: Write access to steveyegge/homebrew-beads
  • PyPI: Maintainer access to beads-mcp package
  • npm: Member of @beads organization

Verify Setup

# Check git
git remote -v  # Should show steveyegge/beads

# Check goreleaser
goreleaser --version

# Check GitHub CLI (optional)
gh auth status

# Check npm
npm whoami  # Should show your npm username

# Check Python/twine (for MCP releases)
python3 --version
twine --version

Release Checklist

Before starting a release:

  • All tests passing (go test ./...)
  • npm package tests passing (cd npm-package && npm run test:all)
  • CHANGELOG.md updated with changes
  • Version bumped in all locations (use scripts/bump-version.sh)
  • No uncommitted changes
  • On main branch and up to date with origin

1. Prepare Release

Update Version

Use the version bump script to update all version references:

# Dry run - shows what will change
./scripts/bump-version.sh 0.22.0

# Review the diff
git diff

# Commit if it looks good
./scripts/bump-version.sh 0.22.0 --commit

This updates:

  • cmd/bd/main.go - CLI version constant
  • integrations/mcp/server/pyproject.toml - MCP server version
  • npm-package/package.json - npm package version
  • Formula/bd.rb - Homebrew formula version
  • .goreleaser.yml - Release configuration

Update CHANGELOG.md

Add release notes:

## [0.22.0] - 2025-11-04

### Added
- New feature X
- New command Y

### Changed
- Improved performance of Z

### Fixed
- Bug in component A

### Breaking Changes
- Changed behavior of B (migration guide)

Commit and Tag

# Commit version bump and changelog
git add -A
git commit -m "chore: Bump version to 0.22.0"

# Create annotated tag
git tag -a v0.22.0 -m "Release v0.22.0"

# Push to GitHub
git push origin main
git push origin v0.22.0

2. GitHub Release

GoReleaser automates binary building and GitHub release creation:

# Clean any previous builds
rm -rf dist/

# Create release (requires GITHUB_TOKEN)
export GITHUB_TOKEN="your-github-token"
goreleaser release --clean

# Or use gh CLI for token
gh auth token | goreleaser release --clean

This will:

  • Build binaries for all platforms (macOS, Linux, Windows - amd64/arm64)
  • Create checksums
  • Generate release notes from CHANGELOG.md
  • Upload everything to GitHub releases
  • Mark as latest release

Manual Release (Alternative)

If goreleaser doesn't work:

# Build for all platforms
./scripts/build-all-platforms.sh

# Create GitHub release
gh release create v0.22.0 \
  --title "v0.22.0" \
  --notes-file CHANGELOG.md \
  dist/*.tar.gz \
  dist/*.zip \
  dist/checksums.txt

Verify GitHub Release

  1. Visit https://github.com/steveyegge/beads/releases
  2. Verify v0.22.0 is marked as "Latest"
  3. Check all platform binaries are present:
    • beads_0.22.0_darwin_amd64.tar.gz
    • beads_0.22.0_darwin_arm64.tar.gz
    • beads_0.22.0_linux_amd64.tar.gz
    • beads_0.22.0_linux_arm64.tar.gz
    • beads_0.22.0_windows_amd64.zip
    • checksums.txt

3. Homebrew Update

Homebrew formula is in a separate tap repository.

Automatic Update (If Configured)

If you have goreleaser configured with Homebrew:

# Already done by goreleaser
# Check Formula/bd.rb was updated automatically

Manual Update

# Clone tap repository
git clone https://github.com/steveyegge/homebrew-beads.git
cd homebrew-beads

# Update formula
# 1. Update version number
# 2. Update SHA256 checksums for macOS binaries

# Test formula
brew install --build-from-source ./Formula/bd.rb
bd version  # Should show 0.22.0

# Commit and push
git add Formula/bd.rb
git commit -m "Update bd to 0.22.0"
git push

Verify Homebrew

# Update tap
brew update

# Install new version
brew upgrade bd

# Verify
bd version  # Should show 0.22.0

4. PyPI Release (MCP Server)

The MCP server is a Python package published separately to PyPI.

Prerequisites

# Install build tools
pip install build twine

# Verify PyPI credentials
cat ~/.pypirc  # Should have token or credentials

Build and Publish

# Navigate to MCP server directory
cd integrations/mcp/server

# Verify version was updated
cat pyproject.toml | grep version

# Clean old builds
rm -rf dist/ build/ *.egg-info

# Build package
python -m build

# Verify contents
tar -tzf dist/beads-mcp-0.22.0.tar.gz

# Upload to PyPI (test first)
twine upload --repository testpypi dist/*

# Verify on test PyPI
pip install --index-url https://test.pypi.org/simple/ beads-mcp==0.22.0

# Upload to production PyPI
twine upload dist/*

Verify PyPI Release

# Check package page
open https://pypi.org/project/beads-mcp/

# Install and test
pip install beads-mcp==0.22.0
python -m beads_mcp --version

5. npm Package Release

The npm package wraps the native binary for Node.js environments.

Prerequisites

# Verify npm authentication
npm whoami  # Should show your username

# Verify you're in @beads org
npm org ls beads

Update and Test

# Navigate to npm package
cd npm-package

# Version should already be updated by bump-version.sh
cat package.json | grep version

# Run all tests
npm run test:all

# Should see:
# ✅ All unit tests passed
# ✅ All integration tests passed

Test Installation Locally

# Pack the package
npm pack

# Install globally from tarball
npm install -g ./beads-bd-0.22.0.tgz

# Verify binary downloads correctly
bd version  # Should show 0.22.0

# Test in a project
mkdir /tmp/test-npm-bd
cd /tmp/test-npm-bd
git init
bd init
bd create "Test issue" -p 1
bd list

# Cleanup
npm uninstall -g @beads/bd
rm -rf /tmp/test-npm-bd
cd -
rm beads-bd-0.22.0.tgz

Publish to npm

# IMPORTANT: Ensure GitHub release with binaries is live first!
# The postinstall script downloads from GitHub releases

# Publish to npm (first time use --access public)
npm publish --access public

# Or for subsequent releases
npm publish

Verify npm Release

# Check package page
open https://www.npmjs.com/package/@beads/bd

# Install and test
npm install -g @beads/bd
bd version  # Should show 0.22.0

# Test postinstall downloaded correct binary
which bd
bd --help

6. Verify Release

After all distribution channels are updated, verify each one:

GitHub

# Download and test binary
wget https://github.com/steveyegge/beads/releases/download/v0.22.0/beads_0.22.0_darwin_arm64.tar.gz
tar -xzf beads_0.22.0_darwin_arm64.tar.gz
./bd version

Homebrew

brew update
brew upgrade bd
bd version

PyPI

pip install --upgrade beads-mcp
python -m beads_mcp --version

npm

npm install -g @beads/bd
bd version

Installation Script

# Test quick install script
curl -fsSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash
bd version

Hotfix Releases

For urgent bug fixes:

# Create hotfix branch from tag
git checkout -b hotfix/v0.22.1 v0.22.0

# Make fixes
# ... edit files ...

# Bump version to 0.22.1
./scripts/bump-version.sh 0.22.1 --commit

# Tag and release
git tag -a v0.22.1 -m "Hotfix release v0.22.1"
git push origin hotfix/v0.22.1
git push origin v0.22.1

# Follow normal release process
goreleaser release --clean

# Merge back to main
git checkout main
git merge hotfix/v0.22.1
git push origin main

Rollback Procedure

If a release has critical issues:

1. Mark GitHub Release as Pre-release

gh release edit v0.22.0 --prerelease

2. Create Hotfix Release

Follow hotfix procedure above to release 0.22.1.

3. Revert Homebrew (If Needed)

cd homebrew-beads
git revert HEAD
git push

4. Deprecate npm Package (If Needed)

npm deprecate @beads/bd@0.22.0 "Critical bug, please upgrade to 0.22.1"

5. Yank PyPI Release (If Needed)

# Can't delete, but can yank (hide from pip install)
# Contact PyPI support or use web interface

Automation Opportunities

GitHub Actions

Create .github/workflows/release.yml:

name: Release
on:
  push:
    tags:
      - 'v*'

jobs:
  goreleaser:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-go@v4
      - uses: goreleaser/goreleaser-action@v4
        with:
          version: latest
          args: release --clean
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  npm:
    needs: goreleaser
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '18'
          registry-url: 'https://registry.npmjs.org'
      - run: cd npm-package && npm publish --access public
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

  pypi:
    needs: goreleaser
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v4
      - run: |
          cd integrations/mcp/server
          pip install build twine
          python -m build
          twine upload dist/*
        env:
          TWINE_USERNAME: __token__
          TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}

Post-Release

After a successful release:

  1. Announce on relevant channels (Twitter, blog, etc.)
  2. Update documentation if needed
  3. Close milestone on GitHub if using milestones
  4. Update project board if using project management
  5. Monitor for issues in the first 24-48 hours

Troubleshooting

"Tag already exists"

# Delete tag locally and remotely
git tag -d v0.22.0
git push origin :refs/tags/v0.22.0

# Recreate
git tag -a v0.22.0 -m "Release v0.22.0"
git push origin v0.22.0

"npm publish fails with EEXIST"

# Version already published, bump version
npm version patch
npm publish

"Binary download fails in npm postinstall"

# Ensure GitHub release is published first
# Check binary URL is correct
# Verify version matches in package.json and GitHub release

"GoReleaser build fails"

# Check .goreleaser.yml syntax
goreleaser check

# Test build locally
goreleaser build --snapshot --clean

Version Numbering

Beads follows Semantic Versioning:

  • MAJOR (x.0.0): Breaking changes
  • MINOR (0.x.0): New features, backwards compatible
  • PATCH (0.0.x): Bug fixes, backwards compatible

Examples:

  • 0.21.50.22.0: New features (minor bump)
  • 0.22.00.22.1: Bug fix (patch bump)
  • 0.22.11.0.0: Stable release (major bump)

Release Cadence

  • Minor releases: Every 2-4 weeks (new features)
  • Patch releases: As needed (bug fixes)
  • Major releases: When breaking changes are necessary

Questions?