Skip to content

Release with changesets and the shared toolchain, not np - #21

Merged
stefanoverna merged 4 commits into
mainfrom
release-toolchain
Aug 31, 2026
Merged

Release with changesets and the shared toolchain, not np#21
stefanoverna merged 4 commits into
mainfrom
release-toolchain

Conversation

@stefanoverna

@stefanoverna stefanoverna commented Aug 31, 2026

Copy link
Copy Markdown
Member

This repo released with np, via a two-line SDKs/RELEASE.md that
prescribed a bare np patch — literally always patch, decided on release day.
There is no CHANGELOG.md here at all.

Changesets moves the bump level into the PR that makes the change, and writes
the changelog from it. The release script is
@datocms/release-toolchain
the same one the four DatoCMS monorepos now run, installed from its repository
by git tag and never published to npm.

The tags do not change. In a repo that is one package, changesets tags
vX.Y.Z, which is exactly what np tagged, so git describe and the existing
tag history carry on unbroken. Verified against this branch:

==> Preflight (release-toolchain v1.2.0)
Aborted: you are not on main. Use --tag to publish a prerelease from a branch.

What changed

  • .changeset/ added: config.json (baseBranch: main, access: public
    which is what makes the scoped package publish publicly without a
    publishConfig) and the standard README.md explaining the bump levels.
  • @changesets/cli and @datocms/release-toolchain added; np removed — it
    was pinned at five different versions across these seven repos, with zero
    configuration anywhere, so nothing is lost.
  • changeset, release and release:next scripts. The release script must not
    be called publish: this repo's root is the published package, so
    changeset publishnpm publish would run a publish script and the
    release would re-enter itself.
  • CHANGELOG.md added to files, so the changelog changesets is about to start
    writing ships with the package.
  • A Releasing section in the README, and the doctoc TOC regenerated for it.

The build

npm run build here is svelte-kit sync && svelte-package -o package, which
regenerates .svelte-kit/tsconfig.json on the way — so the toolchain's plain
npm run build is enough and no special case is needed. prepublishOnly runs it
a second time inside npm publish, which is harmless and left alone.

How to try it

The first release should be a prerelease, which is real in every way except the
dist-tag:

npx changeset pre enter next
npm run release:next        # publishes X.Y.Z-next.0 under `next`, tags, GitHub release
npx changeset pre exit

latest is untouched and the GitHub release is marked as a prerelease.

https://claude.ai/code/session_01XaYAhzmiJwysZeq1XC5xrQ

Stefano Verna added 2 commits August 31, 2026 12:03
RELEASE.md for this family of repos prescribed a bare `np patch` -
literally always patch, decided on release day, with no changelog coming out
of it at all. Changesets moves that decision into the PR that makes the
change, and writes the changelog from it.

The release script is @datocms/release-toolchain, the same one the four
monorepos run, installed by git tag and never published to npm. In a repo
that is one package it tags vX.Y.Z, which is what np tagged too, so the tag
history is continuous.

Claude-Session: https://claude.ai/code/session_01XaYAhzmiJwysZeq1XC5xrQ
.npmrc here sets engine-strict, and @changesets/cli requires Node ^22.11 or
later, so 'npm ci' now fails outright on 18 and 20 - which is what the matrix
was running. Keeping those jobs green would have meant claiming a
compatibility that nobody can install into: a contributor on Node 18 cannot
'npm ci' this repo either.

Both 18 and 20 are past end-of-life anyway, so the matrix was testing two
dead versions and no current one.

Claude-Session: https://claude.ai/code/session_01XaYAhzmiJwysZeq1XC5xrQ
@stefanoverna

Copy link
Copy Markdown
Member Author

One extra commit: the Node matrix moves to 22 and 24

The first push turned Node.js CI red, and the failure is real rather than
incidental:

npm error code EBADENGINE
npm error Not compatible with your version of node/npm: @changesets/apply-release-plan@8.0.0
npm error Required: {"node":"^22.11 || ^24 || >=26"}
npm error Actual:   {"npm":"10.8.2","node":"v18.20.8"}

