diff --git a/docs/release-checklist.md b/docs/release-checklist.md index c0122a99..e0e001b2 100644 --- a/docs/release-checklist.md +++ b/docs/release-checklist.md @@ -2,8 +2,8 @@ Mandatory checklist for version bump and release. **Every version bump MUST follow this checklist.** -> **Incident:** v5.2.0 release failed because `version.ts` and `plugin/package.json` were not bumped. -> CI caught the mismatch, but the manual review missed it. +> **Incident (v5.2.0):** `version.ts` and `plugin/package.json` were not bumped. CI caught the mismatch. +> **Incident (v5.3.0):** `sync-version` changed `peerDependencies` but `yarn install` was not run, so `yarn.lock` was stale. CI `--immutable` rejected it. ## Version Files — Complete List @@ -14,10 +14,28 @@ All files below MUST have matching versions. **Missing even one will fail the re | 1 | `apps/mcp-server/package.json` | MCP server version (primary source) | Manual | | 2 | `apps/mcp-server/src/shared/version.ts` | Runtime VERSION constant | Manual | | 3 | `packages/rules/package.json` | Rules package version | Manual | -| 4 | `packages/claude-code-plugin/package.json` | Plugin package version | `sync-version` script | -| 5 | `packages/claude-code-plugin/.claude-plugin/plugin.json` | Plugin manifest version | `sync-version` script | +| 4 | `packages/claude-code-plugin/package.json` | Plugin package version | `sync-version` / `bump-version.sh` | +| 5 | `packages/claude-code-plugin/.claude-plugin/plugin.json` | Plugin manifest version | `sync-version` / `bump-version.sh` | +| 6 | `.claude-plugin/marketplace.json` | Marketplace listing version | `bump-version.sh` | +| — | `yarn.lock` | Lockfile (peerDependencies change) | `yarn install` after sync | -## Bump Procedure +## Recommended: One-Command Bump + +```bash +./scripts/bump-version.sh X.Y.Z +``` + +This script performs Steps 1–5 automatically: +- Bumps all version files (package.json x3 + version.ts + plugin.json + marketplace.json) +- Updates peerDependencies +- Runs `yarn install` to update lockfile +- Verifies all files match + +After the script succeeds, proceed to Step 6 (Commit + PR). + +--- + +## Manual Bump Procedure (if not using the script) ### Step 1: Bump primary source @@ -41,6 +59,15 @@ This automatically syncs: - `packages/claude-code-plugin/package.json` (version + peerDependencies) - `packages/claude-code-plugin/.claude-plugin/plugin.json` (version) +### Step 4.5: Update lockfile — MANDATORY + +```bash +yarn install +``` + +`sync-version` changes `peerDependencies`, which requires a lockfile update. +CI runs with `--immutable` and will reject stale lockfiles. + ### Step 5: Verify — MANDATORY ```bash @@ -56,6 +83,9 @@ grep -q "\"version\": \"$VERSION\"" packages/claude-code-plugin/.claude-plugin/p # No remaining old version grep -rn "OLD_VERSION" --include="*.ts" --include="*.json" apps/ packages/ | grep -v node_modules | grep -v CHANGELOG && echo "❌ OLD VERSION FOUND" || echo "✅ Clean" + +# Lockfile is up to date (no uncommitted changes after yarn install) +git diff --quiet yarn.lock && echo "✅ yarn.lock clean" || echo "❌ yarn.lock has uncommitted changes — run yarn install and stage it" ``` ### Step 6: Commit + PR @@ -80,6 +110,7 @@ git push origin vX.Y.Z | Forgot `version.ts` | Step 2 is explicit — version.ts is separate from package.json | | Forgot `plugin/package.json` | Step 4 `sync-version` handles this automatically | | Forgot to run `sync-version` | Step 4 is a separate explicit step | +| Stale `yarn.lock` after sync-version | Step 4.5 `yarn install` updates lockfile after peerDependencies change | | Version mismatch between files | Step 5 verification catches this | | Old version remains in codebase | Step 5 grep check catches this | diff --git a/scripts/bump-version.sh b/scripts/bump-version.sh index a353d583..17aa5d7c 100755 --- a/scripts/bump-version.sh +++ b/scripts/bump-version.sh @@ -111,6 +111,32 @@ echo "🔒 Updating lockfile..." yarn install echo " ✅ yarn.lock" +# 9. Verify all version files match echo "" +echo "════════════════════════════════════════════" +echo "🔍 Verification" +echo "════════════════════════════════════════════" + +ERRORS=0 + +grep -q "\"version\": \"$NEW_VERSION\"" apps/mcp-server/package.json && echo " ✅ mcp-server/package.json" || { echo " ❌ mcp-server/package.json"; ERRORS=$((ERRORS+1)); } +grep -q "VERSION = '$NEW_VERSION'" apps/mcp-server/src/shared/version.ts && echo " ✅ version.ts" || { echo " ❌ version.ts"; ERRORS=$((ERRORS+1)); } +grep -q "\"version\": \"$NEW_VERSION\"" packages/rules/package.json && echo " ✅ rules/package.json" || { echo " ❌ rules/package.json"; ERRORS=$((ERRORS+1)); } +grep -q "\"version\": \"$NEW_VERSION\"" packages/claude-code-plugin/package.json && echo " ✅ plugin/package.json" || { echo " ❌ plugin/package.json"; ERRORS=$((ERRORS+1)); } +grep -q "\"version\": \"$NEW_VERSION\"" packages/claude-code-plugin/.claude-plugin/plugin.json && echo " ✅ plugin.json" || { echo " ❌ plugin.json"; ERRORS=$((ERRORS+1)); } +grep -q "\"version\": \"$NEW_VERSION\"" .claude-plugin/marketplace.json && echo " ✅ marketplace.json" || { echo " ❌ marketplace.json"; ERRORS=$((ERRORS+1)); } +git diff --quiet yarn.lock && echo " ✅ yarn.lock clean" || { echo " ❌ yarn.lock has uncommitted changes"; ERRORS=$((ERRORS+1)); } + +echo "" +if [ "$ERRORS" -gt 0 ]; then + echo "❌ Verification failed with $ERRORS error(s). DO NOT commit." + exit 1 +fi + echo "✅ All files bumped to v$NEW_VERSION (including yarn.lock)" -echo " Next: git commit -am \"chore(release): prepare v$NEW_VERSION\"" +echo "" +echo "Next steps:" +echo " git add -A" +echo " git commit -m \"chore: prepare v$NEW_VERSION release\"" +echo " # Create PR, wait for CI, merge" +echo " # Then: git tag v$NEW_VERSION && git push origin v$NEW_VERSION"