Skip to content

Add a prerelease release process - #4086

Draft
brentvatne wants to merge 1 commit into
mainfrom
brent/prerelease-process
Draft

Add a prerelease release process#4086
brentvatne wants to merge 1 commit into
mainfrom
brent/prerelease-process

Conversation

@brentvatne

@brentvatne brentvatne commented Jul 27, 2026

Copy link
Copy Markdown
Member

Everything below was written by Claude

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:

  1. Point latest at the prerelease. lerna publish from-package --yes --no-verify-access passes no --dist-tag, and there is no publishConfig.tag. npm has not special-cased prerelease versions since v7, so 21.3.0-beta.0 would become latest and every npx eas-cli user would get it.
  2. Move the EAS Build tags. Both npm dist-tag add … latest-eas-build-staging and … latest-eas-build run 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, with staging_only and dry_run).
  3. Consume the changelog. The release-changelog job cuts the unreleased section, commits CHANGELOG.md to main and 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: next7.1.0, alpha0.16.1-alpha.0, and the only prerelease versions ever published are 0.1.0-alpha.* and 0.16.1-alpha.0.

How

release.yml gains a resolve job 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.

Stable Prerelease
npm dist-tag latest next
latest-eas-build / -staging moved left alone
CHANGELOG.md cut and committed left alone
GitHub release draft → published published, flagged as prerelease
Slack announcement in #eas-cli yes no

Cutting 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.1 and -canary.0 work too. It has to be explicit because the changelog-based algorithm only ever produces stable versions. release.sh needed no change: it passes the version straight through to lerna version --exact.

The dist-tag is now always passed explicitly. latest is 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.json version 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-package then publishes whichever of those aren't on the registry, and --dist-tag next covers every package published in that run. latest is untouched for all of them, so nothing depending on @expo/eas-json, @expo/steps or @expo/eas-build-job picks up a prerelease implicitly. Two consequences are documented in RELEASING.md: the version line is shared (after 21.3.0-beta.0 the next stable from main is 21.3.0), and main carries the prerelease version until the next release (the changelog algorithm still resolves correctly from there — a MINOR or PATCH bump off 21.3.0-beta.0 both land on 21.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:

21.3.0             prerelease=false dist-tag=latest  eas-build-tags=moved    changelog=cut
21.3.0-beta.0      prerelease=true  dist-tag=next    eas-build-tags=skipped  changelog=untouched
21.3.0-rc.1        prerelease=true  dist-tag=next    eas-build-tags=skipped  changelog=untouched
21.3.0-canary.0    prerelease=true  dist-tag=next    eas-build-tags=skipped  changelog=untouched

Also confirmed --dist-tag is a supported lerna publish flag on the pinned lerna 9.0.3 (npx lerna publish --help), and that semver.inc off 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-tags must still show latest at the current stable and latest-eas-build unmoved. Recommend the first one be cut with dry_run: true first to confirm the version resolution, then for real.

no changelog label applied: this changes release infrastructure and documentation only, with no effect on the published CLI.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@brentvatne brentvatne added the no changelog PR that doesn't require a changelog entry label Jul 27, 2026
@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown

Subscribed to pull request

File Patterns Mentions

Generated by CodeMention

Warning: The preamble and epilogue options in commentConfiguration are deprecated. Use template instead.

@brentvatne brentvatne added the ai-review Commits pushed to PRs with this label be automatically reviewed. label Jul 27, 2026
@brentvatne
brentvatne force-pushed the brent/prerelease-process branch from 8c0ae42 to 1ca4c7e Compare July 27, 2026 02:20
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.
@brentvatne
brentvatne force-pushed the brent/prerelease-process branch from 1ca4c7e to 6ffce49 Compare July 27, 2026 02:22
@github-actions

Copy link
Copy Markdown

⏩ The changelog entry check has been skipped since the "no changelog" label is present.

@github-actions

Copy link
Copy Markdown

🤖 AI code review

Decision: Approve with comments

⚠️ The AI review could not complete: every review pass failed or timed out, so these changes were effectively NOT reviewed. Treat this as "no review", not "looks good".

⏱️ Coverage note: coverage is partial — some review passes did not
finish (timed out or failed), so issues may exist in areas not fully reviewed:

  • The model provider rejected the request (authentication or permission). Check the configured credential (auth.tokenEnv, or REVIEWER_MODEL for a local run) and re-run — those changes were not reviewed.

No findings.


This review is advisory — it never blocks a merge and never auto-approves.

@codecov

codecov Bot commented Jul 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 61.73%. Comparing base (8dc6bff) to head (6ffce49).

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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@brentvatne
brentvatne marked this pull request as draft July 27, 2026 02:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-review Commits pushed to PRs with this label be automatically reviewed. no changelog PR that doesn't require a changelog entry

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant