From e96dd023cef2aa2e9cf44e4d43b88a6bd14d3c33 Mon Sep 17 00:00:00 2001 From: dave Date: Wed, 7 Jan 2026 21:37:19 -0800 Subject: [PATCH] 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 Executed-By: beads/crew/dave Rig: beads Role: crew --- .beads/formulas/beads-release.formula.json | 139 ------------------ .beads/formulas/beads-release.formula.toml | 162 +++++++++++++++++++-- 2 files changed, 148 insertions(+), 153 deletions(-) delete mode 100644 .beads/formulas/beads-release.formula.json diff --git a/.beads/formulas/beads-release.formula.json b/.beads/formulas/beads-release.formula.json deleted file mode 100644 index 1bcefd74..00000000 --- a/.beads/formulas/beads-release.formula.json +++ /dev/null @@ -1,139 +0,0 @@ -{ - "formula": "beads-release", - "type": "workflow", - "description": "Beads release workflow - from version bump to verified release.\n\nThis formula orchestrates a complete release cycle:\n1. Preflight checks (clean git, synced beads, up to date)\n2. Documentation updates (CHANGELOG, info.go)\n3. Version bump (all components)\n4. Git operations (commit, tag, push)\n5. CI verification (GitHub Actions)\n6. Artifact verification (GitHub, npm, PyPI)\n7. Local installation update (with verification gate)\n8. Daemon restart (with version verification)\n9. Post-release cleanup\n\n## Usage\n\n```bash\nbd wisp create beads-release --var version=0.37.0\n```\n\nOr assign to a polecat:\n```bash\ngt sling beads/polecats/p1 --formula beads-release --var version=0.37.0\n```", - "version": 1, - "vars": { - "version": { - "description": "The semantic version to release (e.g., 0.37.0)", - "required": true - } - }, - "steps": [ - { - "id": "preflight-git", - "title": "Preflight: Check git status", - "description": "Ensure working tree is clean before starting release.\n\n```bash\ngit status\n```\n\nIf there are uncommitted changes, either:\n- Commit them first\n- Stash them: `git stash`\n- Abort and resolve" - }, - { - "id": "preflight-sync", - "title": "Preflight: Sync beads", - "description": "Ensure beads are synced before starting release.\n\n```bash\nbd sync\n```\n\nThis catches:\n- Stale worktrees that need repair\n- Uncommitted beads changes in other clones\n- Divergence issues that would block later syncs\n\nIf sync fails, resolve the issue before proceeding.", - "needs": ["preflight-git"] - }, - { - "id": "preflight-pull", - "title": "Preflight: Pull latest", - "description": "Ensure we're up to date with origin.\n\n```bash\ngit pull --rebase\n```\n\nResolve any conflicts before proceeding.", - "needs": ["preflight-sync"] - }, - { - "id": "review-changes", - "title": "Review changes since last release", - "description": "Understand what's being released.\n\n```bash\ngit log $(git describe --tags --abbrev=0)..HEAD --oneline\n```\n\nCategorize changes:\n- Features (feat:)\n- Fixes (fix:)\n- Breaking changes\n- Documentation", - "needs": ["preflight-pull"] - }, - { - "id": "update-changelog", - "title": "Update CHANGELOG.md", - "description": "Write the [Unreleased] section with all changes for {{version}}.\n\nFormat: Keep a Changelog (https://keepachangelog.com)\n\nSections:\n- ### Added\n- ### Changed\n- ### Fixed\n- ### Documentation\n\nThe bump script will stamp the date automatically.", - "needs": ["review-changes"] - }, - { - "id": "update-info-go", - "title": "Update info.go versionChanges", - "description": "Add entry to versionChanges in cmd/bd/info.go.\n\nThis powers `bd info --whats-new` for agents.\n\n```go\n\"{{version}}\": {\n \"summary\": \"Brief description\",\n \"changes\": []string{\n \"Key change 1\",\n \"Key change 2\",\n },\n},\n```\n\nFocus on workflow-impacting changes agents need to know.", - "needs": ["update-changelog"] - }, - { - "id": "run-bump-script", - "title": "Run bump-version.sh", - "description": "Update all component versions atomically.\n\n```bash\n./scripts/bump-version.sh {{version}}\n```\n\nThis updates:\n- cmd/bd/version.go\n- .claude-plugin/*.json\n- integrations/beads-mcp/pyproject.toml\n- integrations/beads-mcp/src/beads_mcp/__init__.py\n- npm-package/package.json\n- Hook templates\n- README.md\n- CHANGELOG.md (adds date)", - "needs": ["update-info-go"] - }, - { - "id": "verify-versions", - "title": "Verify version consistency", - "description": "Confirm all versions match {{version}}.\n\n```bash\ngrep 'Version = ' cmd/bd/version.go\njq -r '.version' .claude-plugin/plugin.json\njq -r '.version' npm-package/package.json\ngrep 'version = ' integrations/beads-mcp/pyproject.toml\n```\n\nAll should show {{version}}.", - "needs": ["run-bump-script"] - }, - { - "id": "commit-release", - "title": "Commit release", - "description": "Stage and commit all version changes.\n\n```bash\ngit add -A\ngit commit -m \"chore: bump version to {{version}}\"\n```\n\nReview the commit to ensure all expected files are included.", - "needs": ["verify-versions"] - }, - { - "id": "create-tag", - "title": "Create release tag", - "description": "Create annotated git tag.\n\n```bash\ngit tag -a v{{version}} -m \"Release v{{version}}\"\n```\n\nVerify: `git tag -l | tail -5`", - "needs": ["commit-release"] - }, - { - "id": "push-main", - "title": "Push to main", - "description": "Push the release commit to origin.\n\n```bash\ngit push origin main\n```\n\nIf rejected, someone else pushed. Pull, rebase, try again.", - "needs": ["create-tag"] - }, - { - "id": "push-tag", - "title": "Push release tag", - "description": "Push the version tag to trigger CI release.\n\n```bash\ngit push origin v{{version}}\n```\n\nThis triggers GitHub Actions to build artifacts and publish.", - "needs": ["push-main"] - }, - { - "id": "wait-ci", - "title": "Wait for CI", - "description": "Monitor GitHub Actions for release completion.\n\nhttps://github.com/steveyegge/beads/actions\n\nExpected time: 5-10 minutes\n\nWatch for:\n- Build artifacts (all platforms)\n- Test suite pass\n- npm publish\n- PyPI publish", - "needs": ["push-tag"] - }, - { - "id": "verify-github-release", - "title": "Verify GitHub release", - "description": "Check the GitHub releases page.\n\nhttps://github.com/steveyegge/beads/releases/tag/v{{version}}\n\nVerify:\n- Release created\n- Binaries attached (linux, darwin, windows)\n- Checksums present", - "needs": ["wait-ci"] - }, - { - "id": "verify-npm", - "title": "Verify npm package", - "description": "Confirm npm package published.\n\n```bash\nnpm show @beads/bd version\n```\n\nShould show {{version}}.\n\nAlso check: https://www.npmjs.com/package/@beads/bd", - "needs": ["verify-github-release"] - }, - { - "id": "verify-pypi", - "title": "Verify PyPI package", - "description": "Confirm PyPI package published.\n\n```bash\npip index versions beads-mcp 2>/dev/null | head -3\n```\n\nOr check: https://pypi.org/project/beads-mcp/\n\nShould show {{version}}.", - "needs": ["verify-github-release"] - }, - { - "id": "local-install", - "title": "Update local installation", - "description": "Update local bd to the new version.\n\n**Detect install method:**\n```bash\nwhich bd\n```\n\n**Option 1 - Dev build** (if bd is in ~/.local/bin or project dir):\n```bash\ngo build -o bd ./cmd/bd\ncp ./bd ~/.local/bin/bd\n```\n\n**Option 2 - Homebrew** (if bd is in /opt/homebrew or /usr/local):\n```bash\nbrew upgrade bd\n```\n\n**Option 3 - Install script:**\n```bash\ncurl -fsSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash\n```", - "needs": ["verify-npm", "verify-pypi"] - }, - { - "id": "verify-local-install", - "title": "Verify local installation", - "description": "**GATE: This step must pass before proceeding.**\n\nVerify the installed version matches the release:\n\n```bash\nbd --version\n```\n\n**Expected output:** `bd version {{version}}`\n\n**If version mismatch:**\n1. Check which bd is in PATH: `which bd`\n2. Rebuild if dev install: `go build -o bd ./cmd/bd && cp ./bd ~/.local/bin/bd`\n3. Verify again: `bd --version`\n\n**Do not proceed until `bd --version` shows {{version}}.**", - "needs": ["local-install"] - }, - { - "id": "restart-daemons", - "title": "Restart daemons", - "description": "Restart bd daemons to pick up new version.\n\n```bash\nbd daemons killall\n```\n\nTrigger daemon restart:\n```bash\nbd list >/dev/null 2>&1\n```\n\nVerify daemon version:\n```bash\nbd daemons list\n```\n\n**Expected:** All daemons should show version {{version}}.\n\nIf daemons show old version, they may be running from a different bd binary.\nCheck with: `ps aux | grep bd.*daemon`", - "needs": ["verify-local-install"] - }, - { - "id": "post-release-sync", - "title": "Post-release: Sync beads", - "description": "Sync beads to capture any changes made during release.\n\n```bash\nbd sync\n```\n\nThis ensures:\n- Molecule progress is committed\n- Any beads updates are pushed\n- Clean state for next session", - "needs": ["restart-daemons"] - }, - { - "id": "release-complete", - "title": "Release complete", - "description": "Release v{{version}} is complete!\n\n**Verification checklist:**\n- [ ] `bd --version` shows {{version}}\n- [ ] `bd daemons list` shows {{version}}\n- [ ] GitHub release has all artifacts\n- [ ] npm package is {{version}}\n- [ ] PyPI package is {{version}}\n- [ ] `bd sync` succeeded\n\n**Summary:**\n- All version files updated\n- Git tag pushed\n- CI artifacts built\n- npm and PyPI packages published\n- Local installation verified\n- Daemons restarted with new version\n- Beads synced\n\n**Note:** If this was a wisp, it will be squashed to a digest.\nThe hook should clear automatically after squash.", - "needs": ["post-release-sync"] - } - ] -} diff --git a/.beads/formulas/beads-release.formula.toml b/.beads/formulas/beads-release.formula.toml index 29263b79..86f6d9b2 100644 --- a/.beads/formulas/beads-release.formula.toml +++ b/.beads/formulas/beads-release.formula.toml @@ -147,31 +147,165 @@ Focus on workflow-impacting changes agents need to know. """ [[steps]] -id = "run-bump-script" -title = "Run bump-version.sh" +id = "bump-version-go" +title = "Bump version in version.go" needs = ["update-info-go"] description = """ -Update all component versions atomically. +Update the Go version constant. ```bash -./scripts/bump-version.sh {{version}} +# macOS +sed -i '' 's/Version = "[^"]*"/Version = "{{version}}"/' cmd/bd/version.go + +# Linux +sed -i 's/Version = "[^"]*"/Version = "{{version}}"/' cmd/bd/version.go ``` -This updates: -- cmd/bd/version.go -- .claude-plugin/*.json -- integrations/beads-mcp/pyproject.toml -- integrations/beads-mcp/src/beads_mcp/__init__.py -- npm-package/package.json -- Hook templates -- README.md -- CHANGELOG.md (adds date) +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 = ["run-bump-script"] +needs = ["stamp-changelog"] description = """ Confirm all versions match {{version}}.