Skip to content

chore: Adopt e18e publishing practices (OIDC trusted publishing + provenance) (v5)#405

Merged
csandman merged 1 commit into
v5from
chore/publish-to-npm-v5
May 14, 2026
Merged

chore: Adopt e18e publishing practices (OIDC trusted publishing + provenance) (v5)#405
csandman merged 1 commit into
v5from
chore/publish-to-npm-v5

Conversation

@csandman
Copy link
Copy Markdown
Owner

Summary

Adopts the e18e publishing recommendations on v5 so this branch can publish under the chakra2 dist-tag from a hardened, isolated CI workflow with OIDC trusted publishing and provenance attestations — no npm tokens, no local credentials.

This is being landed on v5 first so it can be verified end-to-end before being duplicated to main.

What changes

.github/workflows/publish.yml (new)

A three-job publish workflow scaffolded from @e18e/setup-publish (--template default --env publish) and adapted to pnpm. Triggered on release: published to preserve the current "create a GitHub release in the UI → publish" flow.

  • test — installs (with --ignore-scripts), runs lint:src, lint:types, build, lint:exports (attw), and lint:publish (publint).
  • build — installs, builds, aligns package.json version to the release tag, npm packs a tarball, uploads it as an artifact. No publish credentials in this job.
  • publishneeds: [test, build]. Downloads the tarball and runs npm publish --provenance --access public --tag chakra2 <tarball>. This is the only job with id-token: write. Scoped to the publish GitHub Environment for an approval gate.

Security baseline (per e18e):

  • Top-level permissions: {}, every job opts in minimally.
  • All actions pinned to full-length commit SHAs (matching SHAs already used in lint.yml / pkg-pr.yml).
  • persist-credentials: false on checkout.
  • --ignore-scripts on install in CI.
  • Node 24 in the publish job (required for OIDC).
  • Build job isolated from credentials; only publish job has id-token: write.

The --tag chakra2 flag is the only v5-specific bit. When this is later mirrored to main, that's the line that changes.

.npmrc (new)

ignore-scripts=true

Defense-in-depth against malicious lifecycle scripts in transitive deps during local installs. See npm docs on ignore-scripts and the e18e supply-chain note.

Side effect: husky's prepare script won't auto-run on fresh installs — CONTRIBUTING.md updated with a one-line setup note (pnpm install && pnpm prepare on fresh clone; subsequent installs work as normal because git's core.hooksPath is already set).

package.json

  • Removed postpublish: "git push --tags" — CI publishes don't (and shouldn't) push tags; the user pushes tags as part of pnpm version + git push --follow-tags.
  • Removed prepublishOnly: "pnpm build && pnpm lint" — CI publishes from a pre-built tarball, which doesn't run local lifecycle scripts; and .npmrc's ignore-scripts=true would suppress it anyway. It was vestigial.
  • Added lint:publish: "publint" script and publint devDep — catches common package.json / exports misconfigurations before publish, complementing the existing attw check.

.vscode/settings.json

  • Associates .npmrc with the ini language (otherwise some VS Code configurations detect it as JSON).

CONTRIBUTING.md

  • Notes the one-time pnpm prepare step on fresh clones, with a brief explanation.

Manual setup required before first publish

These are configured outside the repo and are not part of this PR's diff. All four must be in place before the workflow can publish successfully:

  • npm Trusted Publisher (docs) — csandman/chakra-react-select, workflow publish.yml, environment publish. Immutable releases enabled.
  • GitHub Environment publish — restricted to branch v5, with me as a required reviewer (gives a 2FA-gated approval on every publish).
  • Tag protection ruleset for v* — restricts tag creation to admins.
  • npm "Require 2FA and disallow tokens" — flip after the first successful trusted-publish run to avoid locking out mid-cutover.

Release flow after merge

Effectively the same as today, plus an approval click:

  1. pnpm version <patch|minor|major> on v5git push --follow-tags origin v5.
  2. Releases → Draft a new release → pick the new tag → Generate release notesPublish release.
  3. The Publish to npm workflow fires. You'll get a GitHub notification to approve the publish environment deployment.
  4. Approve (this is the 2FA gate). Publish runs; ~30s.
  5. Verify on npm: new version visible under the chakra2 dist-tag with a provenance attestation; latest untouched.

