Skip to content

Commit 385f895

Browse files
committed
[LOCAL] backport from 0.66 the logic to deploy new releases
1 parent a6a183a commit 385f895

3 files changed

Lines changed: 153 additions & 90 deletions

File tree

scripts/bump-oss-version.js

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
const fs = require('fs');
2020
const {cat, echo, exec, exit, sed} = require('shelljs');
2121
const yargs = require('yargs');
22+
const {parseVersion} = require('./version-utils');
2223

2324
let argv = yargs
2425
.option('r', {
@@ -29,17 +30,27 @@ let argv = yargs
2930
alias: 'nightly',
3031
type: 'boolean',
3132
default: false,
33+
})
34+
.option('v', {
35+
alias: 'to-version',
36+
type: 'string',
37+
})
38+
.option('l', {
39+
alias: 'latest',
40+
type: 'boolean',
41+
default: false,
3242
}).argv;
3343

3444
const nightlyBuild = argv.nightly;
45+
const version = argv.toVersion;
3546

36-
let version, branch;
37-
if (nightlyBuild) {
38-
const currentCommit = exec('git rev-parse HEAD', {
39-
silent: true,
40-
}).stdout.trim();
41-
version = `0.0.0-${currentCommit.slice(0, 9)}`;
42-
} else {
47+
if (!version) {
48+
echo('You must specify a version using -v');
49+
exit(1);
50+
}
51+
52+
let branch;
53+
if (!nightlyBuild) {
4354
// Check we are in release branch, e.g. 0.33-stable
4455
branch = exec('git symbolic-ref --short HEAD', {
4556
silent: true,
@@ -55,24 +66,24 @@ if (nightlyBuild) {
5566

5667
// - check that argument version matches branch
5768
// e.g. 0.33.1 or 0.33.0-rc4
58-
version = argv._[0];
59-
if (!version || version.indexOf(versionMajor) !== 0) {
69+
if (version.indexOf(versionMajor) !== 0) {
6070
echo(
61-
`You must pass a tag like 0.${versionMajor}.[X]-rc[Y] to bump a version`,
71+
`You must specify a version tag like 0.${versionMajor}.[X]-rc[Y] to bump a version`,
6272
);
6373
exit(1);
6474
}
6575
}
6676

67-
// Generate version files to detect mismatches between JS and native.
68-
let match = version.match(/^(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/);
69-
if (!match) {
70-
echo(
71-
`You must pass a correctly formatted version; couldn't parse ${version}`,
72-
);
77+
let major,
78+
minor,
79+
patch,
80+
prerelease = -1;
81+
try {
82+
({major, minor, patch, prerelease} = parseVersion(version));
83+
} catch (e) {
84+
echo(e.message);
7385
exit(1);
7486
}
75-
let [, major, minor, patch, prerelease] = match;
7687

7788
fs.writeFileSync(
7889
'ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java',
@@ -149,17 +160,26 @@ if (
149160
exec(`node scripts/set-rn-template-version.js ${version}`);
150161

151162
// Verify that files changed, we just do a git diff and check how many times version is added across files
163+
const filesToValidate = [
164+
'package.json',
165+
'ReactAndroid/gradle.properties',
166+
'template/package.json',
167+
];
152168
let numberOfChangedLinesWithNewVersion = exec(
153-
`git diff -U0 | grep '^[+]' | grep -c ${version} `,
169+
`git diff -U0 ${filesToValidate.join(
170+
' ',
171+
)}| grep '^[+]' | grep -c ${version} `,
154172
{silent: true},
155173
).stdout.trim();
156174

157175
// Release builds should commit the version bumps, and create tags.
158176
// Nightly builds do not need to do that.
159177
if (!nightlyBuild) {
160-
if (+numberOfChangedLinesWithNewVersion !== 3) {
178+
if (+numberOfChangedLinesWithNewVersion !== filesToValidate.length) {
161179
echo(
162-
'Failed to update all the files. package.json and gradle.properties must have versions in them',
180+
`Failed to update all the files: [${filesToValidate.join(
181+
', ',
182+
)}] must have versions in them`,
163183
);
164184
echo('Fix the issue, revert and try again');
165185
exec('git diff');
@@ -186,8 +206,9 @@ if (!nightlyBuild) {
186206
let remote = argv.remote;
187207
exec(`git push ${remote} v${version}`);
188208

189-
// Tag latest if doing stable release
190-
if (version.indexOf('rc') === -1) {
209+
// Tag latest if doing stable release.
210+
// This will also tag npm release as `latest`
211+
if (prerelease == null && argv.latest) {
191212
exec('git tag -d latest');
192213
exec(`git push ${remote} :latest`);
193214
exec('git tag latest');

scripts/publish-npm.js

Lines changed: 81 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,29 @@
1010
'use strict';
1111

1212
/**
13-
* This script publishes a new version of react-native to NPM.
13+
* This script prepares a release version of react-native and may publish to NPM.
1414
* It is supposed to run in CI environment, not on a developer's machine.
1515
*
1616
* To make it easier for developers it uses some logic to identify with which
1717
* version to publish the package.
1818
*
1919
* To cut a branch (and release RC):
2020
* - Developer: `git checkout -b 0.XY-stable`
21-
* - Developer: `./scripts/bump-oss-version.js v0.XY.0-rc.0`
21+
* - Developer: `./scripts/bump-oss-version.js -v v0.XY.0-rc.0`
2222
* - CI: test and deploy to npm (run this script) with version `0.XY.0-rc.0`
2323
* with tag "next"
2424
*
2525
* To update RC release:
2626
* - Developer: `git checkout 0.XY-stable`
2727
* - Developer: cherry-pick whatever changes needed
28-
* - Developer: `./scripts/bump-oss-version.js v0.XY.0-rc.1`
28+
* - Developer: `./scripts/bump-oss-version.js -v v0.XY.0-rc.1`
2929
* - CI: test and deploy to npm (run this script) with version `0.XY.0-rc.1`
3030
* with tag "next"
3131
*
3232
* To publish a release:
3333
* - Developer: `git checkout 0.XY-stable`
3434
* - Developer: cherry-pick whatever changes needed
35-
* - Developer: `./scripts/bump-oss-version.js v0.XY.0`
35+
* - Developer: `./scripts/bump-oss-version.js -v v0.XY.0`
3636
* - CI: test and deploy to npm (run this script) with version `0.XY.0`
3737
* and no tag ("latest" is implied by npm)
3838
*
@@ -49,81 +49,79 @@
4949
* If tag v0.XY.Z is present on the commit then publish to npm with version 0.XY.Z and no tag (npm will consider it latest)
5050
*/
5151

52-
/*eslint-disable no-undef */
53-
require('shelljs/global');
52+
const {exec, echo, exit, test} = require('shelljs');
5453
const yargs = require('yargs');
54+
const {parseVersion} = require('./version-utils');
5555

56-
let argv = yargs.option('n', {
57-
alias: 'nightly',
58-
type: 'boolean',
59-
default: false,
60-
}).argv;
61-
62-
const nightlyBuild = argv.nightly;
6356
const buildTag = process.env.CIRCLE_TAG;
6457
const otp = process.env.NPM_CONFIG_OTP;
6558

66-
let branchVersion = 0;
67-
if (nightlyBuild) {
68-
branchVersion = 0;
69-
} else {
70-
if (!buildTag) {
71-
echo('Error: We publish only from git tags');
72-
exit(1);
73-
}
74-
75-
let match = buildTag.match(/^v(\d+\.\d+)\.\d+(?:-.+)?$/);
76-
if (!match) {
77-
echo('Error: We publish only from release version git tags');
78-
exit(1);
79-
}
80-
[, branchVersion] = match;
81-
}
82-
// 0.33
59+
const argv = yargs
60+
.option('n', {
61+
alias: 'nightly',
62+
type: 'boolean',
63+
default: false,
64+
})
65+
.option('d', {
66+
alias: 'dry-run',
67+
type: 'boolean',
68+
default: false,
69+
}).argv;
70+
const nightlyBuild = argv.nightly;
71+
const dryRunBuild = argv.dryRun;
8372

8473
// 34c034298dc9cad5a4553964a5a324450fda0385
85-
const currentCommit = exec('git rev-parse HEAD', {silent: true}).stdout.trim();
86-
// [34c034298dc9cad5a4553964a5a324450fda0385, refs/heads/0.33-stable, refs/tags/latest, refs/tags/v0.33.1, refs/tags/v0.34.1-rc]
87-
const tagsWithVersion = exec(`git ls-remote origin | grep ${currentCommit}`, {
74+
const currentCommit = exec('git rev-parse HEAD', {
8875
silent: true,
89-
})
90-
.stdout.split(/\s/)
91-
// ['refs/tags/v0.33.0', 'refs/tags/v0.33.0-rc', 'refs/tags/v0.33.0-rc1', 'refs/tags/v0.33.0-rc2', 'refs/tags/v0.34.0']
92-
.filter(
93-
version =>
94-
!!version && version.indexOf(`refs/tags/v${branchVersion}`) === 0,
95-
)
96-
// ['refs/tags/v0.33.0', 'refs/tags/v0.33.0-rc', 'refs/tags/v0.33.0-rc1', 'refs/tags/v0.33.0-rc2']
97-
.filter(version => version.indexOf(branchVersion) !== -1)
98-
// ['v0.33.0', 'v0.33.0-rc', 'v0.33.0-rc1', 'v0.33.0-rc2']
99-
.map(version => version.slice('refs/tags/'.length));
100-
101-
if (!nightlyBuild && tagsWithVersion.length === 0) {
102-
echo(
103-
'Error: Cannot find version tag in current commit. To deploy to NPM you must add tag v0.XY.Z[-rc] to your commit',
104-
);
76+
}).stdout.trim();
77+
const shortCommit = currentCommit.slice(0, 9);
78+
79+
const rawVersion =
80+
// 0.0.0 triggers issues with cocoapods for codegen when building template project.
81+
dryRunBuild
82+
? '1000.0.0'
83+
: // For nightly we continue to use 0.0.0 for clarity for npm
84+
nightlyBuild
85+
? '0.0.0'
86+
: // For pre-release and stable releases, we use the git tag of the version we're releasing (set in bump-oss-version)
87+
buildTag;
88+
89+
let version,
90+
major,
91+
minor,
92+
prerelease = null;
93+
try {
94+
({version, major, minor, prerelease} = parseVersion(rawVersion));
95+
} catch (e) {
96+
echo(e.message);
10597
exit(1);
10698
}
10799
let releaseVersion;
100+
if (dryRunBuild) {
101+
releaseVersion = `${version}-${shortCommit}`;
102+
} else if (nightlyBuild) {
103+
// 2021-09-28T05:38:40.669Z -> 20210928-0538
104+
const dateIdentifier = new Date()
105+
.toISOString()
106+
.slice(0, -8)
107+
.replace(/[-:]/g, '')
108+
.replace(/[T]/g, '-');
109+
releaseVersion = `${version}-${dateIdentifier}-${shortCommit}`;
110+
} else {
111+
releaseVersion = version;
112+
}
108113

109-
if (nightlyBuild) {
110-
releaseVersion = `0.0.0-${currentCommit.slice(0, 9)}`;
111-
112-
// Bump version number in various files (package.json, gradle.properties etc)
114+
// Bump version number in various files (package.json, gradle.properties etc)
115+
// For stable, pre-release releases, we manually call bump-oss-version on release branch
116+
if (nightlyBuild || dryRunBuild) {
113117
if (
114-
exec(`node scripts/bump-oss-version.js --nightly ${releaseVersion}`).code
118+
exec(
119+
`node scripts/bump-oss-version.js --nightly --to-version ${releaseVersion}`,
120+
).code
115121
) {
116122
echo('Failed to bump version number');
117123
exit(1);
118124
}
119-
} else if (tagsWithVersion[0].indexOf('-rc') === -1) {
120-
// if first tag on this commit is non -rc then we are making a stable release
121-
// '0.33.0'
122-
releaseVersion = tagsWithVersion[0].slice(1);
123-
} else {
124-
// otherwise pick last -rc tag alphabetically
125-
// 0.33.0-rc2
126-
releaseVersion = tagsWithVersion[tagsWithVersion.length - 1].slice(1);
127125
}
128126

129127
const buildAndroid = (rebuildOnError) => {
@@ -175,12 +173,29 @@ artifacts.forEach(name => {
175173
}
176174
});
177175

178-
// if version contains -rc, tag as prerelease
176+
if (dryRunBuild) {
177+
echo('Skipping `npm publish` because --dry-run is set.');
178+
exit(0);
179+
}
180+
181+
// Running to see if this commit has been git tagged as `latest`
182+
const latestCommit = exec("git rev-list -n 1 'latest'", {
183+
silent: true,
184+
}).stdout.replace('\n', '');
185+
const isLatest = currentCommit === latestCommit;
186+
187+
const releaseBranch = `${major}.${minor}-stable`;
188+
189+
// Set the right tag for nightly and prerelease builds
190+
// If a release is not git-tagged as `latest` we use `releaseBranch` to prevent
191+
// npm from overriding the current `latest` version tag, which it will do if no tag is set.
179192
const tagFlag = nightlyBuild
180193
? '--tag nightly'
181-
: releaseVersion.indexOf('-rc') === -1
182-
? ''
183-
: '--tag next';
194+
: prerelease != null
195+
? '--tag next'
196+
: isLatest
197+
? '--tag latest'
198+
: `--tag ${releaseBranch}`;
184199

185200
// use otp from envvars if available
186201
const otpFlag = otp ? `--otp ${otp}` : '';
@@ -192,5 +207,3 @@ if (exec(`npm publish ${tagFlag} ${otpFlag}`).code) {
192207
echo(`Published to npm ${releaseVersion}`);
193208
exit(0);
194209
}
195-
196-
/*eslint-enable no-undef */

scripts/version-utils.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @format
8+
*/
9+
10+
function parseVersion(versionStr) {
11+
const match = versionStr.match(/^v?((\d+)\.(\d+)\.(\d+)(?:-(.+))?)$/);
12+
if (!match) {
13+
throw new Error(
14+
`You must pass a correctly formatted version; couldn't parse ${versionStr}`,
15+
);
16+
}
17+
const [, version, major, minor, patch, prerelease] = match;
18+
return {
19+
version,
20+
major,
21+
minor,
22+
patch,
23+
prerelease,
24+
};
25+
}
26+
27+
module.exports = {
28+
parseVersion,
29+
};

0 commit comments

Comments
 (0)