Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions .github/workflows/draft.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,19 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PublishBetaPackages:
uses: ./.github/workflows/publish.yml
runs-on: ubuntu-latest
timeout-minutes: 5
if: github.event_name == 'push'
permissions:
contents: write
with:
tag_name: ${{ needs.PublishBetaRelease.outputs.tag_name }}
target_commitish: ${{ github.sha }}
secrets:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
actions: write
steps:
- name: Dispatch publish workflow
run: |-
gh workflow run publish.yml --repo ${{ github.repository }} \
-f tag_name="${{ needs.PublishBetaRelease.outputs.tag_name }}" \
-f target_commitish="${{ github.sha }}"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
needs:
- PublishBetaRelease
UpdateReleaseDraft:
Expand Down
16 changes: 4 additions & 12 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,21 @@ name: Publish Release
release:
types:
- published
workflow_call:
workflow_dispatch:
inputs:
tag_name:
required: true
type: string
target_commitish:
required: true
type: string
secrets:
NPM_TOKEN:
required: true
jobs:
PublishPackages:
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: write
id-token: write
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All @@ -33,11 +31,11 @@ jobs:
- name: Install Node
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 24
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 9
version: 10
- name: Install Dependencies
run: pnpm install --no-frozen-lockfile
- name: Run Build
Expand All @@ -50,10 +48,6 @@ jobs:
(cd packages/lib && npm version --no-git-tag-version ${{ inputs.tag_name || github.event.release.tag_name }})
(cd packages/cli && npm version --no-git-tag-version ${{ inputs.tag_name || github.event.release.tag_name }})
(cd packages/actions && npm version --no-git-tag-version ${{ inputs.tag_name || github.event.release.tag_name }})
- name: Setup npm auth
run: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Publish packages
run: |-
TAG_NAME="${{ inputs.tag_name || github.event.release.tag_name }}"
Expand All @@ -67,8 +61,6 @@ jobs:
echo "Publishing with latest tag"
pnpm -r publish --access public --no-git-checks
fi
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
CommitVersionBump:
runs-on: ubuntu-latest
timeout-minutes: 20
Expand Down
37 changes: 25 additions & 12 deletions workflows/draft.wac.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {
Workflow,
NormalJob,
ReusableWorkflowCallJob,
Step,
expressions as ex,
dedentString,
} from '../packages/lib/src/index.js'

const betaReleaseStep = new Step({
Expand Down Expand Up @@ -34,20 +34,33 @@ const betaReleaseJob = new NormalJob('PublishBetaRelease', {
},
}).addStep(betaReleaseStep)

const publishBetaJob = new ReusableWorkflowCallJob('PublishBetaPackages', {
uses: './.github/workflows/publish.yml',
// Dispatches publish.yml instead of calling it as a reusable workflow: npm
// trusted publishing (OIDC) validates the top-level workflow's filename
// against the package's single trusted publisher, which is publish.yml.
// GITHUB_TOKEN-triggered events don't start workflows, but workflow_dispatch
// is exempt from that rule.
const publishBetaJob = new NormalJob('PublishBetaPackages', {
'runs-on': 'ubuntu-latest',
'timeout-minutes': 5,
if: "github.event_name == 'push'",
permissions: {
contents: 'write',
},
with: {
tag_name: ex.expn(`needs.${betaReleaseJob.name}.outputs.tag_name`),
target_commitish: ex.expn('github.sha'),
},
secrets: {
NPM_TOKEN: ex.secret('NPM_TOKEN'),
actions: 'write',
},
}).needs([betaReleaseJob])
})
.addStep(
new Step({
name: 'Dispatch publish workflow',
run: dedentString(`
gh workflow run publish.yml --repo ${ex.expn('github.repository')} \\
-f tag_name="${ex.expn(`needs.${betaReleaseJob.name}.outputs.tag_name`)}" \\
-f target_commitish="${ex.expn('github.sha')}"
`),
env: {
GH_TOKEN: ex.secret('GITHUB_TOKEN'),
},
}),
)
.needs([betaReleaseJob])

const draftStep = new Step({
name: 'Draft next release',
Expand Down
32 changes: 14 additions & 18 deletions workflows/publish.wac.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ const checkout = new Step({
const installNode = new Step({
name: 'Install Node',
uses: 'actions/setup-node@v4',
with: { 'node-version': 20 },
// npm trusted publishing (OIDC) requires Node >= 22.14
with: { 'node-version': 24 },
})

const installPnpm = new Step({
name: 'Install pnpm',
uses: 'pnpm/action-setup@v4',
with: { version: 9 },
// pnpm 10 supports OIDC trusted publishing; reads the same v9 lockfile
with: { version: 10 },
})

const installDependencies = new Step({
Expand All @@ -54,14 +56,10 @@ const bumpVersions = new Step({
`),
})

const setupNpmAuth = new Step({
name: 'Setup npm auth',
run: 'echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc',
env: {
NPM_TOKEN: ex.secret('NPM_TOKEN'),
},
})

// Auth is handled by npm trusted publishing (OIDC): the job's id-token
// permission lets pnpm mint a short-lived token from the runner's OIDC
// identity. The trusted publisher configured on npmjs.com must reference
// this workflow file (publish.yml).
const publishPackages = new Step({
name: 'Publish packages',
run: dedentString(`
Expand All @@ -77,16 +75,14 @@ const publishPackages = new Step({
pnpm -r publish --access public --no-git-checks
fi
`),
env: {
NPM_TOKEN: ex.secret('NPM_TOKEN'),
},
})

const publishJob = new NormalJob('PublishPackages', {
'runs-on': 'ubuntu-latest',
'timeout-minutes': 20,
permissions: {
contents: 'write',
'id-token': 'write',
},
}).addSteps([
checkout,
Expand All @@ -95,7 +91,6 @@ const publishJob = new NormalJob('PublishPackages', {
installDependencies,
build,
bumpVersions,
setupNpmAuth,
publishPackages,
])

Expand Down Expand Up @@ -139,14 +134,15 @@ export const publishWorkflow = new Workflow('publish', {
release: {
types: ['published'],
},
workflow_call: {
// Dispatched (not workflow_call) by draft.yml for beta releases: npm
// trusted publishing validates the top-level workflow's filename, and a
// package can only have one trusted publisher — so every publish must
// run with publish.yml as the top-level workflow.
workflow_dispatch: {
inputs: {
tag_name: { required: true, type: 'string' },
target_commitish: { required: true, type: 'string' },
},
secrets: {
NPM_TOKEN: { required: true },
},
},
},
}).addJobs([publishJob, commitVersionBumpJob])
Loading