@@ -2,15 +2,20 @@ name: boxel-cli publish
22
33# Single workflow file that owns both publish paths for @cardstack/boxel-cli:
44#
5- # • `unstable` job — on every merge to main that touches packages/boxel-cli/**,
6- # regenerate plugin skill content, decide per-surface version bumps from the
7- # merged PR's title (conventional-commit prefix), commit the bumps back to
8- # main, tag, and publish `@cardstack/boxel-cli@<v>-unstable.<n>` to npm under
9- # dist-tag `unstable`.
5+ # • `unstable` job
6+ # - On push to main touching `packages/boxel-cli/**` — regenerate plugin
7+ # skill content, decide per-surface version bumps from the merged PR's
8+ # title (conventional-commit prefix), commit the bumps back to main,
9+ # tag, and publish `@cardstack/boxel-cli@<v>-unstable.<n>` under
10+ # dist-tag `unstable`.
11+ # - Via "Run workflow" with the `confirm` field left blank — skip the
12+ # bump/commit/tag dance and publish whatever version is currently in
13+ # `packages/boxel-cli/package.json` under dist-tag `unstable`. Fails
14+ # loudly if that version is already on npm (npm refuses to clobber).
1015#
11- # • `stable` job — manual workflow_dispatch that strips `-unstable.<n>` from the
12- # current version and publishes the resulting clean semver under dist-tag
13- # `latest`. The deliberate "cut a release" step.
16+ # • `stable` job — "Run workflow" with `confirm = promote`. Strips
17+ # `-unstable.<n>` from the current version and publishes the resulting
18+ # clean semver under dist-tag `latest`. The deliberate "cut a release" step.
1419#
1520# Both flows live in one file so they share a single npm Trusted-Publisher rule
1621# (registered against this filename). Splitting them into separate workflow files
3338 workflow_dispatch :
3439 inputs :
3540 confirm :
36- description : " Type 'promote' to confirm publishing the latest unstable to npm latest"
37- required : true
41+ description : " Leave blank to publish current main as unstable. Type 'promote' to strip -unstable.N and publish as latest. "
42+ required : false
3843 type : string
3944
4045permissions :
@@ -48,8 +53,16 @@ concurrency:
4853
4954jobs :
5055 unstable :
51- name : Regen, bump, publish unstable
52- if : github.event_name == 'push' && github.actor != 'github-actions[bot]'
56+ name : Publish unstable
57+ # Manual trigger is restricted to "Use workflow from: main" so the workflow
58+ # YAML interpreting the publish is always main's (defense in depth — the
59+ # checkout step below also pins `ref: main`).
60+ if : >-
61+ github.actor != 'github-actions[bot]'
62+ && (
63+ github.event_name == 'push'
64+ || (inputs.confirm == '' && github.ref == 'refs/heads/main')
65+ )
5366 runs-on : ubuntu-latest
5467 steps :
5568 - uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
6982
7083 - name : Fetch PR title from merge SHA
7184 id : pr
85+ if : github.event_name == 'push'
7286 env :
7387 GH_TOKEN : ${{ github.token }}
7488 run : |
@@ -94,15 +108,15 @@ jobs:
94108 echo "PR title: $PR_TITLE"
95109
96110 - name : Regenerate plugin synopsis and skills
97- if : steps.pr.outputs.skip != 'true'
111+ if : github.event_name == 'push' && steps.pr.outputs.skip != 'true'
98112 working-directory : packages/boxel-cli
99113 run : |
100114 pnpm run build:plugin
101115 pnpm run build:skills
102116
103117 - name : Compute release
104118 id : release
105- if : steps.pr.outputs.skip != 'true'
119+ if : github.event_name == 'push' && steps.pr.outputs.skip != 'true'
106120 working-directory : packages/boxel-cli
107121 env :
108122 PR_TITLE : ${{ steps.pr.outputs.title }}
@@ -122,7 +136,7 @@ jobs:
122136 echo "nextPlugin=$(echo "$RESULT" | jq -r '.nextPlugin // ""')" >> "$GITHUB_OUTPUT"
123137
124138 - name : Apply version bumps
125- if : steps.pr.outputs.skip != 'true' && (steps.release.outputs.npmBump != 'none' || steps.release.outputs.pluginBump != 'none')
139+ if : github.event_name == 'push' && steps.pr.outputs.skip != 'true' && (steps.release.outputs.npmBump != 'none' || steps.release.outputs.pluginBump != 'none')
126140 env :
127141 NEXT_NPM : ${{ steps.release.outputs.nextNpm }}
128142 NEXT_PLUGIN : ${{ steps.release.outputs.nextPlugin }}
@@ -151,7 +165,7 @@ jobs:
151165
152166 - name : Generate release notes
153167 id : notes
154- if : steps.pr.outputs.skip != 'true' && steps.release.outputs.npmBump != 'none'
168+ if : github.event_name == 'push' && steps.pr.outputs.skip != 'true' && steps.release.outputs.npmBump != 'none'
155169 env :
156170 GH_TOKEN : ${{ github.token }}
157171 NEW_TAG : boxel-cli-v${{ steps.release.outputs.nextNpm }}
@@ -195,7 +209,7 @@ jobs:
195209
196210 - name : Commit, tag, and push
197211 id : commit
198- if : steps.pr.outputs.skip != 'true'
212+ if : github.event_name == 'push' && steps.pr.outputs.skip != 'true'
199213 env :
200214 NEXT_NPM : ${{ steps.release.outputs.nextNpm }}
201215 NEXT_PLUGIN : ${{ steps.release.outputs.nextPlugin }}
@@ -226,7 +240,7 @@ jobs:
226240 echo "pushed=true" >> "$GITHUB_OUTPUT"
227241
228242 - name : Publish to npm
229- if : steps.pr.outputs.skip != 'true' && steps.release.outputs.npmBump != 'none'
243+ if : github.event_name == 'workflow_dispatch' || ( steps.pr.outputs.skip != 'true' && steps.release.outputs.npmBump != 'none')
230244 working-directory : packages/boxel-cli
231245 env :
232246 NODE_AUTH_TOKEN : ${{ secrets.NPM_TOKEN }}
@@ -264,7 +278,7 @@ jobs:
264278 pnpm publish --tag unstable --access public --provenance --no-git-checks
265279
266280 - name : Create GitHub Release (prerelease)
267- if : steps.pr.outputs.skip != 'true' && steps.release.outputs.npmBump != 'none' && steps.commit.outputs.tag != ''
281+ if : github.event_name == 'push' && steps.pr.outputs.skip != 'true' && steps.release.outputs.npmBump != 'none' && steps.commit.outputs.tag != ''
268282 env :
269283 GH_TOKEN : ${{ github.token }}
270284 TAG : ${{ steps.commit.outputs.tag }}
@@ -289,7 +303,10 @@ jobs:
289303
290304 stable :
291305 name : Promote latest unstable to stable
292- if : github.event_name == 'workflow_dispatch'
306+ # Any non-empty `confirm` routes here so the validation step below can
307+ # error loudly on a typo. Gating on `confirm == 'promote'` here would make
308+ # a typo skip both jobs and look like a successful no-op run.
309+ if : github.event_name == 'workflow_dispatch' && inputs.confirm != ''
293310 runs-on : ubuntu-latest
294311 steps :
295312 - name : Validate confirmation
0 commit comments