Skip to content

Commit 355591a

Browse files
author
Brian Vaughn
authored
Next/experimental release versions include commit date (facebook#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.
1 parent d7dce57 commit 355591a

File tree

7 files changed

+62
-27
lines changed

7 files changed

+62
-27
lines changed

ReactVersions.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
//
1515
// 18.0.0-alpha-a1c2d3e4
1616
//
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.:
1818
//
19-
// 0.0.0-experimental-a1c2d3e4
19+
// 0.0.0-experimental-241c4467e-20200129
2020

2121
const ReactVersion = '18.0.0';
2222

scripts/release/README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ Stable releases should always be created from the "next" channel. This encourage
8787
To prepare a stable release, choose a "next" version and run the [`prepare-release-from-npm`](#prepare-release-from-npm) script <sup>1</sup>:
8888

8989
```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
9191
```
9292

9393
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
165165
"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.
166166

167167
#### 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:
169169
```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
171171
```
172172

173173
## `publish`

scripts/release/prepare-release-from-npm-commands/parse-params.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ const paramDefinitions = [
2929
{
3030
name: 'version',
3131
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)',
3334
},
3435
];
3536

scripts/release/prepare-release-from-npm-commands/update-stable-version-numbers.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ const run = async ({cwd, packages, version}, versionsMap) => {
4747
// (e.g. scheduler@^0.11.0 becomes scheduler@^0.12.0 when we release scheduler 0.12.0).
4848
// Otherwise we leave the constraint alone (e.g. react@^16.0.0 doesn't change between releases).
4949
// 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).
5151
if (
5252
sourceDependencyVersion ===
5353
sourceDependencyConstraint.replace(/^[\^\~]/, '')
@@ -69,7 +69,7 @@ const run = async ({cwd, packages, version}, versionsMap) => {
6969
// Update all package JSON versions and their dependencies/peerDependencies.
7070
// This must be done in a way that respects semver constraints (e.g. 16.7.0, ^16.7.0, ^16.0.0).
7171
// 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).
7373
for (let i = 0; i < packages.length; i++) {
7474
const packageName = packages[i];
7575
const packageJSONPath = join(nodeModulesPath, packageName, 'package.json');

scripts/release/snapshot-test.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const {exec, spawn} = require('child-process-promise');
66
const {join} = require('path');
77
const {readFileSync} = require('fs');
88
const theme = require('./theme');
9-
const {logPromise, printDiff} = require('./utils');
9+
const {getDateStringForCommit, logPromise, printDiff} = require('./utils');
1010

1111
const cwd = join(__dirname, '..', '..');
1212

@@ -37,14 +37,16 @@ const run = async () => {
3737
);
3838
await promise;
3939

40+
const dateString = await getDateStringForCommit(COMMIT);
41+
4042
// Upgrade the above build top a known React version.
4143
// Note that using the --local flag skips NPM checkout.
4244
// This isn't totally necessary but is useful if we want to test an unpublished "next" build.
4345
promise = spawn(
4446
'node',
4547
[
4648
'./scripts/release/prepare-release-from-npm.js',
47-
`--version=0.0.0-${COMMIT}`,
49+
`--version=0.0.0-${COMMIT}-${dateString}`,
4850
'--local',
4951
],
5052
defaultOptions

scripts/release/utils.js

+24-9
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ const execRead = async (command, options) => {
4949
};
5050

5151
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}([^-]+).+/);
5555
if (match === null) {
5656
throw Error(`Could not extra commit from version "${version}"`);
5757
}
@@ -74,9 +74,10 @@ const getBuildInfo = async () => {
7474
});
7575
const commit = await execRead('git show -s --format=%h', {cwd});
7676
const checksum = await getChecksumForCurrentRevision(cwd);
77+
const dateString = await getDateStringForCommit(commit);
7778
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}`;
8081

8182
// Only available for Circle CI builds.
8283
// https://circleci.com/docs/2.0/env-vars/
@@ -88,8 +89,8 @@ const getBuildInfo = async () => {
8889
join(cwd, 'packages', 'react', 'package.json')
8990
);
9091
const reactVersion = isExperimental
91-
? `${packageJSON.version}-experimental-${commit}`
92-
: `${packageJSON.version}-${commit}`;
92+
? `${packageJSON.version}-experimental-${commit}-${dateString}`
93+
: `${packageJSON.version}-${commit}-${dateString}`;
9394

9495
return {branch, buildNumber, checksum, commit, reactVersion, version};
9596
};
@@ -103,6 +104,19 @@ const getChecksumForCurrentRevision = async cwd => {
103104
return hashedPackages.hash.slice(0, 7);
104105
};
105106

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+
106120
const getCommitFromCurrentBuild = async () => {
107121
const cwd = join(__dirname, '..', '..');
108122

@@ -194,10 +208,10 @@ const splitCommaParams = array => {
194208
// This method is used by both local Node release scripts and Circle CI bash scripts.
195209
// It updates version numbers in package JSONs (both the version field and dependencies),
196210
// 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).
198212
// A separate "React version" is used for the embedded renderer version to support DevTools,
199213
// 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).
201215
// Both numbers will be replaced if the "next" release is promoted to a stable release.
202216
const updateVersionsForNext = async (cwd, reactVersion, version) => {
203217
const isExperimental = reactVersion.includes('experimental');
@@ -258,6 +272,7 @@ module.exports = {
258272
getBuildInfo,
259273
getChecksumForCurrentRevision,
260274
getCommitFromCurrentBuild,
275+
getDateStringForCommit,
261276
getPublicPackages,
262277
handleError,
263278
logPromise,

scripts/rollup/build-all-release-channels.js

+25-8
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@ const sha = (
2222
spawnSync('git', ['show', '-s', '--format=%h']).stdout + ''
2323
).trim();
2424

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+
2535
if (process.env.CIRCLE_NODE_TOTAL) {
2636
// In CI, we use multiple concurrent processes. Allocate half the processes to
2737
// build the stable channel, and the other half for experimental. Override
@@ -32,14 +42,16 @@ if (process.env.CIRCLE_NODE_TOTAL) {
3242
if (index < halfTotal) {
3343
const nodeTotal = halfTotal;
3444
const nodeIndex = index;
35-
updateTheReactVersionThatDevToolsReads(ReactVersion + '-' + sha);
45+
updateTheReactVersionThatDevToolsReads(
46+
ReactVersion + '-' + sha + '-' + dateString
47+
);
3648
buildForChannel('stable', nodeTotal, nodeIndex);
3749
processStable('./build');
3850
} else {
3951
const nodeTotal = total - halfTotal;
4052
const nodeIndex = index - halfTotal;
4153
updateTheReactVersionThatDevToolsReads(
42-
ReactVersion + '-experimental-' + sha
54+
ReactVersion + '-experimental-' + sha + '-' + dateString
4355
);
4456
buildForChannel('experimental', nodeTotal, nodeIndex);
4557
processExperimental('./build');
@@ -51,12 +63,16 @@ if (process.env.CIRCLE_NODE_TOTAL) {
5163
} else {
5264
// Running locally, no concurrency. Move each channel's build artifacts into
5365
// a temporary directory so that they don't conflict.
54-
updateTheReactVersionThatDevToolsReads(ReactVersion + '-' + sha);
66+
updateTheReactVersionThatDevToolsReads(
67+
ReactVersion + '-' + sha + '-' + dateString
68+
);
5569
buildForChannel('stable', '', '');
5670
const stableDir = tmp.dirSync().name;
5771
crossDeviceRenameSync('./build', stableDir);
5872
processStable(stableDir);
59-
updateTheReactVersionThatDevToolsReads(ReactVersion + '-experimental-' + sha);
73+
updateTheReactVersionThatDevToolsReads(
74+
ReactVersion + '-experimental-' + sha + '-' + dateString
75+
);
6076
buildForChannel('experimental', '', '');
6177
const experimentalDir = tmp.dirSync().name;
6278
crossDeviceRenameSync('./build', experimentalDir);
@@ -88,13 +104,13 @@ function buildForChannel(channel, nodeTotal, nodeIndex) {
88104

89105
function processStable(buildDir) {
90106
if (fs.existsSync(buildDir + '/node_modules')) {
91-
const defaultVersionIfNotFound = '0.0.0' + '-' + sha;
107+
const defaultVersionIfNotFound = '0.0.0' + '-' + sha + '-' + dateString;
92108
const versionsMap = new Map();
93109
for (const moduleName in stablePackages) {
94110
const version = stablePackages[moduleName];
95111
versionsMap.set(
96112
moduleName,
97-
version + '-' + nextChannelLabel + '-' + sha,
113+
version + '-' + nextChannelLabel + '-' + sha + '-' + dateString,
98114
defaultVersionIfNotFound
99115
);
100116
}
@@ -143,7 +159,8 @@ function processStable(buildDir) {
143159

144160
function processExperimental(buildDir, version) {
145161
if (fs.existsSync(buildDir + '/node_modules')) {
146-
const defaultVersionIfNotFound = '0.0.0' + '-' + 'experimental' + '-' + sha;
162+
const defaultVersionIfNotFound =
163+
'0.0.0' + '-' + 'experimental' + '-' + sha + '-' + dateString;
147164
const versionsMap = new Map();
148165
for (const moduleName in stablePackages) {
149166
versionsMap.set(moduleName, defaultVersionIfNotFound);
@@ -195,7 +212,7 @@ function crossDeviceRenameSync(source, destination) {
195212

196213
/*
197214
* 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
199216
* you're building. Also updates the dependencies and peerDependencies
200217
* to match this version for all of the 'React' packages
201218
* (packages available in this repo).

0 commit comments

Comments
 (0)