-
Notifications
You must be signed in to change notification settings - Fork 0
Integrate OIDC Trusted Publisher auth and modernize CI workflows #206
Description
Summary
Replace the long-lived NPM_TOKEN secret in the publish workflow with keyless OIDC-based authentication (npm Trusted Publishers), upgrade all GitHub Actions to current versions, add npm provenance attestation, and modernize the Node.js CI matrix.
This mirrors the changes made in bacon-ipsum-cli PR #58 and subsequent Node 24 commit.
Manual prerequisite (not automatable): Before merging, the repo owner must register the Trusted Publisher on npmjs.com under the package's Settings → Trusted Publisher, pointing to this repository and workflow filename (
publish.yaml). The environment field should be left blank.
Background: How OIDC Trusted Publishers Work
npm's Trusted Publishers feature uses GitHub's OIDC (OpenID Connect) tokens to authenticate npm publish without any stored secrets. Here's how it works:
- The workflow requests an OIDC identity token from GitHub (enabled by
permissions: id-token: write) actions/setup-nodewithregistry-url: 'https://registry.npmjs.org'automatically configures npm to use this OIDC token whenid-token: writeis granted- npm verifies the token against the Trusted Publisher configuration registered on npmjs.com
- No
NPM_TOKENsecret is needed — the token is short-lived and scoped to the workflow run
Key requirement: Node.js >= 22.14 is required for OIDC provenance support in npm. We use Node 24 in the publish workflow.
The --provenance flag on npm publish generates a SLSA provenance attestation that cryptographically links the published package to its source repo and build.
Changes Required
1. Modify .github/workflows/publish.yaml
Note: This repo uses
.yamlextension (not.yml) for the publish workflow.
Current file:
name: 'Publish to NPM'
on:
workflow_run:
workflows: ['Node.js CI']
types: [completed]
branches: [master,main]
jobs:
publish-new-version:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: '0'
- name: git setup
run: |
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
- name: setup node
uses: actions/setup-node@v3
with:
node-version: 20.x
registry-url: 'https://registry.npmjs.org'
- name: npm install
run: npm ci
- name: Should release
id: should_release
continue-on-error: true
run: npm run should-release -- -v
- name: No release
if: steps.should_release.outcome != 'success'
run: echo "No release required. Skipping publishing."
- name: Version bump
if: steps.should_release.outcome == 'success'
run: npm run release
- name: Publish to NPM
if: steps.should_release.outcome == 'success'
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Push commits to GitHub
if: steps.should_release.outcome == 'success'
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ github.ref }}
tags: true
force: trueTarget file:
name: 'Publish to NPM'
on:
workflow_run:
workflows: ['Node.js CI']
types: [completed]
branches: [master,main]
permissions:
contents: write
id-token: write
jobs:
publish-new-version:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: '0'
- name: git setup
run: |
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
- name: setup node
uses: actions/setup-node@v6
with:
node-version: '24'
registry-url: 'https://registry.npmjs.org'
cache: 'npm'
- name: npm install
run: npm ci
- name: Should release
id: should_release
continue-on-error: true
run: npm run should-release -- -v
- name: No release
if: steps.should_release.outcome != 'success'
run: echo "No release required. Skipping publishing."
- name: Version bump
if: steps.should_release.outcome == 'success'
run: npm run release
- name: Publish to NPM
if: steps.should_release.outcome == 'success'
run: npm publish --provenance
- name: Push commits to GitHub
if: steps.should_release.outcome == 'success'
uses: ad-m/github-push-action@v1.0.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ github.ref }}
tags: true
force: trueSummary of publish.yaml changes:
- Add
permissions:block at workflow level:contents: write+id-token: write actions/checkout@v3→actions/checkout@v6actions/setup-node@v3→actions/setup-node@v6node-version: 20.x→node-version: '24'- Add
cache: 'npm'toactions/setup-node npm publish→npm publish --provenance- Remove the entire
env:block withNODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}from the Publish step ad-m/github-push-action@master→ad-m/github-push-action@v1.0.0- Preserve existing
force: trueon the push action
2. Modify .github/workflows/test.yaml
Current file:
name: Node.js CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x,20.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run lint
- run: npm run build --if-present
- run: npm testTarget file:
name: Node.js CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20.x,22.x]
steps:
- uses: actions/checkout@v6
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run build --if-present
- run: npm testSummary of test.yaml changes:
- Add
permissions: contents: readat workflow level actions/checkout@v3→actions/checkout@v6actions/setup-node@v3→actions/setup-node@v6- Add
cache: 'npm'toactions/setup-node - Node matrix
[18.x,20.x]→[20.x,22.x](drop EOL Node 18, add Node 22 LTS) - Preserve existing
npm run lintandnpm run build --if-presentsteps