Skip to content

feat(release): one v-tag per release, carrying the GitHub release notes - #53

Merged
stefanoverna merged 2 commits into
mainfrom
feat/single-version-tag-and-github-release
Aug 25, 2026
Merged

feat(release): one v-tag per release, carrying the GitHub release notes#53
stefanoverna merged 2 commits into
mainfrom
feat/single-version-tag-and-github-release

Conversation

@stefanoverna

@stefanoverna stefanoverna commented Aug 25, 2026

Copy link
Copy Markdown
Member

Backport of datocms/plugins-sdk#49 and datocms/plugins-sdk#50. It lands here
before the first changesets release rather than after one, so there's
nothing to patch up afterwards.

The tag

changeset publish tags every package separately. Here that's nine tags per
release
@datocms/cma-client@5.9.0, @datocms/dashboard-client@5.9.0, … —
all pointing at the same commit and all saying the same thing, because the
@datocms/* packages are a fixed group. It also means the vX.Y.Z tag this
repo has used for its entire history (every one of its tags is vX.Y.Z) would
have silently stopped being created at the next release.

So changeset publish now runs with --no-git-tag, and the script creates
vX.Y.Z itself, right after the publish returns.

That doesn't weaken the ordering invariant this script was built around, it
tightens it: a tag can still only exist for a version that is actually on the
registry, and a partial publish now leaves no tag at all instead of one tag
per package that made it through.

The release notes

Only 5 tags here ever got a GitHub release, and the most recent one
(v5.7.0) is still a draft — because writing one meant composing it by hand.
Changesets now writes exactly that prose into the CHANGELOG.mds.

With nine lockstep packages, posting every section verbatim gives 46 lines of
release notes carrying one line of actual content
: each package's changelog
dutifully records that the other eight moved. So a section is included only if
it has a bullet that is neither Updated dependencies nor a bare pkg@version,
and a footer lists everything that shipped, so a package with no prose of its
own doesn't vanish from the notes.

Run against a real changeset version rehearsal of this repo (a single minor
changeset on @datocms/cma-client), that's 46 lines down to 22:

## @datocms/cma-client

### Minor Changes

- Rehearsal: a change that touches only one package.

### Patch Changes

- @datocms/rest-client-utils@5.9.0

---

Released in lockstep:
- @datocms/cma-client@5.9.0
- @datocms/cma-client-analysis@5.9.0
- @datocms/cma-client-browser@5.9.0
- @datocms/cma-client-node@5.9.0
- @datocms/cma-schema-types-generator@5.9.0
- @datocms/dashboard-client@5.9.0
- @datocms/rest-api-events@5.9.0
- @datocms/rest-api-reference@5.9.0
- @datocms/rest-client-utils@5.9.0

A prerelease is marked --prerelease, so a publish-next can't take over the
repository's "Latest release" badge. The script prints the release URL when it
finishes.

Preflight

gh and its auth are now checked next to npm whoami, so a missing GitHub CLI
stops the release before anything is mutated rather than after npm has already
been published to.

How this was verified

  • --no-git-tag suppresses every tag, not just some. Read from the installed
    source: @changesets/cli/dist/publish.mjs:94 guards the tag-only path and
    :188 the successful-publish path, both with the same
    options?.gitTag ?? true. With the flag off, gitTagReleases stays empty.
  • The flag parses and composes with --tag — replayed the CLI's own option
    declaration through cac with --no-git-tag --tag next.
  • The release notes are real output, from a changeset version rehearsal on
    a scratch copy of this repo (the block above).
  • gh release create --notes-file - reads stdin, and the whole
    tag→push→release path was exercised for real in plugins-sdk when
    v2.2.7 was
    backfilled with these same helpers.

Not verified here: the script has not been run end to end in this repo — the
next release will be its first run.

The resume check, which was wrong here

Included in this PR rather than left for later, because the tag change makes it
more visible: with --no-git-tag there is no per-package tag to tell you how far
a failed publish got.

The check asked whether @datocms/cma-client was on the registry. The nine
packages publish one after another, so a run that dies partway leaves some on
npm and the rest not — and if cma-client was among the ones that made it, the
script reports "nothing to release" for a release that is half done. The only
way out was publishing the stragglers by hand, which is exactly the class of
problem this script exists to remove.

It now asks which packages are missing and resumes if that list isn't empty,
printing it so you can see what's left.

Verified against the real registry:

state old check new check
all nine at 5.8.0, published nothing to release nothing to release
cma-client at 5.8.0, three siblings at an unpublished version "nothing to release" names all three ✓

Backport of datocms/plugins-sdk#49 and #50, and it lands here before the first
changesets release rather than after one, so nothing has to be patched up.

`changeset publish` tags every package separately — nine tags per release here,
all pointing at the same commit and all saying the same thing, since the
`@datocms/*` packages are a `fixed` group. It also means the `vX.Y.Z` tag this
repo has used for its whole history would silently stop being created.

So publish now runs with `--no-git-tag` and the script tags `vX.Y.Z` itself,
after the publish returns. That keeps the ordering invariant this script was
built around — a tag can only exist for a version that is on the registry — and
tightens it: a partial publish now leaves no tag at all, rather than a tag for
each package that made it through.

The tag then carries the release notes. Only 5 of this repo's tags ever got a
GitHub release, because writing one meant composing it by hand; changesets has
already written that prose into the CHANGELOG.md files. A section is included
only if it has a bullet that isn't `Updated dependencies` or a bare
`pkg@version` — with nine lockstep packages the unfiltered version was 46 lines
of notes carrying a single line of content — and a footer lists every package
published at that version so none of them becomes invisible.

`gh` is checked in preflight, alongside npm auth, so a missing GitHub CLI stops
the release before anything is mutated rather than after npm has been published.
The resume check asked whether `@datocms/cma-client` was on the registry. The
nine packages publish one after another, so a run that dies partway leaves some
of them on npm and the rest not — and if cma-client was among the ones that made
it, the check reports "nothing to release" for a release that is half done. The
only way out was then to publish the stragglers by hand, which is the class of
problem this script exists to remove.

It now asks which packages are missing, and resumes if that list isn't empty,
printing it so you can see what's left. Verified against the real registry: with
every package at 5.8.0 the list is empty, and with cma-client left at 5.8.0
while three siblings sit at an unpublished version, the old check answers
"nothing to do" while this one names all three.
@stefanoverna
stefanoverna merged commit 90c0e04 into main Aug 25, 2026
3 checks passed
@stefanoverna
stefanoverna deleted the feat/single-version-tag-and-github-release branch August 25, 2026 11:28
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