Skip to content

Commit 2633289

Browse files
committed
chore(release): rewrite release workflow with App auth and cosign signing
Replaces manual-release.yaml with release.yaml modeled on bmad-method's publish.yaml. Uses BMAD Release Bot App token for pushes to protected main, runs full `npm test` validation stack, signs tag SHA with cosign keyless via GitHub OIDC, and extracts release body from CHANGELOG.md using keep-a-changelog bracket format. Drops two broken steps from the old workflow: `npm run validate` (script does not exist) and `sed tools/installer/package.json` (path does not exist). Adds v1.7.0 CHANGELOG entry. First release under the new pipeline.
1 parent 7a48868 commit 2633289

3 files changed

Lines changed: 136 additions & 169 deletions

File tree

.github/workflows/manual-release.yaml

Lines changed: 0 additions & 169 deletions
This file was deleted.

.github/workflows/release.yaml

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
name: Release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
bump:
7+
description: "Version bump type"
8+
required: true
9+
default: "patch"
10+
type: choice
11+
options:
12+
- patch
13+
- minor
14+
- major
15+
16+
concurrency:
17+
group: release
18+
cancel-in-progress: false
19+
20+
permissions:
21+
id-token: write
22+
contents: write
23+
24+
jobs:
25+
release:
26+
if: github.repository == 'bmad-code-org/bmad-builder' && github.ref == 'refs/heads/main'
27+
runs-on: ubuntu-latest
28+
steps:
29+
- name: Generate GitHub App token
30+
id: app-token
31+
uses: actions/create-github-app-token@v2
32+
with:
33+
app-id: ${{ secrets.RELEASE_APP_ID }}
34+
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
35+
36+
- name: Checkout
37+
uses: actions/checkout@v4
38+
with:
39+
fetch-depth: 0
40+
token: ${{ steps.app-token.outputs.token }}
41+
42+
- name: Setup Node
43+
uses: actions/setup-node@v4
44+
with:
45+
node-version-file: ".nvmrc"
46+
cache: "npm"
47+
48+
- name: Configure git user
49+
run: |
50+
git config user.name "github-actions[bot]"
51+
git config user.email "github-actions[bot]@users.noreply.github.com"
52+
53+
- name: Install dependencies
54+
run: npm ci
55+
56+
- name: Run validation and tests
57+
run: npm test
58+
59+
- name: Bump version
60+
run: npm version ${{ inputs.bump }} -m "chore(release): v%s [skip ci]"
61+
62+
- name: Capture new version
63+
id: version
64+
run: |
65+
VERSION=$(node -p "require('./package.json').version")
66+
echo "version=${VERSION}" >> $GITHUB_OUTPUT
67+
echo "tag=v${VERSION}" >> $GITHUB_OUTPUT
68+
69+
- name: Push version commit and tag
70+
run: git push origin main --follow-tags
71+
72+
- name: Install cosign
73+
uses: sigstore/cosign-installer@v3
74+
75+
- name: Sign tag SHA with cosign (keyless)
76+
run: |
77+
TAG="${{ steps.version.outputs.tag }}"
78+
SHA=$(git rev-parse "${TAG}")
79+
printf '%s' "${SHA}" > "${TAG}.sha"
80+
cosign sign-blob --yes \
81+
--output-signature "${TAG}.sig" \
82+
--output-certificate "${TAG}.pem" \
83+
"${TAG}.sha"
84+
85+
- name: Create GitHub Release
86+
run: |
87+
TAG="${{ steps.version.outputs.tag }}"
88+
VERSION="${{ steps.version.outputs.version }}"
89+
BODY=$(awk -v ver="$VERSION" '
90+
/^## \[/ { if (found) exit; if (index($0, "## [" ver "]")) found=1; next }
91+
found { print }
92+
' CHANGELOG.md)
93+
if [ -z "$BODY" ]; then
94+
echo "::error::No CHANGELOG.md entry found for $TAG. Add a '## [${VERSION}] - YYYY-MM-DD' section before releasing."
95+
exit 1
96+
fi
97+
gh release create "$TAG" \
98+
--title "BMad Builder $TAG" \
99+
--notes "$BODY" \
100+
"${TAG}.sig" \
101+
"${TAG}.pem" \
102+
"${TAG}.sha"
103+
env:
104+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
105+
106+
- name: Notify Discord
107+
if: success()
108+
continue-on-error: true
109+
run: |
110+
set -o pipefail
111+
source .github/scripts/discord-helpers.sh
112+
[ -z "$WEBHOOK" ] && exit 0
113+
TAG="${{ steps.version.outputs.tag }}"
114+
RELEASE_URL="${{ github.server_url }}/${{ github.repository }}/releases/tag/${TAG}"
115+
MSG=$(printf '🛠️ **[BMad Builder %s released](<%s>)**' "$TAG" "$RELEASE_URL" | esc)
116+
jq -n --arg content "$MSG" '{content: $content}' | curl -sf --retry 2 -X POST "$WEBHOOK" -H "Content-Type: application/json" -d @-
117+
env:
118+
WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
119+
120+
- name: Summary
121+
run: |
122+
TAG="${{ steps.version.outputs.tag }}"
123+
SHA=$(git rev-parse "${TAG}")
124+
{
125+
echo "## Released ${TAG}"
126+
echo ""
127+
echo "- **GitHub Release:** https://github.com/${{ github.repository }}/releases/tag/${TAG}"
128+
echo "- **Tag SHA (cosign-signed):** \`${SHA}\`"
129+
echo "- **Signature artifacts:** \`${TAG}.sig\`, \`${TAG}.pem\`, \`${TAG}.sha\` attached to the release"
130+
} >> $GITHUB_STEP_SUMMARY

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## [1.7.0] - 2026-04-23
4+
5+
### 📚 Documentation
6+
7+
* **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)
8+
39
## [1.6.0] - 2026-04-20
410

511
### 🎁 Features

0 commit comments

Comments
 (0)