react-native/scripts/version-utils.js
Lorenzo Sciandra 7adf6b1e63 fix(script): handle patch versions after the .0 for set version (#36020)
Summary:
A small backport to main of a local fix done in 0.71 to account for the logic for releases 0.Y.1,2,3-prerelease (meaning, not just strictly 0).

I could have done like the other logics and just remove the check for patch, but decided to at least make sure it's a digit 😅

## Changelog

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[INTERNAL] [FIXED] - handle patch versions after the .0 for set version

Pull Request resolved: https://github.com/facebook/react-native/pull/36020

Test Plan: Tested in 0.71-stable, without it we can't test RNTestProject.

Reviewed By: jacdebug, cortinico

Differential Revision: D42924375

Pulled By: cipolleschi

fbshipit-source-id: b003d884cc45a2602adbc14fa8b66d3f1e0c94a6
2023-02-07 03:45:17 -08:00

166 lines
3.8 KiB
JavaScript

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
const VERSION_REGEX = /^v?((\d+)\.(\d+)\.(\d+)(?:-(.+))?)$/;
/**
* Parses a version string and performs some checks to verify its validity.
* A valid version is in the format vX.Y.Z[-KKK] where X, Y, Z are numbers and KKK can be something else.
* The `builtType` is used to enforce that the major version can assume only specific
* values.
*
* Some examples of valid versions are:
* - stable: 0.68.1
* - stable prerelease: 0.70.0-rc.0
* - e2e-test: X.Y.Z-20221116-2018
* - nightly: 0.0.0-20221116-2018-0bc4547fc
* - dryrun: 1000.0.0
*
* Parameters:
* - @versionStr the string representing a version
* - @buildType the build type. It can be of values: `dry-run`, `release`, `nightly`
*
* Returns: an object with the shape:
* ```
* {
* version: string,
* major: number,
* minor: number,
* patch: number,
* prerelease: string
* }
* ```
*
*/
function parseVersion(versionStr, buildType) {
try {
validateBuildType(buildType);
} catch (e) {
throw e;
}
const match = extractMatchIfValid(versionStr);
const [, version, major, minor, patch, prerelease] = match;
const versionObject = {
version,
major,
minor,
patch,
prerelease,
};
try {
validateVersion(versionObject, buildType);
} catch (e) {
throw e;
}
return versionObject;
}
function validateBuildType(buildType) {
const validBuildTypes = new Set(['release', 'dry-run', 'nightly']);
if (!validBuildTypes.has(buildType)) {
throw new Error(`Unsupported build type: ${buildType}`);
}
}
function extractMatchIfValid(versionStr) {
const match = versionStr.match(VERSION_REGEX);
if (!match) {
throw new Error(
`You must pass a correctly formatted version; couldn't parse ${versionStr}`,
);
}
return match;
}
function validateVersion(versionObject, buildType) {
const map = {
release: validateRelease,
'dry-run': validateDryRun,
nightly: validateNightly,
};
const validationFunction = map[buildType];
validationFunction(versionObject);
}
/**
* Releases are in the form of 0.Y.Z[-RC.0]
*/
function validateRelease(version) {
const validRelease = isStableRelease(version) || isStablePrerelease(version);
if (!validRelease) {
throw new Error(`Version ${version.version} is not valid for Release`);
}
}
function validateDryRun(version) {
if (
!isMain(version) &&
!isNightlyBuild(version) &&
!isStableRelease(version) &&
!isStablePrerelease(version)
) {
throw new Error(`Version ${version.version} is not valid for dry-runs`);
}
}
function validateNightly(version) {
// a valid nightly is a prerelease
if (!isNightlyBuild(version)) {
throw new Error(`Version ${version.version} is not valid for nightlies`);
}
}
function isStableRelease(version) {
return (
version.major === '0' && version.minor !== '0' && version.prerelease == null
);
}
function isStablePrerelease(version) {
return (
version.major === '0' &&
version.minor !== '0' &&
version.patch.match(/^\d+$/) &&
version.prerelease != null &&
(version.prerelease.startsWith('rc.') ||
version.prerelease.startsWith('rc-') ||
version.prerelease.match(/^(\d{8})-(\d{4})$/))
);
}
function isNightlyBuild(version) {
return (
version.major === '0' && version.minor === '0' && version.patch === '0'
);
}
function isMain(version) {
return (
version.major === '1000' && version.minor === '0' && version.patch === '0'
);
}
function isReleaseBranch(branch) {
return branch.endsWith('-stable');
}
module.exports = {
validateBuildType,
parseVersion,
isReleaseBranch,
isMain,
isStableRelease,
isStablePrerelease,
};