@samitouri / QOS-React / commits / 355591add4

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).