Verification plan

End-to-end dry-run on this branch's first release after merge:

  • test and build jobs pass.
  • publish job pauses for environment approval.
  • After approval, npm publish --provenance --tag chakra2 succeeds with no token configured.
  • npm dist-tag ls chakra-react-select shows chakra2 pointing at the new version, latest unchanged.
  • npm view chakra-react-select@<version> --json shows dist.attestations populated.
  • After success: flip on "Require 2FA and disallow tokens" on npm and revoke any legacy publish tokens for this package.

Replication to main (out of scope here)

Once verified on v5, copy .github/workflows/publish.yml to main with these adjustments:

  • Remove the hardcoded --tag chakra2 (or restore the e18e template's prerelease ? --tag next conditional).
  • Add main to the publish environment's allowed branches in the GitHub UI.

Resources

Test plan

  • CI: existing lint, pkg-pr, zizmor, package-size-report workflows pass on this PR.
  • After merge: cut a low-stakes release (e.g. pnpm version patch5.1.1) and walk through the verification checklist above.
  • On first successful publish, confirm chakra2 dist-tag updated and latest unchanged on npmjs.com.

🤖 Generated with Claude Code

@bolt-new-by-stackblitz
Copy link
Copy Markdown

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 14, 2026

commit: f1bb8dc

@github-actions
Copy link
Copy Markdown

📊 Package size report   -0.02%↓

File Before After
package.json 2.6 kB -1.14%↓2.6 kB
Total (Includes all files) 155.9 kB -0.02%↓155.8 kB
Tarball size 31.4 kB -0.05%↓31.4 kB
Unchanged files
File Size
dist/index.d.mts 20.0 kB
dist/index.d.ts 20.0 kB
dist/index.js 33.1 kB
dist/index.mjs 31.5 kB
LICENSE.md 1.1 kB
README.md 47.5 kB

🤖 This report was automatically generated by pkg-size-action

@csandman csandman changed the title chore: Adopt e18e publishing practices (OIDC trusted publishing + provenance) chore: Adopt e18e publishing practices (OIDC trusted publishing + provenance) (v5) May 14, 2026
@csandman csandman merged commit 878c85a into v5 May 14, 2026
7 checks passed
@csandman csandman deleted the chore/publish-to-npm-v5 branch May 14, 2026 03:01
csandman added a commit that referenced this pull request May 16, 2026
* docs: fill out SECURITY.md with a real policy

Replace the GitHub-templated stub with a project-specific policy:
support matrix tied to the @chakra-ui/react major peer (v5/v6
supported, v4 and earlier not), private reporting via GitHub
Security Advisories, and pointers to react-select / Chakra UI for
upstream issues.

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

* Downgrade the codemod types/node package to match the installed version of node

* chore: Port the v5 publish workflow to main

Adopts the e18e publishing recommendations on main, mirroring the
v5 setup from #405:

- Add .github/workflows/publish.yml with the three-job
  test → build → publish flow. OIDC trusted publishing with
  provenance attestations; no npm tokens. Top-level
  permissions: {}, persist-credentials: false, pinned action
  SHAs, --ignore-scripts on install, Node 24 throughout.
- Replace v5's hardcoded --tag chakra2 with a conditional:
  stable releases publish to `latest`, GitHub-flagged
  prereleases publish to `next`.
- Add `pnpm test` to the test job (v5 omitted it because the
  test suite didn't exist there yet; on main it does).
- Drop `prepublishOnly` and `postpublish` from package.json —
  CI publishes from a pre-built tarball, and the equivalent
  gating now lives in the publish workflow's test job.
- Drop `.npmrc ignore-scripts=true`. pnpm's `allowBuilds`
  whitelist (pnpm-workspace.yaml) already gates dependency
  install scripts with finer granularity, and the publish
  workflow passes --ignore-scripts to `pnpm install`
  explicitly. Removing the blanket flag lets husky's
  `prepare` script run automatically on fresh installs.
- Update CONTRIBUTING.md to reflect the install-scripts model
  change, and remove the now-obsolete .npmrc → ini
  files.associations entry from .vscode/settings.json.

Before the first publish from main, the GitHub `publish`
environment will need `main` added to its allowed-branches
list alongside `v5`.

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

---------

Co-authored-by: Claude Opus 4.7 (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