.npmrc in this repo sets engine-strict=true, so an unmet engines range is
an error rather than a warning — which is why this shows up here and not in
vue-datocms or react-datocms, whose matrices also run old Node but whose
installs only warn.

There is no way to keep 18 and 20 green that is also honest: @changesets/cli
is a devDependency, npm ci installs it on every matrix job, and a contributor
on Node 18 cannot npm ci this repo either. A passing job on 18 would be
claiming a compatibility nobody can install into. Both versions are also past
end-of-life, so the matrix was testing two dead versions and no current one.

So the matrix is now [22.x, 24.x], with the reason written into the workflow.
This is a change to what CI proves, not to what the package supports: no
engines field is declared here, and nothing in the shipped code changed. If
you want Node 18 covered, that needs a devDependency set that installs there —
a separate conversation from this PR.

Note the sibling job already made the mirror-image decision, and says so:
continuous-releases.yml pins Node 22 because "this job only has to build a
tarball, not prove which Node versions the package supports."

@pkg-pr-new

pkg-pr-new Bot commented Aug 31, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@datocms/svelte@bbd2398

commit: bbd2398

Stefano Verna added 2 commits August 31, 2026 12:26
Rehearsing the resume against a real registry and a real GitHub repo turned
up a bug that every copy of the old script had: killed between
'changeset publish' and 'git push', the next run reads an empty plan - the
packages are on the registry and their tags are local, which is all
changesets looks at - and aborts with 'there is nothing to release', leaving
the commit unpushed and no GitHub release. v1.1.0 finishes that release.

Claude-Session: https://claude.ai/code/session_01XaYAhzmiJwysZeq1XC5xrQ
This repo's root is the published package, so 'npm publish' typed at the
repo root reaches the registry: it skips the tests, the changelog, the tag
and the GitHub release, and npm takes it whenever the working tree carries a
version the registry has not seen. Today a clean checkout carries the version
already published, so the registry answers 403 - a side effect, not a
decision, and it stops holding the moment somebody bumps by hand.

prepublishOnly now runs 'release-toolchain --assert-release', which passes
only while the release script is the one publishing. 'npm pack' runs prepack
instead, so reading a tarball still works and the pkg-pr-new previews, which
pack rather than publish, are untouched.

Also moves the toolchain pin to v1.2.0. The lockfile is the substantive half
of that: changing the spec alone left the previous SHA resolved, so 'npm ci'
kept installing v1.0.0 while package.json claimed otherwise.

Claude-Session: https://claude.ai/code/session_01XaYAhzmiJwysZeq1XC5xrQ
@stefanoverna

Copy link
Copy Markdown
Member Author

One more commit: npm publish typed by hand is now refused

Renaming the script to release means npm run publish fails with npm's
Missing script error. Safe, though npm's suggestion is npm unpublish and it
does not mention release.

npm publish without run is the one that reaches the registry. It skips the
tests, the changelog, the tag and the GitHub release, and npm takes it whenever
the working tree carries a version the registry has not seen. Today a clean
checkout carries the version already published, so the registry answers 403.
That is a side effect of how the toolchain bumps versions, not a decision, and
it stops holding the moment somebody bumps by hand.

So prepublishOnly now runs release-toolchain --assert-release, which passes
only while the release script is the one publishing:

$ npm publish --dry-run
> prepublishOnly
> release-toolchain --assert-release

Aborted: this package is published by 'npm run release'.
  A bare `npm publish` skips the tests, the changelog, the tag and the
  GitHub release, so it is refused here.
  To inspect the tarball without publishing, run 'npm pack'.

npm pack runs prepack rather than prepublishOnly, so reading a tarball
still works, and the pkg-pr-new previews are untouched: it shells out to
npm pack --json, not to npm publish.

The four workspace repos do not get this. Their root package.json is private,
so the same slip at the repo root publishes nothing.

@stefanoverna
stefanoverna merged commit 71a1fca into main Aug 31, 2026
4 checks passed
@stefanoverna
stefanoverna deleted the release-toolchain branch August 31, 2026 10:42
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