Skip to content

Commit 66e19e2

Browse files
styflevercel[bot]
andauthored
ci: set up npm trusted publishing (#213)
Publishes `@vercel/webpack-asset-relocator-loader` to npm via [trusted publishing](https://docs.npmjs.com/trusted-publishers) (GitHub Actions OIDC) instead of the long-lived `NPM_TOKEN_ELEVATED` secret. ## ⚠️ Required manual step before merging npm does **not** let you register a trusted publisher from CI — it has to be done in the npmjs.com UI, and until it exists the OIDC token exchange fails and `@semantic-release/npm` falls back to token auth (which this PR removes). So the next release after merge will fail unless this is done first. On the [package settings page](https://www.npmjs.com/package/@vercel/webpack-asset-relocator-loader/access), under **Trusted Publisher**, add a GitHub Actions publisher: | Field | Value | | --- | --- | | Organization or user | `vercel` | | Repository | `webpack-asset-relocator-loader` | | Workflow filename | `ci.yml` | | Environment name | *(leave blank)* | | Allowed actions | `npm publish` | These fields are case-sensitive and npm doesn't validate them at save time — mistakes only surface as `ENEEDAUTH` at publish time. Note the workflow filename is the file that runs the publish, which is `ci.yml` here, not a path. Once a release has published successfully, the `NPM_TOKEN_ELEVATED` secret can be deleted and Publishing access can be tightened to *Require two-factor authentication and disallow tokens* (that setting only affects token auth, so OIDC keeps working). ## Changes **`package.json`** - Added `publishConfig.access = "public"` so the scoped package keeps publishing publicly. - Bumped `semantic-release` `^17.3.0` → `^25.0.9`. OIDC token exchange landed in `@semantic-release/npm` v13.1.0, which is only pulled in by semantic-release v25. v13 also bundles npm 11.x, satisfying the npm >= 11.5.1 requirement regardless of the runner's npm. No change was needed to `repository` — npm normalizes the `vercel/webpack-asset-relocator-loader` shorthand to `git+https://github.com/vercel/webpack-asset-relocator-loader.git`, which is what the registry already has on record for v1.10.0 and what the OIDC repository check compares against. **`.github/workflows/ci.yml`** - Split the release out of the test matrix into its own `release` job gated on `needs: test` and push-to-main. This keeps `id-token: write` scoped to the publish step rather than granting it to every matrix leg on every PR. - Added an explicit permissions block: `contents: read` at the workflow level, and on the release job `contents: write` (GitHub release + tag), `issues: write` / `pull-requests: write` (release comments), `id-token: write` (OIDC). - Removed `NPM_TOKEN`. `@semantic-release/npm` now calls `getIDToken("npm:registry.npmjs.org")` and exchanges it for a short-lived registry token; [`verify-auth.js`](https://github.com/semantic-release/npm/blob/master/lib/verify-auth.js) returns early on success and never reads `NPM_TOKEN`. - Added `fetch-depth: 0` to the release checkout, per the semantic-release GitHub Actions recipe. - **Bumped the test matrix from Node 18 to Node 22.** This one is forced rather than chosen: semantic-release v25 declares `engines.node: ^22.14.0 || >= 24.10.0`, and yarn v1 hard-errors (`Found incompatible module`) on an engine mismatch rather than warning — so leaving the matrix on Node 18 breaks `yarn install` on every leg. npm trusted publishing itself also requires Node >= 22.14.0. Node 18 went EOL in April 2025. If you'd rather keep Node 18 test coverage, the alternative is `yarn install --ignore-engines` in the test job — happy to switch. Provenance attestations are generated automatically for public packages published from a public repo over OIDC, so no `--provenance` flag or `publishConfig.provenance` is needed. ## Verification - `yarn test` — 85/85 passing on Node 22. - Confirmed the installed tree is `semantic-release@25.0.9` / `@semantic-release/npm@13.1.5` with npm `11.19.0` hoisted, and that the plugin's `trusted-publishing/token-exchange.js` reads the Actions OIDC token that `id-token: write` provides. - Workflow YAML parsed and asserted: two jobs, correct permissions, no remaining `NPM_TOKEN` reference. The end-to-end publish can't be exercised from a PR — OIDC only works on `push` to `main` — so the first real validation is the next release. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com> Co-authored-by: Steven <229881+styfle@users.noreply.github.com>
1 parent 295d101 commit 66e19e2

3 files changed

Lines changed: 2147 additions & 2973 deletions

File tree

.github/workflows/ci.yml

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,17 @@ on:
88
- "!*"
99
pull_request:
1010

11+
permissions:
12+
contents: read
13+
1114
jobs:
1215
test:
1316
name: Node ${{ matrix.node }} and ${{ matrix.os }}
1417
strategy:
1518
fail-fast: false
1619
matrix:
1720
os: [ubuntu-latest, macos-latest, windows-latest]
18-
node: [18]
21+
node: [22]
1922
runs-on: ${{ matrix.os }}
2023
steps:
2124
- uses: actions/checkout@v4
@@ -38,9 +41,28 @@ jobs:
3841
- name: Coverage
3942
if: matrix.os == 'ubuntu-latest'
4043
run: yarn test-coverage
44+
45+
release:
46+
name: Release
47+
needs: test
48+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
49+
runs-on: ubuntu-latest
50+
permissions:
51+
contents: write # to create the GitHub release and push the tag
52+
issues: write # to comment on released issues
53+
pull-requests: write # to comment on released pull requests
54+
id-token: write # to use OIDC for npm trusted publishing and provenance
55+
steps:
56+
- uses: actions/checkout@v4
57+
with:
58+
fetch-depth: 0
59+
- name: Use Node.js
60+
uses: actions/setup-node@v4
61+
with:
62+
node-version: 22
63+
- name: Install Dependencies
64+
run: yarn install
4165
- name: Release
42-
if: matrix.os == 'ubuntu-latest' && matrix.node == 18 && github.event_name == 'push' && github.ref == 'refs/heads/main'
4366
env:
4467
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
45-
NPM_TOKEN: ${{ secrets.NPM_TOKEN_ELEVATED }}
4668
run: yarn semantic-release

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
"files": [
1414
"src/*"
1515
],
16+
"publishConfig": {
17+
"access": "public"
18+
},
1619
"dependencies": {
1720
"@mapbox/node-pre-gyp": "^2.0.0",
1821
"acorn": "^8.3.0",
@@ -35,7 +38,7 @@
3538
"@vercel/ncc": "^0.38.1",
3639
"jest": "^26.6.3",
3740
"memory-fs": "^0.4.1",
38-
"semantic-release": "^17.3.0",
41+
"semantic-release": "^25.0.9",
3942
"socket.io-client": "^2.2.0",
4043
"webpack": "^5",
4144
"webpack-cli": "^4"

0 commit comments

Comments
 (0)