diff --git a/.github/workflows/manual-release.yaml b/.github/workflows/manual-release.yaml deleted file mode 100644 index d532705..0000000 --- a/.github/workflows/manual-release.yaml +++ /dev/null @@ -1,169 +0,0 @@ -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 - -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 - - - 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: 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 "- **GitHub Release**: https://github.com/bmad-code-org/bmad-builder/releases/tag/v${{ steps.version.outputs.new_version }}" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..e5ac7e8 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,133 @@ +name: Release + +on: + workflow_dispatch: + inputs: + bump: + description: "Version bump type" + required: true + default: "patch" + type: choice + options: + - patch + - minor + - major + +concurrency: + group: release + cancel-in-progress: false + +permissions: + id-token: write + contents: write + +jobs: + release: + if: github.repository == 'bmad-code-org/bmad-builder' && github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + steps: + - name: Generate GitHub App token + id: app-token + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ secrets.RELEASE_APP_ID }} + private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }} + + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ steps.app-token.outputs.token }} + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version-file: ".nvmrc" + cache: "npm" + + - name: Configure git user + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Install dependencies + run: npm ci + + - name: Run validation + run: | + npm run format:check + npm run lint:md + + - name: Bump version + run: | + npm version ${{ inputs.bump }} -m "chore(release): v%s [skip ci]" + + - name: Capture new version + id: version + run: | + VERSION=$(node -p "require('./package.json').version") + echo "version=${VERSION}" >> $GITHUB_OUTPUT + echo "tag=v${VERSION}" >> $GITHUB_OUTPUT + + - name: Push version commit and tag + run: git push origin main --follow-tags + + - name: Install cosign + uses: sigstore/cosign-installer@v3 + + - name: Sign tag SHA with cosign (keyless) + run: | + TAG="${{ steps.version.outputs.tag }}" + SHA=$(git rev-parse "${TAG}") + printf '%s' "${SHA}" > "${TAG}.sha" + cosign sign-blob --yes \ + --output-signature "${TAG}.sig" \ + --output-certificate "${TAG}.pem" \ + "${TAG}.sha" + + - name: Create GitHub Release + run: | + TAG="${{ steps.version.outputs.tag }}" + VERSION="${{ steps.version.outputs.version }}" + BODY=$(awk -v ver="$VERSION" ' + /^## \[/ { if (found) exit; if (index($0, "## [" ver "]")) found=1; next } + found { print } + ' CHANGELOG.md) + if [ -z "$BODY" ]; then + echo "::error::No CHANGELOG.md entry found for $TAG. Add a '## [${VERSION}] - YYYY-MM-DD' section before releasing." + exit 1 + fi + gh release create "$TAG" \ + --title "BMad Builder $TAG" \ + --notes "$BODY" \ + "${TAG}.sig" \ + "${TAG}.pem" \ + "${TAG}.sha" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Notify Discord + if: success() + continue-on-error: true + run: | + set -o pipefail + source .github/scripts/discord-helpers.sh + [ -z "$WEBHOOK" ] && exit 0 + TAG="${{ steps.version.outputs.tag }}" + RELEASE_URL="${{ github.server_url }}/${{ github.repository }}/releases/tag/${TAG}" + MSG=$(printf '🛠️ **[BMad Builder %s released](<%s>)**' "$TAG" "$RELEASE_URL" | esc) + jq -n --arg content "$MSG" '{content: $content}' | curl -sf --retry 2 -X POST "$WEBHOOK" -H "Content-Type: application/json" -d @- + env: + WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} + + - name: Summary + run: | + TAG="${{ steps.version.outputs.tag }}" + SHA=$(git rev-parse "${TAG}") + { + echo "## Released ${TAG}" + echo "" + echo "- **GitHub Release:** https://github.com/${{ github.repository }}/releases/tag/${TAG}" + echo "- **Tag SHA (cosign-signed):** \`${SHA}\`" + echo "- **Signature artifacts:** \`${TAG}.sig\`, \`${TAG}.pem\`, \`${TAG}.sha\` attached to the release" + } >> $GITHUB_STEP_SUMMARY diff --git a/CHANGELOG.md b/CHANGELOG.md index 70d0651..c4bf04a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [1.7.0] - 2026-04-23 + +### 📚 Documentation + +* **Customization authoring flow awareness** — `explanation/customization-for-authors.md` and `how-to/make-a-skill-customizable.md` now mention `bmad-customize`, the conversational authoring helper that walks users through scope selection, override writing, and merge verification. Guides authors to pick field names and defaults that read well in that flow, while preserving that hand-writing TOML still works for users who prefer it (#78) + ## [1.6.0] - 2026-04-20 ### 🎁 Features diff --git a/package.json b/package.json index 6d96e48..9296680 100644 --- a/package.json +++ b/package.json @@ -30,12 +30,7 @@ "lint": "eslint . --ext .js,.cjs,.mjs,.yaml --max-warnings=0", "lint:fix": "eslint . --ext .js,.cjs,.mjs,.yaml --fix", "lint:md": "markdownlint-cli2 \"**/*.md\"", - "prepare": "husky || exit 0", - "test": "npm run test:schemas && npm run test:refs && npm run validate:schemas && npm run lint && npm run lint:md && npm run format:check", - "test:refs": "node test/test-validate-file-refs.cjs", - "test:schemas": "node test/test-agent-schema.js", - "validate:refs": "node tools/validate-file-refs.mjs", - "validate:schemas": "node test/validate-agent-schema.js" + "prepare": "husky || exit 0" }, "lint-staged": { "*.{js,cjs,mjs}": [