name: Manual Release on: workflow_dispatch: inputs: version_bump: description: Version bump type required: true default: alpha type: choice options: - alpha - beta - 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-file: ".nvmrc" 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: | case "${{ github.event.inputs.version_bump }}" in alpha|beta) npm version prerelease --no-git-tag-version --preid=${{ github.event.inputs.version_bump }} ;; *) npm version ${{ github.event.inputs.version_bump }} --no-git-tag-version ;; esac - name: Get new version and previous tag id: version run: | echo "new_version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT echo "previous_tag=$(git describe --tags --abbrev=0)" >> $GITHUB_OUTPUT - name: Update installer package.json run: | sed -i 's/"version": ".*"/"version": "${{ steps.version.outputs.new_version }}"/' tools/installer/package.json # TODO: Re-enable web bundles once tools/cli/bundlers/ is restored # - name: Generate web bundles # run: npm run bundle - name: Commit version bump run: | git add . git commit -m "release: bump to v${{ steps.version.outputs.new_version }}" - name: Generate release notes id: release_notes run: | # Get commits since last tag COMMITS=$(git log ${{ steps.version.outputs.previous_tag }}..HEAD --pretty=format:"- %s" --reverse) # Categorize commits FEATURES=$(echo "$COMMITS" | grep -E "^- (feat|Feature)" || true) FIXES=$(echo "$COMMITS" | grep -E "^- (fix|Fix)" || true) CHORES=$(echo "$COMMITS" | grep -E "^- (chore|Chore)" || true) OTHERS=$(echo "$COMMITS" | grep -v -E "^- (feat|Feature|fix|Fix|chore|Chore|release:|Release:)" || true) # Build release notes cat > release_notes.md << 'EOF' ## 🚀 What's New in v${{ steps.version.outputs.new_version }} EOF if [ ! -z "$FEATURES" ]; then echo "### ✨ New Features" >> release_notes.md echo "$FEATURES" >> release_notes.md echo "" >> release_notes.md fi if [ ! -z "$FIXES" ]; then echo "### 🐛 Bug Fixes" >> release_notes.md echo "$FIXES" >> release_notes.md echo "" >> release_notes.md fi if [ ! -z "$OTHERS" ]; then echo "### 📦 Other Changes" >> release_notes.md echo "$OTHERS" >> release_notes.md echo "" >> release_notes.md fi if [ ! -z "$CHORES" ]; then echo "### 🔧 Maintenance" >> release_notes.md echo "$CHORES" >> release_notes.md echo "" >> release_notes.md fi cat >> release_notes.md << 'EOF' ## 📦 Installation ```bash npx bmad-method install ``` **Full Changelog**: https://github.com/bmad-code-org/BMAD-METHOD/compare/${{ steps.version.outputs.previous_tag }}...v${{ steps.version.outputs.new_version }} EOF # Output for GitHub Actions echo "RELEASE_NOTES<> $GITHUB_OUTPUT cat release_notes.md >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT - name: Create and push tag run: | # Check if tag already exists if git rev-parse "v${{ steps.version.outputs.new_version }}" >/dev/null 2>&1; then echo "Tag v${{ steps.version.outputs.new_version }} already exists, skipping tag creation" else 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 }}" fi - name: Push changes to main run: | if git push origin HEAD:main 2>/dev/null; then echo "✅ Successfully pushed to main branch" else echo "⚠️ Could not push to main (protected branch). This is expected." echo "📝 Version bump and tag were created successfully." fi - name: Publish to NPM env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} run: | VERSION="${{ steps.version.outputs.new_version }}" if [[ "$VERSION" == *"alpha"* ]] || [[ "$VERSION" == *"beta"* ]]; then echo "Publishing prerelease version with --tag alpha" npm publish --tag alpha else echo "Publishing stable version with --tag latest" npm publish --tag latest fi - name: Create GitHub Release uses: softprops/action-gh-release@v2 with: tag_name: v${{ steps.version.outputs.new_version }} name: "BMad Method v${{ steps.version.outputs.new_version }}" body: | ${{ steps.release_notes.outputs.RELEASE_NOTES }} draft: false prerelease: ${{ contains(steps.version.outputs.new_version, 'alpha') || contains(steps.version.outputs.new_version, 'beta') }} - name: Summary run: | echo "## 🎉 Successfully released v${{ steps.version.outputs.new_version }}!" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### 📦 Distribution" >> $GITHUB_STEP_SUMMARY echo "- **NPM**: Published with @latest tag" >> $GITHUB_STEP_SUMMARY echo "- **GitHub Release**: https://github.com/bmad-code-org/BMAD-METHOD/releases/tag/v${{ steps.version.outputs.new_version }}" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### ✅ Installation" >> $GITHUB_STEP_SUMMARY echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY echo "npx bmad-method@${{ steps.version.outputs.new_version }} install" >> $GITHUB_STEP_SUMMARY echo "\`\`\`" >> $GITHUB_STEP_SUMMARY