Skip to content

ci: upgrade to changesets v3 and support maintenance releases - #354

Merged
rexxars merged 2 commits into
mainfrom
chore/changesets-v3-maintenance-releases
Aug 12, 2026
Merged

ci: upgrade to changesets v3 and support maintenance releases#354
rexxars merged 2 commits into
mainfrom
chore/changesets-v3-maintenance-releases

Conversation

@rexxars

@rexxars rexxars commented Aug 12, 2026

Copy link
Copy Markdown
Member

Upgrades the release tooling to changesets v3, and makes it possible to ship fixes for older majors without disturbing the current one.

Changesets v3

  • @changesets/cli ^2.31.1 -> ^3.0.0, @changesets/changelog-github ^0.7.0 -> ^1.0.0, config $schema -> @changesets/config@4.0.0.
  • The action moves to changesets/action@v2.0.0 (pinned to 22ccf9a). There is no action v3 - v2 is the release built against changesets v3, and it refuses to run against a v2 CLI. Its breaking changes are handled here:
    • Inputs renamed to kebab-case: version -> version-script, publish -> publish-script, commit -> commit-message, title -> pr-title.
    • The GITHUB_TOKEN environment variable is no longer read, so that block is dropped in favour of the action's github-token input default.
  • Sets format: "oxfmt" explicitly, since v3 removed the prettier option in favour of format. Auto-detection would find oxfmt anyway; being explicit removes the guess.

Worth knowing: changeset version now exits 1 when there are no unreleased changesets. The action only invokes the version script when changesets exist, so CI is unaffected, but running npm run version:packages by hand on a clean tree will now fail rather than no-op.

Maintenance releases

release.yml and changeset.yml now trigger on main plus any v[0-9]+ branch. A Resolve release channel step runs before checkout and maps the branch to an npm dist-tag, failing closed on anything else:

  • main -> latest
  • v4 -> v4

The job-level if still blocks workflow_dispatch from arbitrary refs; it just cannot express a pattern, so the step narrows it to exactly main or vN.

Two problems this had to solve, neither of which is obvious:

  • changeset publish defaults to the latest dist-tag. Without --tag, a 4.x backport would have become the default install for everyone running npm install eventsource.
  • changesets/action calls repos.createRelease without make_latest, and the GitHub API defaults that to true. A backport would have taken the "Latest" release badge off the current major. A post-publish step demotes it, on maintenance branches only.

Both are handled by the workflow; there is nothing to pass by hand when cutting a backport.

Companion branch

v4 has been reset to tag v4.1.1 and carries the same tooling, with baseBranch: "v4" and identical workflow files. It was previously a stale pre-5.0 development branch sitting at 3.0.7, fully contained in main.

3.x is not supported, so there is no v3 branch. SECURITY.md is updated to say so explicitly - the table previously listed 4.x and < 3.0 but left 3.x unstated.

Verification

  • Ran the full version flow with a temporary changeset on both branches: 5.0.0 -> 5.0.1 and 4.1.1 -> 4.1.2, with changelog and lockfile updated correctly, then reverted.
  • npm ci passes from the regenerated lockfiles.
  • Branch-to-dist-tag routing tested against main, v4, v10, v1.x, v2.x, vfoo, fix/thing, v4-hack and an empty ref. Only the first three resolve; the rest fail the step.
  • Lint and typecheck clean. The two pre-existing oxfmt --check failures (package.json, test/tests.ts) also fail on unmodified main and are left alone.

Note for after merge

npm's trusted publisher pins the workflow filename but not the branch, which is what lets v4 publish at all. Renaming release.yml breaks publishing on every branch at once.

Bumps @changesets/cli to v3 and the release action to changesets/action@v2,
which is the version built against changesets v3. The action renamed its
inputs to kebab-case and dropped support for configuring the token through
the GITHUB_TOKEN environment variable, so those move over too.

Releases can now also run from `vN` maintenance branches. The branch decides
the npm dist-tag, so a 4.x backport publishes under `v4` instead of taking
`latest` from the current major, and its GitHub release is demoted so it does
not take the "Latest" badge either.
@rexxars
rexxars force-pushed the chore/changesets-v3-maintenance-releases branch from 1388421 to a43e5bb Compare August 12, 2026 19:25
The demotion now goes through the releases REST API with the explicit
`make_latest=false` string enum, rather than `gh release edit --latest=false`,
which depends on how the runner's gh build handles negated boolean flags.

More importantly it now verifies the result: after clearing the flag the step
re-reads the repository's latest release and fails the job if it is still one
of the versions just published. Previously a demotion that silently did not
apply would have left the badge on the wrong major with the job green.
@rexxars
rexxars merged commit 6da8847 into main Aug 12, 2026
7 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