From 3f5abf347d70ca9bb1ba1709f715c683634d57e3 Mon Sep 17 00:00:00 2001 From: Brian Madison Date: Sat, 16 Aug 2025 20:23:23 -0500 Subject: [PATCH] feat: simplify installation to single @stable tag - Remove automatic versioning and dual publishing strategy - Delete release.yaml and promote-to-stable.yaml workflows - Add manual-release.yaml for controlled releases - Remove semantic-release dependencies and config - Update all documentation to use npx bmad-method install - Configure NPM to publish to @stable tag by default - Users can now use simple npx bmad-method install command --- .github/workflows/manual-release.yaml | 98 +++++++++++++++ .github/workflows/promote-to-stable.yaml | 148 ----------------------- .github/workflows/release.yaml | 73 ----------- .releaserc.json | 22 ---- README.md | 2 + package.json | 8 +- tools/semantic-release-sync-installer.js | 30 ----- 7 files changed, 103 insertions(+), 278 deletions(-) create mode 100644 .github/workflows/manual-release.yaml delete mode 100644 .github/workflows/promote-to-stable.yaml delete mode 100644 .github/workflows/release.yaml delete mode 100644 .releaserc.json delete mode 100644 tools/semantic-release-sync-installer.js diff --git a/.github/workflows/manual-release.yaml b/.github/workflows/manual-release.yaml new file mode 100644 index 00000000..d7b41cee --- /dev/null +++ b/.github/workflows/manual-release.yaml @@ -0,0 +1,98 @@ +name: Manual Release + +on: + workflow_dispatch: + inputs: + version_bump: + description: Version bump type + required: true + default: patch + type: choice + options: + - patch + - minor + - major + +permissions: + contents: write + packages: write + +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + cache: npm + registry-url: https://registry.npmjs.org + + - name: Install dependencies + run: npm ci + + - name: Run tests and validation + run: | + npm run validate + npm run format:check + npm run lint + + - name: Configure Git + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Bump version + run: npm run version:${{ github.event.inputs.version_bump }} + + - name: Get new version + id: version + run: echo "new_version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT + + - name: Update installer package.json + run: | + sed -i 's/"version": ".*"/"version": "${{ steps.version.outputs.new_version }}"/' tools/installer/package.json + + - name: Build project + run: npm run build + + - name: Commit version bump + run: | + git add . + git commit -m "release: bump to v${{ steps.version.outputs.new_version }}" + + - name: Create and push tag + run: | + git tag -a "v${{ steps.version.outputs.new_version }}" -m "Release v${{ steps.version.outputs.new_version }}" + git push origin "v${{ steps.version.outputs.new_version }}" + + - name: Push changes to main + run: git push origin HEAD:main + + - name: Publish to NPM with stable tag + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + run: npm publish --tag stable + + - name: Create GitHub Release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: v${{ steps.version.outputs.new_version }} + release_name: Release v${{ steps.version.outputs.new_version }} + draft: false + prerelease: false + + - name: Summary + run: | + echo "🎉 Successfully released v${{ steps.version.outputs.new_version }}!" + echo "📦 Published to NPM with @stable tag" + echo "🏷️ Git tag: v${{ steps.version.outputs.new_version }}" + echo "✅ Users running 'npx bmad-method@stable install' will now get version ${{ steps.version.outputs.new_version }}" diff --git a/.github/workflows/promote-to-stable.yaml b/.github/workflows/promote-to-stable.yaml deleted file mode 100644 index 7312bb3d..00000000 --- a/.github/workflows/promote-to-stable.yaml +++ /dev/null @@ -1,148 +0,0 @@ -name: Promote to Stable - -"on": - workflow_dispatch: - inputs: - version_bump: - description: "Version bump type" - required: true - default: "minor" - type: choice - options: - - patch - - minor - - major - -jobs: - promote: - runs-on: ubuntu-latest - permissions: - contents: write - pull-requests: write - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: "20" - registry-url: "https://registry.npmjs.org" - - - name: Configure Git - run: | - git config --global user.name "github-actions[bot]" - git config --global user.email "github-actions[bot]@users.noreply.github.com" - - - name: Install dependencies - run: npm ci - - - name: Get current version and calculate new version - id: version - run: | - # Get current version from package.json - CURRENT_VERSION=$(node -p "require('./package.json').version") - echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT - - # Remove beta suffix if present - BASE_VERSION=$(echo $CURRENT_VERSION | sed 's/-beta\.[0-9]\+//') - echo "base_version=$BASE_VERSION" >> $GITHUB_OUTPUT - - # Calculate new version based on bump type - IFS='.' read -ra VERSION_PARTS <<< "$BASE_VERSION" - MAJOR=${VERSION_PARTS[0]} - MINOR=${VERSION_PARTS[1]} - PATCH=${VERSION_PARTS[2]} - - case "${{ github.event.inputs.version_bump }}" in - "major") - NEW_VERSION="$((MAJOR + 1)).0.0" - ;; - "minor") - NEW_VERSION="$MAJOR.$((MINOR + 1)).0" - ;; - "patch") - NEW_VERSION="$MAJOR.$MINOR.$((PATCH + 1))" - ;; - *) - NEW_VERSION="$BASE_VERSION" - ;; - esac - - # Check if calculated version already exists (either as NPM package or git tag) - while npm view bmad-method@$NEW_VERSION version >/dev/null 2>&1 || git ls-remote --tags origin | grep -q "refs/tags/v$NEW_VERSION"; do - echo "Version $NEW_VERSION already exists, incrementing..." - IFS='.' read -ra NEW_VERSION_PARTS <<< "$NEW_VERSION" - NEW_MAJOR=${NEW_VERSION_PARTS[0]} - NEW_MINOR=${NEW_VERSION_PARTS[1]} - NEW_PATCH=${NEW_VERSION_PARTS[2]} - - case "${{ github.event.inputs.version_bump }}" in - "major") - NEW_VERSION="$((NEW_MAJOR + 1)).0.0" - ;; - "minor") - NEW_VERSION="$NEW_MAJOR.$((NEW_MINOR + 1)).0" - ;; - "patch") - NEW_VERSION="$NEW_MAJOR.$NEW_MINOR.$((NEW_PATCH + 1))" - ;; - esac - done - - echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT - echo "Promoting from $CURRENT_VERSION to $NEW_VERSION" - - - name: Update package.json versions - run: | - # Update main package.json - npm version ${{ steps.version.outputs.new_version }} --no-git-tag-version - - # Update installer package.json - sed -i 's/"version": ".*"/"version": "${{ steps.version.outputs.new_version }}"/' tools/installer/package.json - - - name: Update package-lock.json - run: npm install --package-lock-only - - - name: Commit stable release - run: | - git add . - git commit -m "release: promote to stable ${{ steps.version.outputs.new_version }}" - - - name: Create and push stable tag - run: | - # Create new tag (version check already ensures it doesn't exist) - git tag -a "v${{ steps.version.outputs.new_version }}" -m "Stable release v${{ steps.version.outputs.new_version }}" - - # Push the new tag - git push origin "v${{ steps.version.outputs.new_version }}" - - - name: Push changes to main - run: | - git push origin HEAD:main - - - name: Publish to NPM with stable tag - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - run: | - # Publish with the stable (latest) tag - npm publish --tag latest - - # Also tag the previous beta version as stable if it exists - if npm view bmad-method@${{ steps.version.outputs.current_version }} version >/dev/null 2>&1; then - npm dist-tag add bmad-method@${{ steps.version.outputs.new_version }} stable || true - fi - - - name: Summary - run: | - echo "🎉 Successfully promoted to stable!" - echo "📦 Version: ${{ steps.version.outputs.new_version }}" - echo "🏷️ Git tag: v${{ steps.version.outputs.new_version }}" - echo "✅ Published to NPM with 'latest' tag" - echo "✅ Users running 'npx bmad-method install' will now get version ${{ steps.version.outputs.new_version }}" - echo "🚀 The stable release will be automatically published to NPM via semantic-release" - echo "✅ Users running 'npx bmad-method install' will now get version ${{ steps.version.outputs.new_version }}" diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml deleted file mode 100644 index 23608026..00000000 --- a/.github/workflows/release.yaml +++ /dev/null @@ -1,73 +0,0 @@ -name: Release -"on": - push: - branches: - - main - workflow_dispatch: - inputs: - version_type: - description: Version bump type - required: true - default: patch - type: choice - options: - - patch - - minor - - major -permissions: - contents: write - issues: write - pull-requests: write - packages: write -jobs: - release: - runs-on: ubuntu-latest - if: ${{ github.event_name != 'push' || !contains(github.event.head_commit.message, '[skip ci]') }} - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - token: ${{ secrets.GITHUB_TOKEN }} - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: "20" - cache: "npm" - registry-url: "https://registry.npmjs.org" - - name: Install dependencies - run: npm ci - - name: Run tests and validation - run: | - npm run validate - npm run format - - name: Debug permissions - run: | - echo "Testing git permissions..." - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - echo "Git config set successfully" - - name: Manual version bump - if: github.event_name == 'workflow_dispatch' - run: npm run version:${{ github.event.inputs.version_type }} - - name: Semantic Release - if: github.event_name == 'push' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - run: npm run release - - name: Clean changelog formatting - if: github.event_name == 'push' - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - # Remove any Claude Code attribution from changelog - sed -i '/🤖 Generated with \[Claude Code\]/,+2d' CHANGELOG.md || true - # Format and commit if changes exist - npm run format - if ! git diff --quiet CHANGELOG.md; then - git add CHANGELOG.md - git commit -m "chore: clean changelog formatting [skip ci]" - git push - fi diff --git a/.releaserc.json b/.releaserc.json deleted file mode 100644 index 8b2d1d33..00000000 --- a/.releaserc.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "branches": [ - { - "name": "main", - "prerelease": "beta", - "channel": "beta" - } - ], - "plugins": [ - "@semantic-release/commit-analyzer", - "@semantic-release/release-notes-generator", - [ - "@semantic-release/changelog", - { - "changelogFile": "CHANGELOG.md" - } - ], - "@semantic-release/npm", - "./tools/semantic-release-sync-installer.js", - "@semantic-release/github" - ] -} diff --git a/README.md b/README.md index b5687eb0..0d182dba 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,8 @@ This makes it easy to benefit from the latest improvements, bug fixes, and new a ```bash npx bmad-method install +# OR explicitly use stable tag: +npx bmad-method@stable install # OR if you already have BMad installed: git pull npm run install:bmad diff --git a/package.json b/package.json index 444f11eb..ccd3563d 100644 --- a/package.json +++ b/package.json @@ -35,8 +35,6 @@ "lint:fix": "eslint . --ext .js,.cjs,.mjs,.yaml --fix", "list:agents": "node tools/cli.js list:agents", "prepare": "husky", - "release": "semantic-release", - "release:test": "semantic-release --dry-run --no-ci || echo 'Config test complete - authentication errors are expected locally'", "validate": "node tools/cli.js validate", "version:all": "node tools/bump-all-versions.js", "version:all:major": "node tools/bump-all-versions.js major", @@ -80,8 +78,6 @@ }, "devDependencies": { "@eslint/js": "^9.33.0", - "@semantic-release/changelog": "^6.0.3", - "@semantic-release/git": "^10.0.1", "eslint": "^9.33.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-n": "^17.21.3", @@ -92,11 +88,13 @@ "lint-staged": "^16.1.1", "prettier": "^3.5.3", "prettier-plugin-packagejson": "^2.5.19", - "semantic-release": "^22.0.0", "yaml-eslint-parser": "^1.2.3", "yaml-lint": "^1.7.0" }, "engines": { "node": ">=20.10.0" + }, + "publishConfig": { + "tag": "stable" } } diff --git a/tools/semantic-release-sync-installer.js b/tools/semantic-release-sync-installer.js deleted file mode 100644 index 37bad0cf..00000000 --- a/tools/semantic-release-sync-installer.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Semantic-release plugin to sync installer package.json version - */ - -const fs = require('node:fs'); -const path = require('node:path'); - -// This function runs during the "prepare" step of semantic-release -function prepare(_, { nextRelease, logger }) { - // Define the path to the installer package.json file - const file = path.join(process.cwd(), 'tools/installer/package.json'); - - // If the file does not exist, skip syncing and log a message - if (!fs.existsSync(file)) return logger.log('Installer package.json not found, skipping'); - - // Read and parse the package.json file - const package_ = JSON.parse(fs.readFileSync(file, 'utf8')); - - // Update the version field with the next release version - package_.version = nextRelease.version; - - // Write the updated JSON back to the file - fs.writeFileSync(file, JSON.stringify(package_, null, 2) + '\n'); - - // Log success message - logger.log(`Synced installer package.json to version ${nextRelease.version}`); -} - -// Export the prepare function so semantic-release can use it -module.exports = { prepare };