Skip to content

chore: modernize release pipeline with OIDC trusted publishing#20

Merged
bnimit merged 1 commit into
mainfrom
chore/secure-release-and-deps
May 14, 2026
Merged

chore: modernize release pipeline with OIDC trusted publishing#20
bnimit merged 1 commit into
mainfrom
chore/secure-release-and-deps

Conversation

@bnimit
Copy link
Copy Markdown
Contributor

@bnimit bnimit commented May 14, 2026

Summary

Modernizes the release pipeline and dependency surface for this repo:

  • Required for npm provenance: adds repository, homepage, bugs fields to package.json. npm cross-checks repository.url against the workflow's OIDC-asserted GitHub origin and rejects the publish if they don't match — without these fields, the first trusted-publishing release would 422.
  • engines.node bumped from >=10 (EOL since 2021) to >=20. Honest signal; CI matrix already runs Node 20 and 22.
  • Patch/minor dev-dep bumps where the lockfile resolution stays clean: eslint 9.39.4, prettier 3.8.3, postcss 8.5.14, react/react-dom 19.2.6, @types/react 19.2.14, @babel/runtime 7.29.2 resolution. Intentionally held vitest at ^4.0.18 and vite at ^7.3.1 — vitest 4.1.x changed packaging in a way that triggers yarn 1.x dependency linking invariant violations on nested vite lookups.
  • All GitHub Actions pinned by commit SHA in ci.yml and release.yml. Defense against tag-rewrite attacks. Versions bumped where newer was available: checkout v6 → v6.0.2, setup-node v6 → v6.4.0, peter-evans/create-pull-request v8 → v8.1.1.
  • Default-deny workflow permissions (permissions: contents: read) on ci.yml and release.yml. The release job retains its explicit contents: write + pull-requests: write because it commits and opens PRs.
  • New publish.yml: tag-triggered (v*) npm publish via OIDC Trusted Publishing with --provenance, gated behind a npm-publish GitHub environment for reviewer approval. Pre-release tags (vX.Y.Z-foo) route to the next dist-tag so they don't replace latest. Removes the need for a long-lived NPM_TOKEN and produces verifiable provenance attestations on every published tarball.
  • release.yml PR-body updated: removes the manual npm publish step, points reviewers at the new tag-driven publish flow.

What changes for consumers

Nothing in the published package — this PR touches .github/workflows/, package.json metadata fields, engines.node, and devDependencies resolutions. None of those are in the package's files field. The next release published from this branch will be byte-identical to one published before it (modulo any code changes).

After the first release goes out under the new flow, consumers can run npm audit signatures on react-align to verify the tarball was published by this repo's workflow at a specific commit, rather than from a maintainer's local machine.

One-time pre-merge setup (before first tag push)

Configured on the npm + GitHub side, not in this PR:

  1. npmjs.comreact-align package settings → Trusted publishers → add:
    • Publisher: GitHub Actions
    • Org/user: reearth
    • Repository: react-align
    • Workflow filename: publish.yml
    • Environment name: npm-publish
  2. GitHub → Settings → Environments → create npm-publish with required reviewers.

publish.yml only fires on v* tag push, so it's dormant after merge until the first release tag is pushed.

Release flow after this lands

  1. Run the existing Release workflow → pick version bump → it opens a release PR
  2. Merge the release PR
  3. Locally: git pull && git tag vX.Y.Z && git push origin vX.Y.Z
  4. New Publish workflow run pauses at the npm-publish environment gate → approve → react-align@X.Y.Z ships with provenance

Test plan

  • yarn lint passes
  • yarn type (tsc) passes
  • yarn test --run — 6/6 tests pass
  • yarn build produces dist/react-align.{mjs,umd.js} and types
  • actionlint clean on publish.yml and ci.yml (release.yml has 18 pre-existing shellcheck info-level warnings on lines this PR doesn't touch)
  • CI green on this PR
  • (Post-merge, after npm + GH environment setup) push a vX.Y.Z tag → approve → first provenance-attested publish

🤖 Generated with Claude Code

- Add `repository`, `homepage`, `bugs` fields to package.json. Required
  for npm provenance verification: npm cross-checks the workflow's
  origin against package.json.repository.url at publish time, and
  rejects the publish if they don't match. Without these fields the
  first trusted-publishing run would 422.
- Bump `engines.node` from `>=10` (EOL since 2021) to `>=20`. Honest
  signal — CI runs on Node 20 and 22.
- Patch/minor dev-dep bumps where the lockfile resolution stays clean:
  eslint 9.39.4, prettier 3.8.3, postcss 8.5.14, react/react-dom 19.2.6,
  @types/react 19.2.14, @babel/runtime 7.29.2 resolution. Held vitest
  at ^4.0.18 / vite at ^7.3.1 to keep yarn 1.x dependency linking
  working (vitest 4.1.x changed packaging in a way that triggers yarn 1
  invariant violations on nested vite lookups).
- Pin every GitHub Action by commit SHA in ci.yml, release.yml. Bumps
  checkout v6 -> v6.0.2, setup-node v6 -> v6.4.0, peter-evans/
  create-pull-request v8 -> v8.1.1. Defense against tag-rewrite
  attacks.
- Add workflow-level `permissions: contents: read` (default-deny) to
  ci.yml, release.yml. release.yml's job retains its explicit
  contents/pull-requests: write where it needs them.
- New publish.yml: tag-triggered (v*) npm publish via OIDC Trusted
  Publishing with --provenance, gated behind the `npm-publish` GitHub
  environment for reviewer approval. Pre-release tags (vX.Y.Z-foo)
  route to the `next` dist-tag so they don't replace `latest`. Removes
  the need for a long-lived NPM_TOKEN.
- Update release.yml PR body: removes the manual `npm publish` step,
  points at the new tag-driven publish flow.

Pre-merge setup required before the first release tag is pushed:
1. npmjs.com -> Trusted publishers -> add `reearth/react-align` +
   workflow filename `publish.yml` + environment `npm-publish`.
2. GitHub -> Settings -> Environments -> create `npm-publish` with
   required reviewers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bnimit bnimit merged commit 5fbbacc into main May 14, 2026
2 checks passed
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