Repository navigation
ci: harden releases from maintenance branches - #323
Conversation
Release Draft now runs only on main or a maintenance/<major>.x branch, and drafts a major bump only from main, so a maintenance branch can't publish the next major. Release Publish settles the npm dist-tag against npm's current latest, in .github/scripts/npm-dist-tag.sh. A stable release takes latest only when it is newer, so a maintenance release ships as latest until the next major is out (otherwise npm install would keep resolving the older release), and a release from main that is not newer fails instead of moving latest backwards. The GitHub release is marked latest the same way. npm publishes from different branches run one at a time, so each reads latest after the one before it has published. The rules are checked by npm-dist-tag.spec.sh in the pull request workflow. The zizmor scan also runs on pushes to maintenance branches, and the new RELEASING.md describes the release lines, the dist-tags and how to cut and patch a maintenance branch, including allowing it to deploy to the npm-publish environment. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
🛣️ Rokt Platform Paved Roads Scan Complete✅ No paved-road issues detected Scanned files against 188 rules. · Reviewed commit: 📜 Scan history (1 scan)
ℹ️ About Rokt Platform Paved Roads AgentThis scan was performed by the Rokt Platform Paved Roads Agent, an automated paved-road standards review tool for pull requests. See the User Guide for details on severity levels, feedback reactions, and scan configuration. Reply |
🔒 Security Scan Complete✅ No security issues detected Scanned files against 88 rules. · Reviewed commit: 📜 Scan history (1 scan)
ℹ️ About PR Security AgentThis scan was performed by PR Security Agent, an automated security review tool for pull requests. See the User Guide for details on severity levels, feedback reactions, and scan configuration. Reply |
Why
Once work on the next major release starts, apps that stay on the current major still need fixes, so that major needs its own release branch. The release workflows can already publish from such a branch, but its releases never become the version a plain install picks up, even before the next major exists. A maintenance branch can also draft a major release by mistake, and none of the steps are written down. Once this lands, the current major's branch can be cut from
mainand released from straight away.Programme
Part of preparing the next major release; the plan is internal and cannot be linked.
What changes
Before: Release Draft runs on any branch and offers a major bump everywhere. Release Publish tags
mainreleaseslatestand maintenance releasesmaintenance-<major>.x, whatever is already on npm.After:
mainor amaintenance/<major>.xbranch, and drafts a major bump only frommain.latest.latestonly when it is newer. So a maintenance release ships aslatestuntil the next major is out, then asmaintenance-<major>.x.mainthat is not newer stops with an error instead of movinglatestbackwards.RELEASING.mdcovers release lines, dist-tags, and cutting and patching a maintenance branch; the README's publishing note points to it. The changelog is generated at release.This also needs a repository setting, which this pull request doesn't change. The
npm-publishenvironment deploys only frommain, so an admin must allowmaintenance/*before the first maintenance release.RELEASING.mdmakes this the first step of cutting a branch.Start reading at
.github/scripts/npm-dist-tag.shand its checks, then thepublish-npmjob.Linked work
Unblocks: cutting
maintenance/5.xfrommain(planned, once this merges).Related: the same release rules in mParticle's React Native SDK, mParticle/react-native-mparticle#420.
Rollout
Path: merging changes the release workflows on
main; nothing is published until a release is drafted and merged. A maintenance branch cut afterwards inherits the changes.Feature flags: none.
Turning it off: revert this pull request; the workflows change when the revert merges.
What we watch: the next Release Publish run. Its "Resolve npm dist-tag" step logs the version, the chosen tag and npm's
latest, which is 5.1.2 today. Afterwardsnpm view @rokt/react-native-sdk dist-tagsshould showlateston the newest version. A failed step or alatestthat moved backwards means revert; one correct release means it has settled.Risks
mainis refused as not newer thanlatest; only happens when versions are out of order, and the error names both; we would see Release Publish fail at "Resolve npm dist-tag".latestafter the next major has shipped; prevented by the comparison and by running publishes one at a time; we would seelateston an older major.npm-publishenvironment; not addressed in code, since it is a repository setting documented as the first step of cutting a branch; we would see "Branch is not allowed to deploy".Risk class: low.
Who
Written by: an automated coding agent (Claude Code), at an engineer's request, following an internal plan.
Code reviewed before opening: an independent review agent; it found that the
npm-publishenvironment only allowsmainand that the documented maintenance install command would fail, both fixed. No person yet.Design reviewed before opening: an engineer approved the plan on 21 October 2026.
Decision this implements: an engineering decision of 20 October 2026 to keep the current major on a maintenance branch and land the pipeline changes first; internal, cannot be linked.
Checked: on 21 October 2026, locally: the dist-tag checks (10 of 10); the script against the live registry (5.2.0 from a maintenance branch gets
latestwhilelatestis 5.1.2, and 5.1.0 frommainstops with an error); the branch check; the workflow files parse;trunk checkon the changed files.Not checked: the release workflows on GitHub, which run only on dispatch or a
VERSIONchange; the workflow security scan, which runs on this pull request.Size
Hand-written: 180 lines (176 added, 4 removed) across 8 files.
Generated: none.
🤖 Generated with Claude Code