Skip to content

chore: Port the v5 publish workflow to main#413

Merged
csandman merged 3 commits into
mainfrom
chore/publish-to-npm-main
May 16, 2026
Merged

chore: Port the v5 publish workflow to main#413
csandman merged 3 commits into
mainfrom
chore/publish-to-npm-main

Conversation

@csandman

Copy link
Copy Markdown
Owner

Summary

Brings main to parity with v5's publishing setup from #405, adapted for the post-stable release flow on this branch. Three commits:

  1. docs: fill out SECURITY.md — replaces the GitHub-templated stub with a real policy: support matrix tied to the @chakra-ui/react major peer (v5/v6 supported, v4 and earlier not), private reporting via GitHub Security Advisories, out-of-scope pointers to react-select / Chakra UI.
  2. Downgrade codemod types/node — incidental: aligns the dev type to the locally installed Node version.
  3. chore: Port the v5 publish workflow to main — the main event.

Publish workflow (.github/workflows/publish.yml)

Three-job testbuildpublish flow scaffolded from @e18e/setup-publish per the e18e publishing guide, copied verbatim from v5 with two adjustments:

  • Conditional dist-tag: v5 hardcoded --tag chakra2. On main, stable releases publish to latest; GitHub-flagged prereleases publish to next:
    - name: Publish to npm
      env:
        PRERELEASE: ${{ github.event.release.prerelease }}
      run: |
        if [ "$PRERELEASE" = "true" ]; then
          npm publish --provenance --access public --tag next "$TARBALL"
        else
          npm publish --provenance --access public "$TARBALL"
        fi
    Uses an env: indirection to avoid the template-injection class that zizmor flags.
  • pnpm test added to the test job: v5 omitted it because the test suite didn't exist there at the time of chore: Adopt e18e publishing practices (OIDC trusted publishing + provenance) (v5) #405. On main (PR Add an integration test suite #412) it does, and dropping that gate when migrating from prepublishOnly to CI would be a regression.

Security baseline (per e18e hardening):

  • Top-level permissions: {}; each job opts in minimally (contents: read on test/build, id-token: write only on publish).
  • All actions pinned to full-length commit SHAs (matching what lint.yml / pkg-pr.yml already use).
  • persist-credentials: false on every checkout.
  • pnpm install --frozen-lockfile --ignore-scripts in every job.
  • Node 24 throughout (required for OIDC trusted publishing).
  • Build job isolated from credentials; only publish has id-token: write. The publish job is scoped to environment: publish for an approval gate.

Departure from v5: drop .npmrc ignore-scripts=true

v5 ships .npmrc with ignore-scripts=true per the e18e tip. This PR removes it on main, because the protection it provides is now covered better by pnpm's allowBuilds whitelist (only esbuild is permitted to run install scripts). The publish workflow still passes --ignore-scripts to pnpm install explicitly, which is the load-bearing protection for the high-stakes publish path.

Removing the blanket setting lets husky's prepare script run automatically on fresh clones — no more pnpm prepare rake.

Updates that fall out:

  • CONTRIBUTING.md: replaces the pnpm prepare note with one pointing at allowBuilds as the dep-script gate.
  • .vscode/settings.json: drops the now-obsolete .npmrcini file association.

package.json script cleanup

Two scripts are obsolete under CI-driven publishing (per #405's rationale):

  • prepublishOnly: "pnpm build && pnpm lint && pnpm test" — CI publishes from a pre-built tarball, which doesn't run local lifecycle scripts. The equivalent gating now lives in the publish workflow's test job (with pnpm test added — see above).
  • postpublish: "git push --follow-tags" — CI shouldn't push tags. The intended flow is pnpm version locally → git push --follow-tags → create GitHub release → workflow fires.

Pre-flight checklist (manual setup outside the repo)

These must be in place before the first publish from main, or the workflow will fail at the publish step:

  • GitHub Environment publish — add main to allowed-branches alongside v5 (Settings → Environments → publish). Per e18e guidance, hardcode exact branch names; do not use patterns.
  • npm Trusted Publisher — verify the entry for publish.yml + environment publish at https://www.npmjs.com/package/chakra-react-select/access. Per-workflow/environment binding should already cover main; check that the entry exists.
  • Tag protection ruleset for v* — already in place from v5 setup.
  • npm "Require 2FA and disallow tokens" — flip on if not yet enabled, after the first successful trusted-publish run from either branch.

Release flow after merge

  1. pnpm version <patch|minor|major> on maingit push --follow-tags origin main.
  2. Releases → Draft a new release → pick the new tag → Generate release notesPublish release.
  3. The 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: npm dist-tag ls chakra-react-select shows latest updated; chakra2 and next unchanged. npm view chakra-react-select@<version> --json shows dist.attestations populated.

Test plan

  • CI on this PR: lint, test (Node 20 & 24), pkg-pr, zizmor, package-size-report all green.
  • zizmor is the key check — it lints the new publish.yml for template injection, excessive permissions, unpinned actions. Any flags here should be fixed before merge.
  • The publish workflow itself does not run on this PR — it triggers only on release: published. Expected.
  • After merge + pre-flight checklist: cut a low-stakes patch release and walk through the release flow above.

🤖 Generated with Claude Code

csandman and others added 3 commits May 15, 2026 21:35
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>
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>
@bolt-new-by-stackblitz

Copy link
Copy Markdown

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

@pkg-pr-new

pkg-pr-new Bot commented May 16, 2026

Copy link
Copy Markdown

commit: 7fbcaca

@github-actions

Copy link
Copy Markdown

📊 Package size report   -0.07%↓

File Before After
package.json 2.8 kB -3.79%↓2.7 kB
Total (Includes all files) 152.8 kB -0.07%↓152.7 kB
Tarball size 30.1 kB -0.12%↓30.0 kB
Unchanged files
File Size
dist/index.d.mts 20.1 kB
dist/index.d.ts 20.1 kB
dist/index.js 31.1 kB
dist/index.mjs 29.5 kB
LICENSE.md 1.1 kB
README.md 48.1 kB

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

@csandman csandman merged commit e161571 into main May 16, 2026
9 checks passed
csandman added a commit that referenced this pull request May 16, 2026
Removing .npmrc's ignore-scripts=true in #413 had an unintended
consequence: `npm pack` now runs the project's own `prepare`
script (husky), which dumps lifecycle output to stdout. With
TARBALL=$(npm pack), that output gets captured alongside the
tarball filename, producing a multi-line value that breaks
$GITHUB_OUTPUT's key=value\n format and fails the build job.

pnpm's `allowBuilds` whitelist only gates *dependency* install
scripts; it doesn't suppress the project's own scripts during
`npm pack`. Adding --ignore-scripts to the pack invocation
restores clean stdout. Husky's `prepare` doesn't need to run
during CI pack anyway — git hooks aren't relevant in the
ephemeral runner.

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