Skip to content

Commit 028430c

Browse files
JohnMcLearclaude
andauthored
ci: migrate npm publish to OIDC trusted publishing (#983)
The npmpublish.yml workflow was authenticating via a stored NPM_TOKEN secret that recently started failing E404 on PUT — first observed after #981 merged at 6.1.1 (run 26279691349). Same E404 pattern that hit ep_hljs four days ago. Stored publish tokens have two failure modes that this PR removes entirely: 1. They expire / get rotated and silently break automated publishes. 2. They survive in compromised CI logs / forks long enough to be abused. OIDC trusted publishing exchanges a short-lived GitHub-issued id-token for a per-publish credential at the registry. No secret on our side, no expiry, and the resulting publish is attested with `--provenance` so the npm package page shows the signing GHA run. Removes: - "Set publishing config" step that consumed secrets.NPM_TOKEN - "Add package to etherpad organization" step (the access grant is idempotent and was set at initial publish; it doesn't need to run on every release and the OIDC credential isn't authorised for it) Adds: - `permissions: { contents: write, id-token: write }` on the publish job (contents:write was already implicit via GITHUB_TOKEN for the version-bump push; id-token:write is the OIDC enabler) - `registry-url` on setup-node so the auth header lands at npmjs.org - `--no-git-checks` on pnpm publish (skip the dirty-tree guard that would otherwise trip on the just-pushed version-bump commit) - `--provenance` for the signing attestation One-time setup required on https://www.npmjs.com/package/ueberdb2/access before this lands — Trusted Publishers → Add → Provider: GitHub Actions, Org: ether, Repo: ueberDB, Workflow: npmpublish.yml, Environment: blank. Documented at the top of the publish-npm job. Bumps the publish-job pnpm pin from 10 to 11 to match the test job; trusted publishing requires pnpm >= 10.4 either way. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 11ac0b8 commit 028430c

1 file changed

Lines changed: 25 additions & 16 deletions

File tree

‎.github/workflows/npmpublish.yml‎

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,18 @@ jobs:
5656
needs:
5757
- test
5858
runs-on: ubuntu-latest
59+
# OIDC trusted publishing: npm exchanges the GitHub-issued `id-token`
60+
# for a short-lived publish credential at the registry, so there is no
61+
# stored NPM_TOKEN to expire or rotate. `contents: write` is needed for
62+
# the auto-bump commit + tag push.
63+
#
64+
# One-time setup on https://www.npmjs.com/package/ueberdb2/access:
65+
# Trusted Publishers → Add → Provider: GitHub Actions
66+
# Org: ether, Repo: ueberDB, Workflow filename: npmpublish.yml
67+
# Environment: (blank)
68+
permissions:
69+
contents: write
70+
id-token: write
5971
steps:
6072
- uses: actions/checkout@v6
6173
with:
@@ -64,11 +76,12 @@ jobs:
6476
- uses: actions/setup-node@v6
6577
with:
6678
node-version: 24
79+
registry-url: 'https://registry.npmjs.org'
6780

6881
- name: Install pnpm
6982
uses: pnpm/action-setup@v5
7083
with:
71-
version: 10
84+
version: 11
7285
run_install: false
7386

7487
- name: Get pnpm store directory
@@ -89,11 +102,6 @@ jobs:
89102
# version.
90103
- run: pnpm install --frozen-lockfile # Workaround based on https://github.com/pnpm/pnpm/issues/3141
91104

92-
- name: Set publishing config
93-
run: pnpm config set '//registry.npmjs.org/:_authToken' "${NODE_AUTH_TOKEN}"
94-
env:
95-
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
96-
97105
- name: Bump version (patch)
98106
run: |
99107
LATEST_TAG=$(git describe --tags --abbrev=0) || exit 1
@@ -107,22 +115,23 @@ jobs:
107115
git push
108116
git push --follow-tags
109117
110-
# `npm publish` must come after `git push` otherwise there is a race
111-
# condition: If two PRs are merged back-to-back then master/main will be
118+
# `pnpm publish` must come after `git push` otherwise there is a race
119+
# condition: If two PRs are merged back-to-back then main will be
112120
# updated with the commits from the second PR before the first PR's
113-
# workflow has a chance to push the commit generated by `npm version
121+
# workflow has a chance to push the commit generated by `pnpm version
114122
# patch`. This causes the first PR's `git push` step to fail after the
115123
# package has already been published, which in turn will cause all future
116124
# workflow runs to fail because they will all attempt to use the same
117-
# already-used version number. By running `npm publish` after `git push`,
125+
# already-used version number. By running `pnpm publish` after `git push`,
118126
# back-to-back merges will cause the first merge's workflow to fail but
119127
# the second's will succeed.
120128
- name: Convert typescript and create dist folder
121129
run: pnpm run build
122130

123-
- run: pnpm publish
124-
125-
- name: Add package to etherpad organization
126-
run: npm access grant read-write etherpad:developers ueberdb2
127-
env:
128-
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
131+
# pnpm 10.4+ auto-discovers the GHA OIDC token via `id-token: write`
132+
# and exchanges it with npm for a publish credential — no NPM_TOKEN
133+
# secret involved. `--provenance` attaches the signed-by-GitHub
134+
# attestation that npm shows on the package page.
135+
# `--no-git-checks` skips the "working tree dirty" guard, which would
136+
# otherwise trip on the version-bump commit that's already been pushed.
137+
- run: pnpm publish --no-git-checks --provenance

0 commit comments

Comments
 (0)