chore: migrate from semantic-release to changesets - #351
Conversation
Releases are now driven by changeset files rather than commit messages. Pushing to main opens a "Version Packages" pull request; merging that pull request publishes to npm, pushes the tag and creates the release. Publishing uses npm trusted publishing over OIDC, so NPM_PUBLISH_TOKEN is no longer needed. Trusted publishing requires npm >= 11.5.1, and older versions skip OIDC silently rather than failing, so the workflow installs a current npm rather than trusting the runner default. Notable details: - changedFilePatterns is limited to src/**, so docs, test, CI and Renovate dependency pull requests do not require a changeset. - CHANGELOG.md now starts with its heading: changesets inserts new entries after the first line, so the previous comment/preamble header would have split entries away from the rest of the file. - .prettierignore only existed to exclude CHANGELOG.md, which changesets now formats itself, so it has been dropped and the existing entries reformatted in one go. - changesets/action is pinned to a SHA since this workflow holds publish rights. The trailing version comment is what Renovate reads to bump it. Includes a changeset for 61d9476, the only unreleased commit touching src/.
The build needs `Event`, `Response`, `MessageEvent` and `AbortSignal`, which come from @types/node: tsconfig.settings.json sets lib to ES2020 with no DOM, and does not restrict `types`, so TypeScript picks up whatever is hoisted into node_modules/@types. @types/node was never declared, only ever arriving transitively. Dropping semantic-release removed what was pulling a modern copy to the top, and @changesets/cli brings in @manypkg/find-root, which wants @types/node@^12.7.1. npm still hoisted 22.x, but bun hoisted 12.20.55, which predates all four globals, so `bun install` failed in its prepare script with TS2304. Declare it so all three package managers resolve the same version rather than depending on hoisting order.
There was a problem hiding this comment.
🟡 Not ready to approve
The release workflow currently allows manual dispatch from any branch and installs npm@latest, both of which increase the risk of unintended/unstable publishing behavior.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.
Pull request overview
Migrates the repository’s release process from semantic-release (commit-message driven) to Changesets (file-driven), including CI workflows to enforce changeset presence and automate version PR + publish with npm trusted publishing (OIDC).
Changes:
- Replace semantic-release config/dependencies with Changesets CLI + GitHub changelog integration.
- Add CI workflows for (1) changeset status checks on PRs and (2) automated “Version Packages” PR / publish flow on main.
- Reformat
CHANGELOG.mdto work with Changesets’ insertion behavior and remove.prettierignorethat only excluded the changelog.
File summaries
| File | Description |
|---|---|
| package.json | Adds Changesets-related scripts and devDependencies; removes semantic-release dependencies. |
| CONTRIBUTING.md | Documents Changesets expectations for contributors and the new release flow for maintainers. |
| CHANGELOG.md | Removes preamble and normalizes list formatting to support Changesets’ changelog updates. |
| bun.lock | Updates lockfile to reflect dependency migration to Changesets and removals of semantic-release deps. |
| .releaserc.json | Removes semantic-release configuration. |
| .prettierignore | Removes changelog exclusion now that Changesets manages its formatting expectations. |
| .github/workflows/release.yml | Replaces semantic-release-based publishing with changesets/action + OIDC trusted publishing. |
| .github/workflows/changeset.yml | Adds PR-time enforcement that user-facing src/** changes include a changeset. |
| .changeset/README.md | Adds repository-local documentation for Changesets usage. |
| .changeset/rare-deserts-stay.md | Adds a changeset entry describing a patch-level user-facing change. |
| .changeset/config.json | Adds Changesets configuration (GitHub changelog integration + changedFilePatterns). |
Review details
Suppressed comments (1)
.github/workflows/release.yml:32
- Installing
npm@latestmakes the release workflow sensitive to future npm major releases (and their Node engine requirements). Since trusted publishing only requires npm >= 11.5.1, pin to the npm 11 line (or a specific minimum) to reduce unexpected breakage.
- run: npm install --global npm@latest
- Files reviewed: 10/13 changed files
- Comments generated: 1
- Review effort level: Lite
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
Addresses Copilot review feedback on #351. `workflow_dispatch` can be triggered on any ref, and npm's trusted publisher config pins owner, repo and workflow file but not the branch, so a dispatch from a feature branch would have run with contents: write and live publish rights. Gate the job to refs/heads/main; push-to-main and dispatch-from-main both still run. `npm@latest` is already npm 12, so the workflow was picking up a major beyond the >= 11.5.1 that trusted publishing needs. Hold it to npm@11 (11.19.0) so patches still flow but a new major cannot land unattended on the publish path.
npm@latest is already npm 12, so holding at 11 meant deliberately releasing on a stale major. npm 12's headline change, dependency install scripts off by default, does not affect this repo: it targets dependencies' preinstall/install/postinstall, not the root package's own prepare, and the one dependency here with an install script (esbuild) resolves its binary from the @esbuild/* optional dependency and runs fine without it. Verified npm 12 runs prepare and packs dist identically to npm 11. That comparison did surface one real difference. npm 12 evaluates the `files` negation as last-match-wins, so "!dist/stats.html" listed before "dist" was overridden and the 158K bundle analysis landed in the tarball, taking it from 25K to 70K. Move the negation after the include, which is correct under both: 13 files and 25K on npm 11 and npm 12 alike.
There was a problem hiding this comment.
🟡 Not ready to approve
The release workflow drops npm provenance configuration that was previously enabled, which can unintentionally weaken supply-chain guarantees for published releases.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.
Review details
Suppressed comments (1)
.github/workflows/release.yml:49
- The previous release workflow explicitly enabled npm provenance (
NPM_CONFIG_PROVENANCE: true). With trusted publishing/OIDC you can still publish without provenance, but this change drops provenance attestations for published releases. If provenance is still desired, addNPM_CONFIG_PROVENANCEto the publish step env sochangeset publish(and its underlyingnpm publish) emits provenance.
- name: Create version pull request or publish to npm
uses: changesets/action@a45c4d594aa4e2c509dc14a9f2b3b67ba3780d0d # v1.9.0
with:
version: npm run version:packages
publish: npm run release
commit: 'chore(release): version packages'
title: 'chore(release): version packages'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- Files reviewed: 10/13 changed files
- Comments generated: 0 new
- Review effort level: Lite
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
Releases are now driven by changeset files rather than commit messages.
Pushing to main opens a "Version Packages" pull request; merging that
pull request publishes to npm, pushes the tag and creates the release.
Publishing uses npm trusted publishing over OIDC, so NPM_PUBLISH_TOKEN
is no longer needed. Trusted publishing requires npm >= 11.5.1, and
older versions skip OIDC silently rather than failing, so the workflow
installs a current npm rather than trusting the runner default.
Notable details:
Renovate dependency pull requests do not require a changeset.
entries after the first line, so the previous comment/preamble header
would have split entries away from the rest of the file.
now formats itself, so it has been dropped and the existing entries
reformatted in one go.
rights. The trailing version comment is what Renovate reads to bump it.