-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Update release flow to be more robust #3938
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Overhauls the npm release automation to support additional release channels (beta/rc), optional explicit version publishing, and stronger validation around what can be published and tagged.
Changes:
- Add release helpers for computing next stable/pre-release versions and validating latest vs non-latest publishes.
- Refactor release scripting by extracting argument parsing and version computation into dedicated modules.
- Add Jest-based unit tests for the release scripts and introduce a CI workflow to run them.
Reviewed changes
Copilot reviewed 17 out of 18 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| yarn.lock | Adds Jest dependency to lockfile for running new script tests. |
| package.json | Adds test script and Jest dev dependency for running release-script tests. |
| scripts/release/version-utils.js | Adds helpers to compute latest/next stable/pre-release versions using npm registry queries. |
| scripts/release/validate-non-latest-version.js | Adds validation to prevent publishing non-latest releases when the base version already exists. |
| scripts/release/validate-latest-version.js | Adds validation to ensure latest-tagged stable releases increment semver correctly. |
| scripts/release/should-be-latest.js | Expands logic for deciding whether a stable release should be tagged as latest. |
| scripts/release/set-package-version.js | Refactors to use shared argument parsing + version selection helpers. |
| scripts/release/parse-arguments.js | Introduces centralized CLI flag parsing for release scripts. |
| scripts/release/get-version.js | Implements version selection logic per release type (stable/beta/rc/commitly). |
| scripts/release/tests/version-utils.test.js | Adds unit tests for version parsing and next-version helpers. |
| scripts/release/tests/validate-non-latest-version.test.js | Adds unit tests for non-latest publish validation logic. |
| scripts/release/tests/validate-latest-version.test.js | Adds unit tests for latest publish validation logic. |
| scripts/release/tests/should-be-latest.test.js | Adds unit tests for npm-tag selection logic. |
| scripts/release/tests/parse-arguments.test.js | Adds unit tests for release CLI argument parsing. |
| scripts/release/tests/get-version.test.js | Adds unit tests for deriving versions for each release type. |
| .github/workflows/run-jest-tests.yml | Adds a CI workflow to run the new Jest tests. |
| .github/workflows/publish-release.yml | Extends publish workflow to support manual stable/beta/rc and automatic commitly releases. |
| .github/actions/publish-npm-package/action.yml | Updates composite action to accept release type/version, determine npm tag, and validate versions before publishing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| function getNextPreReleaseVersion(releaseType, version) { | ||
| let dotIndex = 1; | ||
| while (true) { | ||
| const targetVersion = `${version}-${releaseType}.${dotIndex}`; | ||
|
|
||
| try { | ||
| // if the version is already published, increment the pre-release sequence (rc/beta number) and try again | ||
| getPackageVersionByTag('react-native-gesture-handler', targetVersion); | ||
| dotIndex++; | ||
| } catch (error) { | ||
| return targetVersion; | ||
| } | ||
| } |
Copilot
AI
Jan 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getNextPreReleaseVersion also treats any getPackageVersionByTag failure as "version doesn't exist". This can incorrectly pick a pre-release number if npm view fails for transient reasons. Suggest the same approach as stable: distinguish "not found" from other errors (or add retries) instead of assuming all errors mean absence.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be fine - worst case we try to publish with a version number that's already been published and the process fails.
| function versionExists(version) { | ||
| try { | ||
| getPackageVersionByTag('react-native-gesture-handler', version); | ||
| return true; | ||
| } catch (error) { | ||
| return false; | ||
| } |
Copilot
AI
Jan 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
versionExists treats any failure from getPackageVersionByTag as "version does not exist". Since npm-utils throws the same error for 404s and for transient npm/network failures, this can incorrectly allow publishing a version that already exists when npm is temporarily unavailable. Consider distinguishing "not found" from other failures (or retrying) and rethrowing unexpected errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be fine - worst case we try to publish with a version number that's already been published and the process fails.
| function getNextStableVersion() { | ||
| const [major, minor] = getStableBranchVersion(); | ||
|
|
||
| let nextPatch = 0; | ||
| while (true) { | ||
| const version = `${major}.${minor}.${nextPatch}`; | ||
|
|
||
| try { | ||
| // if the version is already published, increment the patch version and try again | ||
| getPackageVersionByTag('react-native-gesture-handler', version); | ||
| nextPatch++; | ||
| } catch (error) { | ||
| return [Number(major), Number(minor), nextPatch]; | ||
| } |
Copilot
AI
Jan 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getNextStableVersion treats any error from getPackageVersionByTag as "version does not exist" and returns the current nextPatch. With the current npm-utils implementation, transient npm/network failures are indistinguishable from an actual 404, which could cause selecting an already-published version. Consider surfacing the underlying npm error in npm-utils and only treating a real "not found"/E404 as the signal to stop; rethrow or retry on other failures.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be fine - worst case we try to publish with a version number that's already been published and the process fails.
Description
Overhaul of the release process:
betaandrcoptions to the previously existingstableandcommitly2.30.0-beta.1when stable2.30.0is published`).Internally:
version-utilsTest plan
Tested on a fork: