Skip to content

Conversation

@j-piasecki
Copy link
Member

Description

Overhaul of the release process:

  • adds beta and rc options to the previously existing stable and commitly
  • allows the release of a specific version, independent from the branch name (optional, will still detect the version from the branch name when unspecified)
  • verifies that the latest version is either one patch, one minor, or one major higher than the currently published version (ATM throws on major change)
  • verifies that beta, rc and commitly releases aren't done for an already published version (i.e. will disallow publishing 2.30.0-beta.1 when stable 2.30.0 is published`).
  • automatic numbering of beta and rc releases

Internally:

  • moved most of the helpers to separate files
  • moved version numbering helpers to version-utils
  • added tests covering the release scripts

Test plan

Tested on a fork:

Copilot AI review requested due to automatic review settings January 29, 2026 12:10
Copy link
Contributor

Copilot AI left a 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.

Comment on lines +53 to +65
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;
}
}
Copy link

Copilot AI Jan 29, 2026

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.

Copilot uses AI. Check for mistakes.
Copy link
Member Author

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.

Comment on lines +4 to +10
function versionExists(version) {
try {
getPackageVersionByTag('react-native-gesture-handler', version);
return true;
} catch (error) {
return false;
}
Copy link

Copilot AI Jan 29, 2026

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.

Copilot uses AI. Check for mistakes.
Copy link
Member Author

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.

Comment on lines +36 to +49
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];
}
Copy link

Copilot AI Jan 29, 2026

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.

Copilot uses AI. Check for mistakes.
Copy link
Member Author

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.

@j-piasecki j-piasecki marked this pull request as ready for review January 29, 2026 14:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants