Publishing openlore to npm
May 27, 2026 · View on GitHub
OpenLore uses npm Trusted Publishing (OIDC) so the package is published from CI with no long-lived npm token in any secret store, shell, or laptop. Every published version carries a signed npm provenance attestation linking it to the exact GitHub Actions run that built it.
The CI workflow that does the publish lives at .github/workflows/release.yml and fires automatically when a vX.Y.Z tag is pushed (it also still fires if you publish a GitHub Release by hand).
How a release happens
- Bump the version locally:
npm version <patch|minor|major>(this creates avX.Y.Ztag). git push --follow-tagsto push both the bump commit and the tag.- That's it. Pushing the tag triggers the
Releaseworkflow, which:validate— re-runslint,typecheck,test:run,buildagainst the tagged commit.create-release— creates the GitHub Release for the tag with auto-generated notes (idempotent: skipped if a Release for that tag already exists). Created withGITHUB_TOKEN, so it does not re-trigger the workflow.publish— re-builds and runsnpm publish --provenance --access public. No token; the OIDC handshake with npm authenticates the run.
If the npm-publish environment has a required reviewer, the publish job pauses for a human approval click before it can mint the OIDC token.
Alternative paths
- Publish a GitHub Release by hand (Releases → Draft a new release → pick the tag → Publish): the
create-releasejob is skipped (the Release already exists) andpublishruns. - Re-run a failed publish: Actions → Release → Run workflow and pass the tag (
workflow_dispatch).
One-time setup (do this once, then never again)
1. Configure Trusted Publishing on npmjs.com
Sign in to npmjs.com as a maintainer of the openlore package, then:
- Visit https://www.npmjs.com/package/openlore/access
- Scroll to Trusted Publisher and click Add Trusted Publisher
- Select GitHub Actions as the provider
- Fill in:
- Organization or user:
clay-good - Repository:
OpenLore - Workflow filename:
release.yml - Environment name:
npm-publish(must match theenvironment:block inrelease.yml)
- Organization or user:
- Save.
2. Create the npm-publish deployment environment on GitHub
- Repo → Settings → Environments → New environment
- Name:
npm-publish - (Optional but recommended) Add a required reviewer so every publish requires a human approval click before the workflow can mint an OIDC token.
- (Optional) Restrict to the
mainbranch under Deployment branches.
3. Revoke any existing npm automation tokens
This is the whole point of the migration. From npmjs.com:
- Account settings → Access Tokens
- Find any token with publish/write scope on
openlore(likely labeled something like "openlore-ci" or "automation"). - Click Revoke.
If GitHub repo secrets still contain NPM_TOKEN, delete that secret too (Settings → Secrets and variables → Actions → remove NPM_TOKEN). The workflow no longer references it.
Verifying a published version
After a release fires, anyone can audit the provenance:
npm view openlore --json | jq '.dist.attestations'
The attestation includes the GitHub workflow file, the commit SHA, and the run ID — anyone reproducing those inputs can confirm the published tarball came from this repo.
Why Trusted Publishing matters
Long-lived publish tokens are the supply-chain attacker's favorite target — they bypass 2FA, often live in CI secret stores indefinitely, and have been exploited by worms like Shai-Hulud. Trusted Publishing replaces the token with a short-lived OIDC token minted per-workflow-run, scoped to a specific repo + workflow file + environment. There's nothing useful to steal even if a CI runner is compromised.
Troubleshooting
E401 You must be logged in to publish packages— npm's Trusted Publisher config doesn't match the workflow. Double-check the org/repo/workflow filename/environment on npmjs.com against what's inrelease.yml.Error: Resource not accessible by integration— the workflow is missingid-token: writepermission. It's already set inrelease.yml; if you forked the workflow, copy that line.- Workflow fires but never runs the publish job — check the
npm-publishenvironment exists and is reachable from the branch/tag being published.