Repository navigation
CORE-4004: Tag each release in publish.bash - #182
Merged
Merged
Conversation
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…nd-in Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
RoyEJohnson
force-pushed
the
release-tag-in-publish-script
branch
from
October 26, 2026 23:02
899032c to
6f9603d
Compare
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

publish.bashran onlynpm ci, a build andnpm publish, so a release had no git tag unless someone made one by hand. Consumers that install from git, such as rex-web withopenstax/ui-components#1.24.2, need the tag. 1.26.1 to 1.26.3 are in the registry without tags, and I tagged 1.26.4 by hand.The script used to tag before the registry switch in #124. This restores that, in a non-interactive form that moves no branch.
The approach
Publishing can't be undone, so the script creates the tag before it publishes. Everything that can go wrong with the tag (the git identity, tag signing, a clash, the package not matching it) then fails before
npm publish, using the real tag and not a stand-in for it. An earlier version of this PR tried to predict those failures with a--checkmode that made a throwaway tag, and each review round found another way the stand-in differed from the real run. Creating the real tag first removes that whole class, and the throwaway tag with it. The only step left after the publish is pushing the tag, which is one command to repeat.The tag is an annotated tag named for the version (no
vprefix, like1.25.0) on a "Dist files" commit: the release commit plus the builtdist/. The commit is built in a temporary index, so no branch moves and the working tree is untouched, and it is reachable only from the tag. This is the same shape as the existing1.25.0and1.26.4tags.What
publish.bashdoesThe release commit is
HEADwhen the script starts, recorded once. Then, in order:package.jsonisn'tMAJOR.MINOR.PATCHorMAJOR.MINOR.PATCH-prerelease(no build metadata). A pre-release is published with--tag next, so it never takes thelatestdist-tag.npm whoami).npm ciandnpm run build:clean, then stop if the build changed any tracked file.build:cleanregeneratessrc/theme/theme.css, and a stale committed copy would be published but missing from the tag.tag.gpgSignis on, fails.scripts/verify-release.mjs <tag>: every filenpm pack --dry-runwould publish must be in the tag's tree with the same contents. Files are hashed as they are on disk, with no line-ending conversion, because npm packs the bytes on disk and not what git would store. This catches an untracked or ignored file undersrc/, a checkout with CRLF line endings fromcore.autocrlf(git treats it as clean, but the package would contain CRLF while the tag holds LF), and anything else that would make the package and the tag differ.HEADhas moved since the script started.npm publishto the same registry the login was checked against (--registry), with--tag nextfor a pre-release, then push the tag.If the script stops before the publish is attempted, it deletes the tag it created, and only that tag: a tag it didn't create makes it stop at step 1 and is left alone. If
npm publishfails, or the push fails after it, the tag is kept and the message says what to run:git push origin refs/tags/<version>, orgit tag -d <version>if the package was not published.The README's "Git Tags" section said tags were used "instead of npm publishing". It now describes both ways to install, the tag naming, the release steps and these checks.
Tested
I ran the script in a scratch clone with a local bare repository as
originandnpmstubbed. Each of these stops beforenpm publish, leaves no tag behind and makes no registry call:MAJOR.MINOR.PATCH[-prerelease](01.2.3,1.26,1.2.3+b,1.2.3-), before any tag or build. A pre-release such as1.2.3-pre1passes validation. The--tag nextargument itself is checked only in isolation, not through a full stubbed publish.npm ci).tag.gpgSignon, and no git identity.src/that the package would include.core.autocrlf=true, where git reports a clean tree. Hashing it with git's filters would have matched the tag's LF copy, and the unfiltered check rejects it.HEADmoves between the build and the publish.And these keep the tag, with the message above:
git push origin refs/tags/<version>afterwards pushes it.npm publishfails.A full run publishes (stub) and pushes an annotated tag whose commit has the release commit as its parent and differs from it only by the
dist/files. IfHEADmoves during the publish itself, the tag is still on the release commit. The branch doesn't move and the working tree stays clean.I also ran the real build in this repo, made a real tag with the same steps, and the verifier passed: the 382
dist/files and everything insrc/match, so a normal release won't be blocked by it. I have not run any of this against the real registry.One trade-off: because the tag needs the built
dist/, an identity or signing problem now shows up after thenpm ciand build rather than before them. It is still before the publish, which is the part that can't be undone.This PR has no Jira ticket in its title. Add one if the check needs it.
🤖 Generated with Claude Code