Add support for patch rc versions

Summary:
We might want to publish some new versions of React Native with experimental feature to allow some partners to test whether those versions fixes some reported issues, before creating a proper stable version for the whole ecosystem.

The infra is mostly [setup for this](https://www.internalfb.com/code/fbsource/[496a64d180faab501b8598aa0ec26d47454fb961]/xplat/js/react-native-github/scripts/releases/utils/version-utils.js?lines=149), already. The only detail we need to take care of is not to move the `next` tag.

## Changelog:
[Internal]

Reviewed By: cortinico, huntie

Differential Revision: D56578456

fbshipit-source-id: 8dcc674aab5f85077c1b3e6580c5aeb99226eff8
This commit is contained in:
Riccardo Cipolleschi 2024-04-25 15:17:34 -07:00 committed by Facebook GitHub Bot
parent 7b44c8d1d0
commit 993f500fcf
4 changed files with 66 additions and 14 deletions

View File

@ -16,6 +16,7 @@ const {
const execMock = jest.fn();
const getCurrentCommitMock = jest.fn();
const exitIfNotOnGitMock = jest.fn();
jest.mock('shelljs', () => ({
exec: execMock,
@ -23,6 +24,7 @@ jest.mock('shelljs', () => ({
jest.mock('./../scm-utils', () => ({
getCurrentCommit: getCurrentCommitMock,
exitIfNotOnGit: exitIfNotOnGitMock,
}));
describe('npm-utils', () => {
@ -103,6 +105,13 @@ describe('npm-utils', () => {
{cwd: 'path/to/my-package'},
);
});
it('should handle -no-tag', () => {
publishPackage('path/to/my-package', {tags: ['--no-tag'], otp: 'otp'});
expect(execMock).toHaveBeenCalledWith('npm publish --no-tag --otp otp', {
cwd: 'path/to/my-package',
});
});
});
describe('getNpmInfo', () => {
@ -117,6 +126,29 @@ describe('npm-utils', () => {
tag: 'prealpha',
});
});
it('return the expected format for patch-prereleases', () => {
const isoStringSpy = jest.spyOn(Date.prototype, 'toISOString');
isoStringSpy.mockReturnValue('2023-10-04T15:43:55.123Z');
getCurrentCommitMock.mockImplementation(() => 'abcd1234');
// exitIfNotOnGit takes a function as a param and it:
// 1. checks if we are on git => if not it exits
// 2. run the function passed as a param and return the output to the caller
// For the mock, we are assuming we are on github and we are returning `false`
// as the `getNpmInfo` function will pass a function that checks if the
// current commit is a tagged with 'latest'.
// In the Mock, we are assuming that we are on git (it does not exits) and the
// checkIfLatest function returns `false`
exitIfNotOnGitMock.mockImplementation(() => false);
process.env.CIRCLE_TAG = 'v0.74.1-rc.0';
const returnedValue = getNpmInfo('release');
expect(returnedValue).toMatchObject({
version: `0.74.1-rc.0`,
tag: '--no-tag',
});
process.env.CIRCLE_TAG = null;
});
});
describe('getVersionsBySpec', () => {

View File

@ -95,7 +95,7 @@ function getNpmInfo(buildType /*: BuildType */) /*: NpmInfo */ {
);
}
const {version, major, minor, prerelease} = parseVersion(
const {version, major, minor, patch, prerelease} = parseVersion(
process.env.CIRCLE_TAG,
buildType,
);
@ -108,15 +108,19 @@ function getNpmInfo(buildType /*: BuildType */) /*: NpmInfo */ {
);
const releaseBranchTag = `${major}.${minor}-stable`;
let tag = releaseBranchTag;
// npm will automatically tag the version as `latest` if no tag is set when we publish
// To prevent this, use `releaseBranchTag` when we don't want that (ex. releasing a patch on older release)
const tag =
prerelease != null
? 'next'
: isLatest === true
? 'latest'
: releaseBranchTag;
if (prerelease != null) {
if (patch === '0') {
// Set `next` tag only on prereleases of 0.m.0-RC.k.
tag = 'next';
} else {
tag = '--no-tag';
}
} else if (isLatest === true) {
tag = 'latest';
}
return {
version,
@ -133,13 +137,17 @@ function publishPackage(
execOptions /*: ?ExecOptsSync */,
) /*: ShellString */ {
const {otp, tags, access} = packageOptions;
const tagsFlag =
tags != null
? tags
let tagsFlag = '';
if (tags != null) {
tagsFlag = tags.includes('--no-tag')
? ' --no-tag'
: tags
.filter(Boolean)
.map(t => ` --tag ${t}`)
.join('')
: '';
.join('');
}
const otpFlag = otp != null ? ` --otp ${otp}` : '';
const accessFlag = access != null ? ` --access ${access}` : '';
const options = execOptions

View File

@ -135,6 +135,18 @@ describe('version-utils', () => {
expect(prerelease).toBe('rc.4');
});
it('should parse patch pre-release version from tag', () => {
const {version, major, minor, patch, prerelease} = parseVersion(
'v0.66.1-rc.4',
'release',
);
expect(version).toBe('0.66.1-rc.4');
expect(major).toBe('0');
expect(minor).toBe('66');
expect(patch).toBe('1');
expect(prerelease).toBe('rc.4');
});
it('should reject pre-release version from tag with random prerelease pattern', () => {
function testInvalidVersion() {
parseVersion('v0.66.0-something_invalid', 'release');

View File

@ -29,7 +29,7 @@ export type Version = {
*
* Some examples of valid versions are:
* - stable: 0.68.1
* - stable prerelease: 0.70.0-rc.0
* - prerelease: 0.Y.Z-rc.K
* - e2e-test: X.Y.Z-20221116-2018
* - nightly: X.Y.Z-20221116-0bc4547fc
* - dryrun: 1000.0.0