Skip to content

ci: release workflow publishing via npm trusted publishing - #49

Open
arekkubaczkowski wants to merge 1 commit into
mainfrom
ci/release-workflow
Open

ci: release workflow publishing via npm trusted publishing#49
arekkubaczkowski wants to merge 1 commit into
mainfrom
ci/release-workflow

Conversation

@arekkubaczkowski

Copy link
Copy Markdown
Owner

Releasing 2.1.1 took four attempts, so this removes the part that fought back.

Why it fought

release-it shells out to npm publish. npm only offers the browser authorization flow when stdin/stdout are a TTY — from a child process it skips straight to EOTP and demands a code from an authenticator app. So the release worked only when run by hand, in a real terminal, in two halves.

What this does

A manually dispatched Release workflow, split along the auth boundary:

step credential
version, commit, tag, push, GitHub release (release-it --no-npm.publish) GITHUB_TOKEN
npm publish GitHub OIDC — npm trusted publishing

No token to store and no interactive second factor: permissions: id-token: write lets npm exchange the workflow's OIDC token for publish rights on this package. Provenance is generated as a side effect. --npm.skipChecks is needed because release-it's npm whoami precheck has no token to check.

Also sets git.requireCommits in the release-it config. Without it release-it happily bumps with an empty changelog — a dry run with no commits since v2.1.1 produced a 2.1.2 whose changelog had no entries, which is one stray click away in a dispatch-triggered workflow. With it, that run aborts with There are no commits since the latest tag.

npm install -g npm@latest is there because trusted publishing landed in npm 11.5.1 and .nvmrc (node 20) ships npm 10.

One-time browser step before the first run

This cannot work until the package knows which workflow to trust — on npmjs.com, package Settings → Trusted publisher → GitHub Actions:

  • organization/user: arekkubaczkowski
  • repository: react-native-bottom-sheet-stack
  • workflow filename: release.yml
  • environment: leave empty

The workflow file has to be on main for npm to accept it, so: merge this, configure the trusted publisher, then Actions → Release → Run workflow. Tick dry_run on the first go — it prints the version and changelog and touches nothing.

Notes

  • main is unprotected, so the release commit pushes cleanly. If that ever changes, the push needs an exemption for github-actions[bot].
  • Pushes made with GITHUB_TOKEN don't trigger other workflows, so the release commit won't re-run CI. The workflow runs yarn lint, yarn typecheck and yarn test itself before releasing.
  • Unrelated but adjacent: the test job in ci.yml only runs the setup action — it never invokes yarn test. Worth a follow-up.

🤖 Generated with Claude Code

Releases needed a TTY: release-it shells out to `npm publish`, npm only
offers the browser authorization flow from an interactive terminal, and
without one it fails with EOTP asking for a code from an authenticator.

Move the whole thing into a manually dispatched workflow. GitHub's OIDC
token stands in for npm credentials, so there is nothing to authenticate
interactively and no publish token to store — one browser step registers
this workflow as the package's trusted publisher and that is the last of
it. Provenance comes along for free.

The two halves are split because their auth is: release-it does version,
commit, tag, push and the GitHub release on GITHUB_TOKEN, then `npm
publish` runs on OIDC. `--npm.skipChecks` because release-it's `npm
whoami` precheck has no token to check.

Also set `git.requireCommits`, which is what stops a stray dispatch from
cutting a version with an empty changelog.

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