Skip to content

feat: prepare release workflow for OIDC trusted publishing - #567

Open
AndreLars wants to merge 1 commit into
mainfrom
fna-1654-oidc-prep
Open

AndreLars wants to merge 1 commit into
mainfrom
fna-1654-oidc-prep

Conversation

@AndreLars

@AndreLars AndreLars commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

FNA-1654 · blocked release: FNA-1653 · registration request: SSCHELP-3009 · npm publishing guide

Important

This does not make the release work on its own. Publishing stays broken until the six trusted-publisher entries are registered on npmjs.org, which needs a package-owner login and is the other half of FNA-1654.

Status (2026-09-30): SSC has set up a JFrog OIDC provider for the twilio-labs org (github-actions-twilio-labs), which is for curated dependency resolution, not publishing. The npm trusted-publisher registration for all six packages is still outstanding and being chased in SSCHELP-3009.

Why

The NPM_TOKEN secret is expired and cannot be rotated — long-lived npm tokens are no longer permitted. So keyless publishing via GitHub OIDC is not a nice-to-have follow-up any more, it's the only route to releasing. twilio-run@6.0.0 and five other packages are sitting unpublished behind this.

This is the workflow half. It needs no npm account access and is safe to merge ahead of registration.

Changes

Split the release job in two. release opens the version PR exactly as before; a new publish job does the publishing. This matters because the production approval gate has to sit on the publish job only. Left as one job, every merge into main would wait on a reviewer just to open a version PR.

publish job: id-token: write, Node 24, and an explicit npm i -g npm@11. OIDC trusted publishing needs npm ≥ 11.5.1, and Node 24 does not bundle a new enough npm in every release, so the minimum is installed rather than assumed. This replaces the npm i -g npm@10 pin, which dated to the Node 16 era (8f0d104) and capped npm below the minimum — it had gone from vestigial to actively blocking.

Removed the token plumbing: the registry-url added in #566, plus the NPM_TOKEN / NODE_AUTH_TOKEN env vars. Those exist to make a token-based publish work. Under OIDC the .npmrc _authToken line they produce is actively harmful, because npm would try a dead credential instead of exchanging its OIDC token. Publishing targets registry.npmjs.org, which is npm's default; curated Artifactory is for resolving dependencies, not a publish target.

Explicit permissions blocks. Worth a careful look: an explicit block replaces the repository defaults, so every scope has to be listed. release needs contents: write and pull-requests: write to push the branch and open the PR; publish needs contents: write for the tag push and id-token: write for OIDC.

What this PR does not do

  • Register the trusted publishers. Six entries on npmjs.org, one per package, bound to this repo, on-merge-main.yml, and the production environment. Needs a login as twilio-labs-ci or twilio-serverless. All six packages already exist on npm, so the guide's one-time manual seed publish does not apply. Requested in SSCHELP-3009.
  • Create the production environment protection rules. The job references the environment, but required reviewers have to be set separately (gh api --method PUT repos/twilio-labs/serverless-toolkit/environments/production). Until they are, the environment exists without a gate and publishing is not paused. Note the wait timer is in minutes — leave it at 0.
  • Adopt curated Artifactory resolution. Deliberately out of scope. If it's added later, the guide's ordering caveat applies: an artifactory-oidc step must run after setup-node, with provider-name: github-actions-twilio-labs (the action defaults to github-actions, which is not configured for this org). Keep it out of the publish job: it writes an Artifactory registry= into ~/.npmrc, and changeset publish would then try to publish there.

Decision for reviewers

Adding required reviewers to production turns every release into a manual approval, where today it auto-publishes on merge. The guide recommends the gate. The job split means you can adopt it without gating version PRs, but it is still a real change to how the team ships.

Open question

Keyless publish with changesets is expected to work but I have not found it demonstrated. changeset publish shells out to npm publish per package and the OIDC exchange happens inside the npm CLI, so with npm ≥ 11.5.1 and a trusted publisher per package it should be fine. Worth noting the guide's monorepo section does not show a keyless multi-package publish; it recommends deferring. Suggest verifying with one package before assuming all six, and keeping a manual publish in reserve for the first release.

Testing

Workflow changes cannot be exercised from a PR branch: this workflow only runs on push to main. What I verified:

  • Parses as valid YAML, and the job graph is as intended: publish needs release, gated on needs.release.outputs.has_changesets == 'false', with environment: production
  • Both setup-node steps receive only {node-version: 24} — no registry-url survives except in an explanatory comment
  • Zero occurrences of NPM_TOKEN and npm@10 remain
  • The version-PR shell logic is unchanged from main, just moved behind an if: instead of the old if/else
  • Branch is a clean copy of origin/main (1669e74) with this single commit

🤖 Generated with Claude Code

FNA-1654

Long-lived npm tokens are no longer permitted, so the expired NPM_TOKEN
cannot be rotated and keyless publishing via GitHub OIDC is the only
route to releasing. This is the workflow half of that change, which
needs no npm account access and is safe to merge before the
trusted-publisher entries are registered on npmjs.org.

Split the single release job in two. The `release` job opens the version
PR as before. A new `publish` job does the publishing, so that the
`production` approval gate applies only to actual releases rather than
to every merge into main.

The publish job declares id-token: write, runs on Node 24, and installs
npm 11 explicitly, since OIDC trusted publishing requires npm 11.5.1 or
newer and Node 24 does not bundle a new enough npm in every release.
This replaces the npm@10 pin, which dated to the Node 16 era and capped
npm below that minimum.

Dropped the registry-url added in #566 along with the NPM_TOKEN and
NODE_AUTH_TOKEN env vars. They exist to make a token-based publish work;
under OIDC the .npmrc _authToken line they produce would make npm try a
dead credential instead of exchanging its OIDC token.

Publishing does not work until the six trusted-publisher entries are
registered on npmjs.org. That is the remaining half of FNA-1654.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Sep 21, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: c44f4a6

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants