From 4ee4afe098b2ae9f28b35c1294aadf011df76ef7 Mon Sep 17 00:00:00 2001 From: Francesco Carrella Date: Mon, 15 Jun 2026 05:52:33 +0200 Subject: [PATCH] ci: publish via npm Trusted Publishing (OIDC), drop npm token Replace the NPM_TOKEN-based release with token-less publishing through GitHub OIDC. Remove the setup-node registry-url (it writes an _authToken .npmrc that npm prefers over the OIDC exchange), install npm>=11.5.1 (pnpm delegates the publish to the npm CLI, which performs the exchange), and enable provenance. Add RELEASING.md. --- .github/workflows/release.yml | 16 +++++++-- RELEASING.md | 62 +++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 RELEASING.md diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5d9010c..b0f1be9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,3 +1,10 @@ +# Publishes `canup` to npm via Changesets + npm Trusted Publishing (OIDC). +# +# No npm token is used. Authentication happens through GitHub's OIDC token, which +# npm exchanges for a short-lived publish credential (requires `id-token: write` +# and a trusted publisher configured for this package on npmjs.com — see +# RELEASING.md). Provenance is generated automatically because this is a public +# repository. name: Release on: push: @@ -17,7 +24,12 @@ jobs: with: node-version: 22 cache: pnpm - registry-url: 'https://registry.npmjs.org' + # No `registry-url`: it writes an .npmrc with `_authToken=${NODE_AUTH_TOKEN}` + # that npm prefers over the OIDC token exchange, breaking trusted publishing. + # Runners bundle an older npm; trusted publishing needs npm >= 11.5.1, and + # pnpm delegates the publish + OIDC exchange to the npm CLI. + - name: Use npm >= 11.5.1 + run: npm install -g npm@latest - run: pnpm install --frozen-lockfile - run: pnpm run build - run: pnpm run test @@ -27,4 +39,4 @@ jobs: version: pnpm changeset version env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + NPM_CONFIG_PROVENANCE: true diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 0000000..01989ba --- /dev/null +++ b/RELEASING.md @@ -0,0 +1,62 @@ +# Releasing + +Releases are automated with [Changesets](https://github.com/changesets/changesets) +and [npm Trusted Publishing](https://docs.npmjs.com/trusted-publishers) (OIDC). +**No npm token is involved** — GitHub Actions authenticates to npm via a +short-lived OIDC credential, and packages are published with +[provenance](https://docs.npmjs.com/generating-provenance-statements). + +## For contributors + +If your change affects published behavior, add a changeset in the same PR: + +```sh +pnpm changeset +``` + +Pick the bump type (patch / minor / major) and write a short, user-facing +summary. CI reminds you if a PR is missing one. + +That's it — you don't publish anything. Maintainers merge the automated release +PR (below) when it's time to ship. + +## How a release happens + +1. PRs merge to `main`, each carrying a changeset. +2. The release workflow opens (and keeps updating) a **"Version Packages"** PR + that bumps the version and updates `CHANGELOG.md`. +3. Merging that PR publishes the new version to npm — with provenance, no token. + +## Maintainer setup (one-time) + +npm Trusted Publishing requires the package to exist before a trusted publisher +can be attached, so the very first release is published manually; every release +after that is automated. + +1. **First publish (once, requires npm 2FA):** + + ```sh + pnpm install --frozen-lockfile + pnpm run build + npm publish --access public + ``` + +2. **Configure the trusted publisher** at + → **Trusted Publisher** → + **GitHub Actions**: + + | Field | Value | + |-------|-------| + | Organization or user | `sparkncraft` | + | Repository | `canup` | + | Workflow filename | `release.yml` *(filename only, not a path)* | + | Environment | *(leave blank)* | + +After this, no token is needed and the `release.yml` workflow publishes on its +own. Any previously configured `NPM_TOKEN` secret can be deleted. + +## Requirements (handled by the workflow) + +- npm **≥ 11.5.1** and Node **≥ 22.14.0** — the workflow installs `npm@latest` + because runners ship an older npm and pnpm delegates the publish to the npm CLI. +- `id-token: write` permission on the release job.