Add a prerelease release process - #4086
Conversation
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.
Tip: disable this comment in your organization's Code Review settings.
|
Subscribed to pull request
Generated by CodeMention Warning: The preamble and epilogue options in commentConfiguration are deprecated. Use template instead. |
8c0ae42 to
1ca4c7e
Compare
There was no way to ship a version for people to try. Running the existing release with a prerelease version would have been actively harmful: `lerna publish from-package` passed no --dist-tag and npm has not special-cased prerelease versions since v7, so `latest` would have pointed at the prerelease and every `npx eas-cli` user would have gotten it. The run would also have moved `latest-eas-build` and `latest-eas-build-staging` — which select the CLI version for EAS Build, so a prerelease would have reached production builds — and consumed the unreleased CHANGELOG.md section, committing it to main and Slack-announcing it as a release. The stale `next` (7.1.0) and `alpha` (0.16.1-alpha.0) dist-tags show how long it has been since anyone tried. Detect a SemVer prerelease identifier on the pushed tag and branch on it: publish under `next`, skip both EAS Build dist-tag steps, and skip the changelog job so the entries stay unreleased for the stable release that follows. The GitHub release is published immediately and flagged as a prerelease instead of waiting for the changelog job to un-draft it. The dist-tag is now always passed explicitly. `latest` is what npm defaulted to, so stable releases are unchanged — but that silent default is what made this unsafe, so the intent is stated rather than inherited. Documents the process, what differs from a stable release, how it interacts with the other packages in the monorepo (fixed mode versions only what changed; `next` covers every package published in the run), and that prereleases are cut from main so they are not the tool for validating an unmerged branch.
1ca4c7e to
6ffce49
Compare
|
⏩ The changelog entry check has been skipped since the "no changelog" label is present. |
🤖 AI code reviewDecision: Approve with comments
No findings. This review is advisory — it never blocks a merge and never auto-approves. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4086 +/- ##
=======================================
Coverage 61.73% 61.73%
=======================================
Files 988 988
Lines 44306 44306
Branches 9304 9304
=======================================
Hits 27349 27349
Misses 15503 15503
Partials 1454 1454 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Why
There is no way to ship a version for people to try before committing to a stable release, and the existing release workflow could not safely be reused for one. Passing a prerelease version to it today would:
latestat the prerelease.lerna publish from-package --yes --no-verify-accesspasses no--dist-tag, and there is nopublishConfig.tag. npm has not special-cased prerelease versions since v7, so21.3.0-beta.0would becomelatestand everynpx eas-cliuser would get it.npm dist-tag add … latest-eas-build-stagingand… latest-eas-buildrun unconditionally. Those select the CLI version used by EAS Build, so a prerelease would land in production builds. They are sensitive enough to have their own gated workflow (move-eas-build-tag.yml, withstaging_onlyanddry_run).release-changelogjob cuts the unreleased section, commitsCHANGELOG.mdtomainand Slack-announces it as a release — so the eventual stable release would lose those entries.The stale dist-tags show how long it has been since anyone tried:
next→ 7.1.0,alpha→ 0.16.1-alpha.0, and the only prerelease versions ever published are0.1.0-alpha.*and0.16.1-alpha.0.How
release.ymlgains aresolvejob that derives the version from the pushed tag and classifies it by the presence of a SemVer prerelease identifier. Every other job branches on that one output rather than re-deriving it.latestnextlatest-eas-build/-stagingCutting one uses the existing "Manually trigger a release" workflow with an explicit version such as
21.3.0-beta.0— the identifier is free-form, so-rc.1and-canary.0work too. It has to be explicit because the changelog-based algorithm only ever produces stable versions.release.shneeded no change: it passes the version straight through tolerna version --exact.The dist-tag is now always passed explicitly.
latestis what npm defaulted to, so stable releases are byte-identical in behaviour — but that silent default is exactly what made a prerelease unsafe, so the intent is stated rather than inherited.Interaction with the other packages
Prereleases version and publish packages exactly as stable releases do. lerna runs in fixed mode, so it applies the single
lerna.jsonversion to the packages that changed since the last release and leaves the rest alone — which is why the packages currently sit at 21.0.0 / 21.0.2 / 21.1.0 / 21.2.0.from-packagethen publishes whichever of those aren't on the registry, and--dist-tag nextcovers every package published in that run.latestis untouched for all of them, so nothing depending on@expo/eas-json,@expo/stepsor@expo/eas-build-jobpicks up a prerelease implicitly. Two consequences are documented inRELEASING.md: the version line is shared (after21.3.0-beta.0the next stable from main is21.3.0), andmaincarries the prerelease version until the next release (the changelog algorithm still resolves correctly from there — a MINOR or PATCH bump off21.3.0-beta.0both land on21.3.0).Test plan
Both workflows parse, and the conditionals resolve to the intended jobs/steps. Verified the classification against every identifier style, mirroring the shell logic exactly as the workflow runs it:
Also confirmed
--dist-tagis a supportedlerna publishflag on the pinned lerna 9.0.3 (npx lerna publish --help), and thatsemver.incoff a prerelease resolves as documented.What this cannot verify without spending a version number: the end-to-end publish. The first real prerelease is the proof, and it is cheap to check — after it runs,
npm view eas-cli dist-tagsmust still showlatestat the current stable andlatest-eas-buildunmoved. Recommend the first one be cut withdry_run: truefirst to confirm the version resolution, then for real.no changeloglabel applied: this changes release infrastructure and documentation only, with no effect on the published CLI.