Files
beads/.beads/formulas/beads-release.formula.toml
dave e96dd023ce refactor(formula): break run-bump-script into individual version-update steps (bd-a854)
Replace the monolithic run-bump-script step with 7 individual steps:
- bump-version-go: Update cmd/bd/version.go
- bump-plugin-json: Update .claude-plugin/*.json
- bump-mcp-python: Update pyproject.toml and __init__.py
- bump-npm-package: Update npm-package/package.json
- bump-hook-templates: Update cmd/bd/templates/hooks/*
- bump-readme: Update README.md badge
- stamp-changelog: Add date to [Unreleased] section

Benefits:
- Durability: If interrupted mid-release, can resume from specific step
- Visibility: Activity feed shows progress through each sub-operation
- Atomicity: Each step has clear verify commands

Also removed outdated JSON formula file (TOML is authoritative).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Executed-By: beads/crew/dave
Rig: beads
Role: crew
2026-01-07 21:37:19 -08:00

544 lines
12 KiB
TOML

# Beads Release Formula v2 (Gate-Aware)
#
# This formula uses gates for async waits during CI, enabling clean phase handoffs.
# Instead of polling, the polecat completes Phase 1, and a gate blocks Phase 2
# until GitHub Actions finishes.
#
# Phases:
# 1. Prep & Push: preflight → push-tag (polecat work)
# 2. Gate: await-ci (async wait for release.yml)
# 3. Verify: verify-github, verify-npm, verify-pypi (parallel)
# 4. Install: local-install → release-complete (fan-in)
formula = "beads-release"
description = """
Beads release workflow v2 - gate-aware async release.
This formula orchestrates a complete release cycle with async gates:
Phase 1 (Polecat Work):
1. Preflight checks (clean git, up to date)
2. Documentation updates (CHANGELOG, info.go)
3. Version bump (all components)
4. Git operations (commit, tag, push)
Gate (Async Wait):
5. await-ci: Gate on GitHub Actions release.yml completion
Phase 2 (Parallel Verification):
6. Verify GitHub release, npm package, PyPI package (concurrent)
Phase 3 (Installation):
7. Local installation update
8. Daemon restart
## Usage
```bash
bd mol wisp create beads-release --var version=0.44.0
```
Or assign to a polecat:
```bash
gt sling beads/polecats/p1 --formula beads-release --var version=0.44.0
```
The polecat will complete Phase 1, then signal phase-complete. The gate blocks
until release.yml finishes. A new polecat (or the same one) resumes for Phases 2-3.
"""
type = "workflow"
phase = "vapor" # Ensures this runs as a wisp - bd pour will warn, gt sling --formula creates wisp
version = 1
[vars.version]
description = "The semantic version to release (e.g., 0.44.0)"
required = true
# =============================================================================
# Phase 1: Prep & Push
# =============================================================================
[[steps]]
id = "preflight-git"
title = "Preflight: Check git status"
description = """
Ensure working tree is clean before starting release.
```bash
git status
```
If there are uncommitted changes, either:
- Commit them first
- Stash them: `git stash`
- Abort and resolve
"""
[[steps]]
id = "preflight-pull"
title = "Preflight: Pull latest"
needs = ["preflight-git"]
description = """
Ensure we're up to date with origin.
```bash
git pull --rebase
```
Resolve any conflicts before proceeding.
"""
[[steps]]
id = "review-changes"
title = "Review changes since last release"
needs = ["preflight-pull"]
description = """
Understand what's being released.
```bash
git log $(git describe --tags --abbrev=0)..HEAD --oneline
```
Categorize changes:
- Features (feat:)
- Fixes (fix:)
- Breaking changes
- Documentation
"""
[[steps]]
id = "update-changelog"
title = "Update CHANGELOG.md"
needs = ["review-changes"]
description = """
Write the [Unreleased] section with all changes for {{version}}.
Format: Keep a Changelog (https://keepachangelog.com)
Sections:
- ### Added
- ### Changed
- ### Fixed
- ### Documentation
The bump script will stamp the date automatically.
"""
[[steps]]
id = "update-info-go"
title = "Update info.go versionChanges"
needs = ["update-changelog"]
description = """
Add entry to versionChanges in cmd/bd/info.go.
This powers `bd info --whats-new` for agents.
```go
"{{version}}": {
"summary": "Brief description",
"changes": []string{
"Key change 1",
"Key change 2",
},
},
```
Focus on workflow-impacting changes agents need to know.
"""
[[steps]]
id = "bump-version-go"
title = "Bump version in version.go"
needs = ["update-info-go"]
description = """
Update the Go version constant.
```bash
# macOS
sed -i '' 's/Version = "[^"]*"/Version = "{{version}}"/' cmd/bd/version.go
# Linux
sed -i 's/Version = "[^"]*"/Version = "{{version}}"/' cmd/bd/version.go
```
Verify:
```bash
grep 'Version = ' cmd/bd/version.go
```
"""
[[steps]]
id = "bump-plugin-json"
title = "Bump version in plugin JSON files"
needs = ["bump-version-go"]
description = """
Update Claude plugin manifest versions.
```bash
# macOS/Linux with jq
jq '.version = "{{version}}"' .claude-plugin/plugin.json > tmp && mv tmp .claude-plugin/plugin.json
jq '.plugins[0].version = "{{version}}"' .claude-plugin/marketplace.json > tmp && mv tmp .claude-plugin/marketplace.json
```
Verify:
```bash
jq -r '.version' .claude-plugin/plugin.json
jq -r '.plugins[0].version' .claude-plugin/marketplace.json
```
"""
[[steps]]
id = "bump-mcp-python"
title = "Bump version in MCP Python package"
needs = ["bump-plugin-json"]
description = """
Update the beads-mcp Python package version.
```bash
# macOS
sed -i '' 's/version = "[^"]*"/version = "{{version}}"/' integrations/beads-mcp/pyproject.toml
sed -i '' 's/__version__ = "[^"]*"/__version__ = "{{version}}"/' integrations/beads-mcp/src/beads_mcp/__init__.py
# Linux
sed -i 's/version = "[^"]*"/version = "{{version}}"/' integrations/beads-mcp/pyproject.toml
sed -i 's/__version__ = "[^"]*"/__version__ = "{{version}}"/' integrations/beads-mcp/src/beads_mcp/__init__.py
```
Verify:
```bash
grep 'version = ' integrations/beads-mcp/pyproject.toml | head -1
grep '__version__ = ' integrations/beads-mcp/src/beads_mcp/__init__.py
```
"""
[[steps]]
id = "bump-npm-package"
title = "Bump version in npm package"
needs = ["bump-mcp-python"]
description = """
Update the npm package version.
```bash
# macOS/Linux with jq
jq '.version = "{{version}}"' npm-package/package.json > tmp && mv tmp npm-package/package.json
```
Verify:
```bash
jq -r '.version' npm-package/package.json
```
"""
[[steps]]
id = "bump-hook-templates"
title = "Bump version in hook templates"
needs = ["bump-npm-package"]
description = """
Update version comment in git hook templates.
```bash
# macOS
for f in cmd/bd/templates/hooks/pre-commit cmd/bd/templates/hooks/post-merge cmd/bd/templates/hooks/pre-push cmd/bd/templates/hooks/post-checkout; do
sed -i '' 's/# bd-hooks-version: .*/# bd-hooks-version: {{version}}/' "$f"
done
# Linux
for f in cmd/bd/templates/hooks/pre-commit cmd/bd/templates/hooks/post-merge cmd/bd/templates/hooks/pre-push cmd/bd/templates/hooks/post-checkout; do
sed -i 's/# bd-hooks-version: .*/# bd-hooks-version: {{version}}/' "$f"
done
```
Verify:
```bash
grep '# bd-hooks-version:' cmd/bd/templates/hooks/pre-commit
```
"""
[[steps]]
id = "bump-readme"
title = "Bump version in README badge"
needs = ["bump-hook-templates"]
description = """
Update the Alpha version badge in README.md.
```bash
# macOS
sed -i '' 's/Alpha (v[^)]*)/Alpha (v{{version}})/' README.md
# Linux
sed -i 's/Alpha (v[^)]*)/Alpha (v{{version}})/' README.md
```
Verify:
```bash
grep 'Alpha (v' README.md
```
"""
[[steps]]
id = "stamp-changelog"
title = "Stamp changelog with release date"
needs = ["bump-readme"]
description = """
Add the release date to the [Unreleased] section header.
```bash
DATE=$(date +%Y-%m-%d)
# macOS
sed -i '' "s/## \\[Unreleased\\]/## [Unreleased]\\
\\
## [{{version}}] - $DATE/" CHANGELOG.md
# Linux
sed -i "s/## \\[Unreleased\\]/## [Unreleased]\\n\\n## [{{version}}] - $DATE/" CHANGELOG.md
```
Note: The update-changelog step handles the content; this step just adds the date stamp.
Verify:
```bash
grep -A2 '\\[Unreleased\\]' CHANGELOG.md
```
"""
[[steps]]
id = "verify-versions"
title = "Verify version consistency"
needs = ["stamp-changelog"]
description = """
Confirm all versions match {{version}}.
```bash
grep 'Version = ' cmd/bd/version.go
jq -r '.version' .claude-plugin/plugin.json
jq -r '.version' npm-package/package.json
grep 'version = ' integrations/beads-mcp/pyproject.toml
```
All should show {{version}}.
"""
[[steps]]
id = "commit-release"
title = "Commit release"
needs = ["verify-versions"]
description = """
Stage and commit all version changes.
```bash
git add -A
git commit -m "chore: Bump version to {{version}}"
```
Review the commit to ensure all expected files are included.
"""
[[steps]]
id = "create-tag"
title = "Create release tag"
needs = ["commit-release"]
description = """
Create annotated git tag.
```bash
git tag -a v{{version}} -m "Release v{{version}}"
```
Verify: `git tag -l | tail -5`
"""
[[steps]]
id = "push-main"
title = "Push to main"
needs = ["create-tag"]
description = """
Push the release commit to origin.
```bash
git push origin main
```
If rejected, someone else pushed. Pull, rebase, try again.
"""
[[steps]]
id = "push-tag"
title = "Push release tag"
needs = ["push-main"]
description = """
Push the version tag to trigger CI release.
```bash
git push origin v{{version}}
```
This triggers GitHub Actions to build artifacts and publish.
**Phase 1 Complete**: After this step, signal phase-complete:
```bash
gt done --phase-complete
```
The gate will block until CI finishes. A new session will resume at Phase 2.
"""
# =============================================================================
# Gate: CI Completion
# =============================================================================
[[steps]]
id = "await-ci"
title = "Await CI: release.yml completion"
needs = ["push-tag"]
description = """
Gate step: Wait for GitHub Actions release workflow to complete.
This gate blocks until the release.yml workflow run succeeds.
The Refinery auto-discovers the workflow run triggered by v{{version}}
and closes this gate when it completes.
Expected time: 5-10 minutes
The gate monitors:
- Build artifacts (all platforms)
- Test suite pass
- npm publish
- PyPI publish
If the workflow fails, this gate remains open and requires manual intervention.
"""
[steps.gate]
type = "gh:run"
id = "release.yml"
timeout = "30m"
# =============================================================================
# Phase 2: Verification (Parallel)
# =============================================================================
[[steps]]
id = "verify-github"
title = "Verify GitHub release"
needs = ["await-ci"]
description = """
Check the GitHub releases page.
https://github.com/steveyegge/beads/releases/tag/v{{version}}
Verify:
- Release created
- Binaries attached (linux, darwin, windows)
- Checksums present
```bash
gh release view v{{version}} --json assets --jq '.assets[].name'
```
"""
[[steps]]
id = "verify-npm"
title = "Verify npm package"
needs = ["await-ci"]
description = """
Confirm npm package published.
```bash
npm show @beads/bd version
```
Should show {{version}}.
Also check: https://www.npmjs.com/package/@beads/bd
Note: npm registry may have a small propagation delay (1-2 min).
"""
[[steps]]
id = "verify-pypi"
title = "Verify PyPI package"
needs = ["await-ci"]
description = """
Confirm PyPI package published.
```bash
pip index versions beads-mcp 2>/dev/null | head -3
```
Or check: https://pypi.org/project/beads-mcp/
Should show {{version}}.
Note: PyPI may have a small propagation delay (1-2 min).
"""
# =============================================================================
# Phase 3: Installation (Fan-in)
# =============================================================================
[[steps]]
id = "local-install"
title = "Update local installation"
needs = ["verify-github", "verify-npm", "verify-pypi"]
description = """
Update local bd to the new version.
Option 1 - Homebrew:
```bash
brew upgrade bd
```
Option 2 - Install script:
```bash
curl -fsSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash
```
Verify:
```bash
bd --version
```
Should show {{version}}.
"""
[[steps]]
id = "restart-daemons"
title = "Restart daemons"
needs = ["local-install"]
description = """
Restart bd daemons to pick up new version.
```bash
bd daemons killall
```
Daemons will auto-restart with new version on next bd command.
Verify:
```bash
bd daemons list
```
"""
[[steps]]
id = "release-complete"
title = "Release complete"
needs = ["restart-daemons"]
description = """
Release v{{version}} is complete!
Summary:
- All version files updated
- Git tag pushed
- CI artifacts built (via gate)
- npm and PyPI packages verified
- Local installation updated
- Daemons restarted
Optional next steps:
- Announce on social media
- Update documentation site
- Close related milestone
"""