Skip to content

ci: publish to npm via OIDC trusted publishing - #294

Open
shahzaib-sheikh wants to merge 2 commits into
mainfrom
shahzaib/bfe-934-npm-oidc
Open

shahzaib-sheikh wants to merge 2 commits into
mainfrom
shahzaib/bfe-934-npm-oidc

Conversation

@shahzaib-sheikh

@shahzaib-sheikh shahzaib-sheikh commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

What

Moves @bluefin-exchange/pro-sdk off secrets.NPM_TOKEN onto npm OIDC trusted publishing.

Part of the org-wide move off npm tokens (BFE-934), prompted by the 7k SDK publish failures.
Already proven end to end: @ember-finance/sdk@2.10.4 published this way with no token
(ember-sdk#84).

Merging is safe; the next release needs npmjs.com config

Publishing only happens on a ts-release-* / ts-pre-release-* tag, so nothing publishes on
merge
. But the next release will fail unless a @bluefin-exchange npm org owner adds, on
@bluefin-exchange/pro-sdk → Settings → Trusted publisher:

Field Value
Publisher GitHub Actions
Organization fireflyprotocol
Repository pro-sdk
Workflow filename npm_publish.yaml
Environment (leave empty)
Allowed actions npm publish

⚠️ The filename must match character for character. On ember-sdk it was registered as
publish_to_npm.yaml against a publish_to_npm.yml file and the publish failed with a bare
ENEEDAUTH — npm silently declines OIDC and reports having no credentials, with nothing in the
error naming OIDC or the filename. If a release fails that way, align the names rather than
bumping the version; a failed publish burns nothing.

npm_publish_prerelease.yaml is deleted — this is the important bit

It published the same package from a second workflow file. npm allows exactly one trusted
publisher per package, bound to one workflow filename, so only one of the two files could ever
have authorised — whichever wasn't registered would have started failing ENEEDAUTH the moment
the shared token went away. Its ts-pre-release-* trigger is folded into npm_publish.yaml:

Tag pushed dist-tag
ts-release-<version> latest
ts-pre-release-<version> pre-release
(workflow dispatch) your choice

The pre-release prefix is matched first, since both prefixes begin with ts-. Behaviour is
otherwise identical to the two separate files.

Changes

  • permissions: id-token: write; NODE_AUTH_TOKEN / secrets.NPM_TOKEN gone from both paths.
  • Node → 24. Trusted publishing requires >= 22.14.0; the release path was on 20, but the
    pre-release path already built this package on 24, so 24 is the better-evidenced choice.
  • npm install -g npm@latest — OIDC needs npm >= 11.5.1.
  • Strip the _authToken line from the npmrc after setup-node. registry-url
    unconditionally writes //registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN} and exports a
    dummy NODE_AUTH_TOKEN; npm then treats auth as configured and never attempts the OIDC
    exchange (setup-node#1551,
    npm/documentation#1960). Present on the successful ember-sdk run; repos here using setup-node@v7 publish fine without it, so treat it as belt-and-braces on v4/v6 rather than strictly required — it's a no-op when the line is absent.
  • Added workflow_dispatch (pre-release / latest) to retry a publish without cutting
    another tag.
  • Guards, since there's no token fallback and npm versions are immutable: the tag must end in
    ts/sdk/package.json's version, the version must not already be on npm, and a dispatch must
    name a commit reachable from origin/main.
  • concurrency group so two tag pushes can't race a publish.

yarn install --immutable / yarn build and the ts/sdk working directory are unchanged.

Provenance

Unlike the Ember repos (which are private), this repo is public, so npm attaches a
provenance attestation automatically under trusted publishing — a genuine supply-chain win. The
repository field in ts/sdk/package.json already matches
https://github.com/fireflyprotocol/pro-sdk.git, which provenance requires. I left provenance
at its default rather than forcing it on, so an attestation problem can't fail an otherwise-good
publish.

Note on the current version

ts/sdk/package.json is at 2.1.0, which is already on npm under pre-release (latest is
2.0.0). The new guard refuses to republish an existing version, so tagging ts-release-2.1.0
today fails with a clear message instead of an opaque npm conflict — the next release needs a
bump.

Verification

YAML parses, no token references remain, and the tag → dist-tag/version parsing is checked
against ts-release-2.1.0, ts-pre-release-2.1.0, ts-release-1.17.0 and
ts-pre-release-3.0.0-rc.1. The OIDC handshake itself can only be exercised by a real publish,
so the next release is the test — the dispatch path exists to retry it without burning a version.

Drops the NPM_TOKEN dependency from the @bluefin-exchange/pro-sdk publish path
in favour of npm trusted publishing (OIDC).

Node moves 20 -> 22 (trusted publishing needs >= 22.14.0) and npm is upgraded
in-job, since the OIDC flow needs npm >= 11.5.1.

Adds a workflow_dispatch path to retry a failed publish without cutting another
tag, guarded so it only publishes a commit reachable from origin/main. The
ts-release-<version> tag must match ts/sdk/package.json's version, and a version
already on npm is refused up front, since there is no token to fall back on and
npm versions are immutable.

This repo is public, so npm attaches a provenance attestation automatically
under trusted publishing; the package.json repository field already matches.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…rkflow

npm_publish_prerelease.yaml published the same package from a second workflow
file. npm allows one trusted publisher per package, bound to a single workflow
filename, so only one of the two could ever have authorised — the other would
have failed with ENEEDAUTH once the token was gone.

Folds its `ts-pre-release-*` tag trigger into npm_publish.yaml and deletes it.
The pre-release prefix is matched before the release prefix, since both begin
with "ts-".

Node is 24 rather than 22: the pre-release path already built this package on
24, so it is the better-evidenced choice for the release path too.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

1 participant