Next/experimental release versions include commit date (#21700)
Change format of @next and @experimental release versions from <number>-<sha> to <number>-<sha>-<date> to make them more human readable. This format still preserves the ability for us to easily map a version number to the changes it contains, while also being able to more easily know at a glance how recent a release is.
Brian Vaughn committed
Jun 23, 2021 at 13:50 UTC
355591add41c0f6dad738fdb1b6603e0786b7b4e
7 files changed
+62
-27
ReactVersions.js
+2
-2
@@ -14,9 +14,9 @@
14
//
15
// 18.0.0-alpha-a1c2d3e4
16
//
17
-// The @experimental channel doesn't include a version, only a sha, e.g.:
17
+// The @experimental channel doesn't include a version, only a date and a sha, e.g.:
18
//
19
-// 0.0.0-experimental-a1c2d3e4
19
+// 0.0.0-experimental-241c4467e-20200129
20
21
const ReactVersion = '18.0.0';
22
scripts/release/README.md
+3
-3
@@ -87,7 +87,7 @@ Stable releases should always be created from the "next" channel. This encourage
87
To prepare a stable release, choose a "next" version and run the [`prepare-release-from-npm`](#prepare-release-from-npm) script <sup>1</sup>:
88
89
```sh
90
-scripts/release/prepare-release-from-npm.js --version=0.0.0-241c4467e
90
+scripts/release/prepare-release-from-npm.js --version=0.0.0-241c4467e-20200129
91
```
92
93
This script will prompt you to select stable version numbers for each of the packages. It will update the package JSON versions (and dependencies) based on the numbers you select.
@@ -165,9 +165,9 @@ This script prompts for new (stable) release versions for each public package an
165
"Next" releases have already been tested but it is still a good idea to **manually test and verify a release** before publishing to ensure that e.g. version numbers are correct. Upon completion, this script prints manual testing instructions.
166
167
#### Example usage
168
-To promote the "next" release `0.0.0-241c4467e` (aka commit [241c4467e](https://github.com/facebook/react/commit/241c4467e)) to stable:
168
+To promote the "next" release `0.0.0-241c4467e-20200129` (aka commit [241c4467e](https://github.com/facebook/react/commit/241c4467e)) to stable:
169
```sh
170
-scripts/release/prepare-release-from-npm.js --version=0.0.0-241c4467e
170
+scripts/release/prepare-release-from-npm.js --version=0.0.0-241c4467e-20200129
171
```
172
173
## `publish`
scripts/release/prepare-release-from-npm-commands/parse-params.js
+2
-1
@@ -29,7 +29,8 @@ const paramDefinitions = [
29
{
30
name: 'version',
31
type: String,
32
- description: 'Version of published "next" release (e.g. 0.0.0-ddaf2b07c)',
32
+ description:
33
+ 'Version of published "next" release (e.g. 0.0.0-0e526bcec-20210202)',
34
},
35
];
36
scripts/release/prepare-release-from-npm-commands/update-stable-version-numbers.js
+2
-2
@@ -47,7 +47,7 @@ const run = async ({cwd, packages, version}, versionsMap) => {
47
// (e.g. scheduler@^0.11.0 becomes scheduler@^0.12.0 when we release scheduler 0.12.0).
48
// Otherwise we leave the constraint alone (e.g. react@^16.0.0 doesn't change between releases).
49
// Note that in both cases, we must update the target package JSON,
50
- // since "next" releases are all locked to the version (e.g. 0.0.0-ddaf2b07c).
50
+ // since "next" releases are all locked to the version (e.g. 0.0.0-0e526bcec-20210202).
51
if (
52
sourceDependencyVersion ===
53
sourceDependencyConstraint.replace(/^[\^\~]/, '')
@@ -69,7 +69,7 @@ const run = async ({cwd, packages, version}, versionsMap) => {
69
// Update all package JSON versions and their dependencies/peerDependencies.
70
// This must be done in a way that respects semver constraints (e.g. 16.7.0, ^16.7.0, ^16.0.0).
71
// To do this, we use the dependencies defined in the source package JSONs,
72
- // because the "next" dependencies have already been flattened to an exact match (e.g. 0.0.0-ddaf2b07c).
72
+ // because the "next" dependencies have already been flattened to an exact match (e.g. 0.0.0-0e526bcec-20210202).
73
for (let i = 0; i < packages.length; i++) {
74
const packageName = packages[i];
75
const packageJSONPath = join(nodeModulesPath, packageName, 'package.json');
scripts/release/snapshot-test.js
+4
-2
@@ -6,7 +6,7 @@ const {exec, spawn} = require('child-process-promise');
6
const {join} = require('path');
7
const {readFileSync} = require('fs');
8
const theme = require('./theme');
9
-const {logPromise, printDiff} = require('./utils');
9
+const {getDateStringForCommit, logPromise, printDiff} = require('./utils');
10
11
const cwd = join(__dirname, '..', '..');
12
@@ -37,6 +37,8 @@ const run = async () => {
37
);
38
await promise;
39
40
+ const dateString = await getDateStringForCommit(COMMIT);
41
+
42
// Upgrade the above build top a known React version.
43
// Note that using the --local flag skips NPM checkout.
44
// This isn't totally necessary but is useful if we want to test an unpublished "next" build.
@@ -44,7 +46,7 @@ const run = async () => {
46
'node',
47
[
48
'./scripts/release/prepare-release-from-npm.js',
47
- `--version=0.0.0-${COMMIT}`,
49
+ `--version=0.0.0-${COMMIT}-${dateString}`,
50
'--local',
51
],
52
defaultOptions
scripts/release/utils.js
+24
-9
@@ -49,9 +49,9 @@ const execRead = async (command, options) => {
49
};
50
51
const extractCommitFromVersionNumber = version => {
52
- // Support stable version format e.g. "0.0.0-0e526bcec"
53
- // and experimental version format e.g. "0.0.0-experimental-0e526bcec"
54
- const match = version.match(/0\.0\.0\-([a-z]+\-){0,1}(.+)/);
52
+ // Support stable version format e.g. "0.0.0-0e526bcec-20210202"
53
+ // and experimental version format e.g. "0.0.0-experimental-0e526bcec-20210202"
54
+ const match = version.match(/0\.0\.0\-([a-z]+\-){0,1}([^-]+).+/);
55
if (match === null) {
56
throw Error(`Could not extra commit from version "${version}"`);
57
}
@@ -74,9 +74,10 @@ const getBuildInfo = async () => {
74
});
75
const commit = await execRead('git show -s --format=%h', {cwd});
76
const checksum = await getChecksumForCurrentRevision(cwd);
77
+ const dateString = await getDateStringForCommit(commit);
78
const version = isExperimental
78
- ? `0.0.0-experimental-${commit}`
79
- : `0.0.0-${commit}`;
79
+ ? `0.0.0-experimental-${commit}-${dateString}`
80
+ : `0.0.0-${commit}-${dateString}`;
81
82
// Only available for Circle CI builds.
83
// https://circleci.com/docs/2.0/env-vars/
@@ -88,8 +89,8 @@ const getBuildInfo = async () => {
89
join(cwd, 'packages', 'react', 'package.json')
90
);
91
const reactVersion = isExperimental
91
- ? `${packageJSON.version}-experimental-${commit}`
92
- : `${packageJSON.version}-${commit}`;
92
+ ? `${packageJSON.version}-experimental-${commit}-${dateString}`
93
+ : `${packageJSON.version}-${commit}-${dateString}`;
94
95
return {branch, buildNumber, checksum, commit, reactVersion, version};
96
};
@@ -103,6 +104,19 @@ const getChecksumForCurrentRevision = async cwd => {
104
return hashedPackages.hash.slice(0, 7);
105
};
106
107
+const getDateStringForCommit = async commit => {
108
+ let dateString = await execRead(
109
+ `git show -s --format=%cd --date=format:%Y%m%d ${commit}`
110
+ );
111
+
112
+ // On CI environment, this string is wrapped with quotes '...'s
113
+ if (dateString.startsWith("'")) {
114
+ dateString = dateString.substr(1, 8);
115
+ }
116
+
117
+ return dateString;
118
+};
119
+
120
const getCommitFromCurrentBuild = async () => {
121
const cwd = join(__dirname, '..', '..');
122
@@ -194,10 +208,10 @@ const splitCommaParams = array => {
208
// This method is used by both local Node release scripts and Circle CI bash scripts.
209
// It updates version numbers in package JSONs (both the version field and dependencies),
210
// As well as the embedded renderer version in "packages/shared/ReactVersion".
197
-// Canaries version numbers use the format of 0.0.0-<sha> to be easily recognized (e.g. 0.0.0-01974a867).
211
+// Canaries version numbers use the format of 0.0.0-<sha>-<date> to be easily recognized (e.g. 0.0.0-01974a867-20200129).
212
// A separate "React version" is used for the embedded renderer version to support DevTools,
213
// since it needs to distinguish between different version ranges of React.
200
-// It is based on the version of React in the local package.json (e.g. 16.12.0-01974a867).
214
+// It is based on the version of React in the local package.json (e.g. 16.12.0-01974a867-20200129).
215
// Both numbers will be replaced if the "next" release is promoted to a stable release.
216
const updateVersionsForNext = async (cwd, reactVersion, version) => {
217
const isExperimental = reactVersion.includes('experimental');
@@ -258,6 +272,7 @@ module.exports = {
272
getBuildInfo,
273
getChecksumForCurrentRevision,
274
getCommitFromCurrentBuild,
275
+ getDateStringForCommit,
276
getPublicPackages,
277
handleError,
278
logPromise,
scripts/rollup/build-all-release-channels.js
+25
-8
@@ -22,6 +22,16 @@ const sha = (
22
spawnSync('git', ['show', '-s', '--format=%h']).stdout + ''
23
).trim();
24
25
+let dateString = (
26
+ spawnSync('git', ['show', '-s', '--format=%cd', '--date=format:%Y%m%d', sha])
27
+ .stdout + ''
28
+).trim();
29
+
30
+// On CI environment, this string is wrapped with quotes '...'s
31
+if (dateString.startsWith("'")) {
32
+ dateString = dateString.substr(1, 8);
33
+}
34
+
35
if (process.env.CIRCLE_NODE_TOTAL) {
36
// In CI, we use multiple concurrent processes. Allocate half the processes to
37
// build the stable channel, and the other half for experimental. Override
@@ -32,14 +42,16 @@ if (process.env.CIRCLE_NODE_TOTAL) {
42
if (index < halfTotal) {
43
const nodeTotal = halfTotal;
44
const nodeIndex = index;
35
- updateTheReactVersionThatDevToolsReads(ReactVersion + '-' + sha);
45
+ updateTheReactVersionThatDevToolsReads(
46
+ ReactVersion + '-' + sha + '-' + dateString
47
+ );
48
buildForChannel('stable', nodeTotal, nodeIndex);
49
processStable('./build');
50
} else {
51
const nodeTotal = total - halfTotal;
52
const nodeIndex = index - halfTotal;
53
updateTheReactVersionThatDevToolsReads(
42
- ReactVersion + '-experimental-' + sha
54
+ ReactVersion + '-experimental-' + sha + '-' + dateString
55
);
56
buildForChannel('experimental', nodeTotal, nodeIndex);
57
processExperimental('./build');
@@ -51,12 +63,16 @@ if (process.env.CIRCLE_NODE_TOTAL) {
63
} else {
64
// Running locally, no concurrency. Move each channel's build artifacts into
65
// a temporary directory so that they don't conflict.
54
- updateTheReactVersionThatDevToolsReads(ReactVersion + '-' + sha);
66
+ updateTheReactVersionThatDevToolsReads(
67
+ ReactVersion + '-' + sha + '-' + dateString
68
+ );
69
buildForChannel('stable', '', '');
70
const stableDir = tmp.dirSync().name;
71
crossDeviceRenameSync('./build', stableDir);
72
processStable(stableDir);
59
- updateTheReactVersionThatDevToolsReads(ReactVersion + '-experimental-' + sha);
73
+ updateTheReactVersionThatDevToolsReads(
74
+ ReactVersion + '-experimental-' + sha + '-' + dateString
75
+ );
76
buildForChannel('experimental', '', '');
77
const experimentalDir = tmp.dirSync().name;
78
crossDeviceRenameSync('./build', experimentalDir);
@@ -88,13 +104,13 @@ function buildForChannel(channel, nodeTotal, nodeIndex) {
104
105
function processStable(buildDir) {
106
if (fs.existsSync(buildDir + '/node_modules')) {
91
- const defaultVersionIfNotFound = '0.0.0' + '-' + sha;
107
+ const defaultVersionIfNotFound = '0.0.0' + '-' + sha + '-' + dateString;
108
const versionsMap = new Map();
109
for (const moduleName in stablePackages) {
110
const version = stablePackages[moduleName];
111
versionsMap.set(
112
moduleName,
97
- version + '-' + nextChannelLabel + '-' + sha,
113
+ version + '-' + nextChannelLabel + '-' + sha + '-' + dateString,
114
defaultVersionIfNotFound
115
);
116
}
@@ -143,7 +159,8 @@ function processStable(buildDir) {
159
160
function processExperimental(buildDir, version) {
161
if (fs.existsSync(buildDir + '/node_modules')) {
146
- const defaultVersionIfNotFound = '0.0.0' + '-' + 'experimental' + '-' + sha;
162
+ const defaultVersionIfNotFound =
163
+ '0.0.0' + '-' + 'experimental' + '-' + sha + '-' + dateString;
164
const versionsMap = new Map();
165
for (const moduleName in stablePackages) {
166
versionsMap.set(moduleName, defaultVersionIfNotFound);
@@ -195,7 +212,7 @@ function crossDeviceRenameSync(source, destination) {
212
213
/*
214
* Grabs the built packages in ${tmp_build_dir}/node_modules and updates the
198
- * `version` key in their package.json to 0.0.0-${commitHash} for the commit
215
+ * `version` key in their package.json to 0.0.0-${date}-${commitHash} for the commit
216
* you're building. Also updates the dependencies and peerDependencies
217
* to match this version for all of the 'React' packages
218
* (packages available in this repo).