From 68053d94076d0b17b19d196e1775d295e5eebc39 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Wed, 23 Jun 2021 12:20:57 -0400 Subject: [PATCH] Next and Experimental release versions include date Change format of @next and @experimental release versions from - to -- to make them more human readable. --- ReactVersions.js | 4 +-- scripts/release/README.md | 6 ++-- .../parse-params.js | 3 +- .../update-stable-version-numbers.js | 4 +-- scripts/release/snapshot-test.js | 6 ++-- scripts/release/utils.js | 33 ++++++++++++++----- scripts/rollup/build-all-release-channels.js | 33 ++++++++++++++----- 7 files changed, 62 insertions(+), 27 deletions(-) diff --git a/ReactVersions.js b/ReactVersions.js index bac58ffb909..95d4bd8b7c2 100644 --- a/ReactVersions.js +++ b/ReactVersions.js @@ -14,9 +14,9 @@ // // 18.0.0-alpha-a1c2d3e4 // -// The @experimental channel doesn't include a version, only a sha, e.g.: +// The @experimental channel doesn't include a version, only a date and a sha, e.g.: // -// 0.0.0-experimental-a1c2d3e4 +// 0.0.0-experimental-241c4467e-20200129 const ReactVersion = '18.0.0'; diff --git a/scripts/release/README.md b/scripts/release/README.md index befc605b9be..979062dd148 100644 --- a/scripts/release/README.md +++ b/scripts/release/README.md @@ -87,7 +87,7 @@ Stable releases should always be created from the "next" channel. This encourage To prepare a stable release, choose a "next" version and run the [`prepare-release-from-npm`](#prepare-release-from-npm) script 1: ```sh -scripts/release/prepare-release-from-npm.js --version=0.0.0-241c4467e +scripts/release/prepare-release-from-npm.js --version=0.0.0-241c4467e-20200129 ``` 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 "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. #### Example usage -To promote the "next" release `0.0.0-241c4467e` (aka commit [241c4467e](https://github.com/facebook/react/commit/241c4467e)) to stable: +To promote the "next" release `0.0.0-241c4467e-20200129` (aka commit [241c4467e](https://github.com/facebook/react/commit/241c4467e)) to stable: ```sh -scripts/release/prepare-release-from-npm.js --version=0.0.0-241c4467e +scripts/release/prepare-release-from-npm.js --version=0.0.0-241c4467e-20200129 ``` ## `publish` diff --git a/scripts/release/prepare-release-from-npm-commands/parse-params.js b/scripts/release/prepare-release-from-npm-commands/parse-params.js index 0aa85fa428a..b9aa1a4f5e7 100644 --- a/scripts/release/prepare-release-from-npm-commands/parse-params.js +++ b/scripts/release/prepare-release-from-npm-commands/parse-params.js @@ -29,7 +29,8 @@ const paramDefinitions = [ { name: 'version', type: String, - description: 'Version of published "next" release (e.g. 0.0.0-ddaf2b07c)', + description: + 'Version of published "next" release (e.g. 0.0.0-0e526bcec-20210202)', }, ]; diff --git a/scripts/release/prepare-release-from-npm-commands/update-stable-version-numbers.js b/scripts/release/prepare-release-from-npm-commands/update-stable-version-numbers.js index 2a845bebde2..16bec66b607 100644 --- a/scripts/release/prepare-release-from-npm-commands/update-stable-version-numbers.js +++ b/scripts/release/prepare-release-from-npm-commands/update-stable-version-numbers.js @@ -47,7 +47,7 @@ const run = async ({cwd, packages, version}, versionsMap) => { // (e.g. scheduler@^0.11.0 becomes scheduler@^0.12.0 when we release scheduler 0.12.0). // Otherwise we leave the constraint alone (e.g. react@^16.0.0 doesn't change between releases). // Note that in both cases, we must update the target package JSON, - // since "next" releases are all locked to the version (e.g. 0.0.0-ddaf2b07c). + // since "next" releases are all locked to the version (e.g. 0.0.0-0e526bcec-20210202). if ( sourceDependencyVersion === sourceDependencyConstraint.replace(/^[\^\~]/, '') @@ -69,7 +69,7 @@ const run = async ({cwd, packages, version}, versionsMap) => { // Update all package JSON versions and their dependencies/peerDependencies. // This must be done in a way that respects semver constraints (e.g. 16.7.0, ^16.7.0, ^16.0.0). // To do this, we use the dependencies defined in the source package JSONs, - // because the "next" dependencies have already been flattened to an exact match (e.g. 0.0.0-ddaf2b07c). + // because the "next" dependencies have already been flattened to an exact match (e.g. 0.0.0-0e526bcec-20210202). for (let i = 0; i < packages.length; i++) { const packageName = packages[i]; const packageJSONPath = join(nodeModulesPath, packageName, 'package.json'); diff --git a/scripts/release/snapshot-test.js b/scripts/release/snapshot-test.js index 9a0d4f84b89..d199b51c7b9 100755 --- a/scripts/release/snapshot-test.js +++ b/scripts/release/snapshot-test.js @@ -6,7 +6,7 @@ const {exec, spawn} = require('child-process-promise'); const {join} = require('path'); const {readFileSync} = require('fs'); const theme = require('./theme'); -const {logPromise, printDiff} = require('./utils'); +const {getDateStringForCommit, logPromise, printDiff} = require('./utils'); const cwd = join(__dirname, '..', '..'); @@ -37,6 +37,8 @@ const run = async () => { ); await promise; + const dateString = await getDateStringForCommit(COMMIT); + // Upgrade the above build top a known React version. // Note that using the --local flag skips NPM checkout. // This isn't totally necessary but is useful if we want to test an unpublished "next" build. @@ -44,7 +46,7 @@ const run = async () => { 'node', [ './scripts/release/prepare-release-from-npm.js', - `--version=0.0.0-${COMMIT}`, + `--version=0.0.0-${COMMIT}-${dateString}`, '--local', ], defaultOptions diff --git a/scripts/release/utils.js b/scripts/release/utils.js index d989a175675..ea110ba6961 100644 --- a/scripts/release/utils.js +++ b/scripts/release/utils.js @@ -49,9 +49,9 @@ const execRead = async (command, options) => { }; const extractCommitFromVersionNumber = version => { - // Support stable version format e.g. "0.0.0-0e526bcec" - // and experimental version format e.g. "0.0.0-experimental-0e526bcec" - const match = version.match(/0\.0\.0\-([a-z]+\-){0,1}(.+)/); + // Support stable version format e.g. "0.0.0-0e526bcec-20210202" + // and experimental version format e.g. "0.0.0-experimental-0e526bcec-20210202" + const match = version.match(/0\.0\.0\-([a-z]+\-){0,1}([^-]+).+/); if (match === null) { throw Error(`Could not extra commit from version "${version}"`); } @@ -74,9 +74,10 @@ const getBuildInfo = async () => { }); const commit = await execRead('git show -s --format=%h', {cwd}); const checksum = await getChecksumForCurrentRevision(cwd); + const dateString = await getDateStringForCommit(commit); const version = isExperimental - ? `0.0.0-experimental-${commit}` - : `0.0.0-${commit}`; + ? `0.0.0-experimental-${commit}-${dateString}` + : `0.0.0-${commit}-${dateString}`; // Only available for Circle CI builds. // https://circleci.com/docs/2.0/env-vars/ @@ -88,8 +89,8 @@ const getBuildInfo = async () => { join(cwd, 'packages', 'react', 'package.json') ); const reactVersion = isExperimental - ? `${packageJSON.version}-experimental-${commit}` - : `${packageJSON.version}-${commit}`; + ? `${packageJSON.version}-experimental-${commit}-${dateString}` + : `${packageJSON.version}-${commit}-${dateString}`; return {branch, buildNumber, checksum, commit, reactVersion, version}; }; @@ -103,6 +104,19 @@ const getChecksumForCurrentRevision = async cwd => { return hashedPackages.hash.slice(0, 7); }; +const getDateStringForCommit = async commit => { + let dateString = await execRead( + `git show -s --format=%cd --date=format:%Y%m%d ${commit}` + ); + + // On CI environment, this string is wrapped with quotes '...'s + if (dateString.startsWith("'")) { + dateString = dateString.substr(1, 8); + } + + return dateString; +}; + const getCommitFromCurrentBuild = async () => { const cwd = join(__dirname, '..', '..'); @@ -194,10 +208,10 @@ const splitCommaParams = array => { // This method is used by both local Node release scripts and Circle CI bash scripts. // It updates version numbers in package JSONs (both the version field and dependencies), // As well as the embedded renderer version in "packages/shared/ReactVersion". -// Canaries version numbers use the format of 0.0.0- to be easily recognized (e.g. 0.0.0-01974a867). +// Canaries version numbers use the format of 0.0.0-- to be easily recognized (e.g. 0.0.0-01974a867-20200129). // A separate "React version" is used for the embedded renderer version to support DevTools, // since it needs to distinguish between different version ranges of React. -// It is based on the version of React in the local package.json (e.g. 16.12.0-01974a867). +// It is based on the version of React in the local package.json (e.g. 16.12.0-01974a867-20200129). // Both numbers will be replaced if the "next" release is promoted to a stable release. const updateVersionsForNext = async (cwd, reactVersion, version) => { const isExperimental = reactVersion.includes('experimental'); @@ -258,6 +272,7 @@ module.exports = { getBuildInfo, getChecksumForCurrentRevision, getCommitFromCurrentBuild, + getDateStringForCommit, getPublicPackages, handleError, logPromise, diff --git a/scripts/rollup/build-all-release-channels.js b/scripts/rollup/build-all-release-channels.js index 71b6f2dd0de..575f1c9f058 100644 --- a/scripts/rollup/build-all-release-channels.js +++ b/scripts/rollup/build-all-release-channels.js @@ -22,6 +22,16 @@ const sha = ( spawnSync('git', ['show', '-s', '--format=%h']).stdout + '' ).trim(); +let dateString = ( + spawnSync('git', ['show', '-s', '--format=%cd', '--date=format:%Y%m%d', sha]) + .stdout + '' +).trim(); + +// On CI environment, this string is wrapped with quotes '...'s +if (dateString.startsWith("'")) { + dateString = dateString.substr(1, 8); +} + if (process.env.CIRCLE_NODE_TOTAL) { // In CI, we use multiple concurrent processes. Allocate half the processes to // build the stable channel, and the other half for experimental. Override @@ -32,14 +42,16 @@ if (process.env.CIRCLE_NODE_TOTAL) { if (index < halfTotal) { const nodeTotal = halfTotal; const nodeIndex = index; - updateTheReactVersionThatDevToolsReads(ReactVersion + '-' + sha); + updateTheReactVersionThatDevToolsReads( + ReactVersion + '-' + sha + '-' + dateString + ); buildForChannel('stable', nodeTotal, nodeIndex); processStable('./build'); } else { const nodeTotal = total - halfTotal; const nodeIndex = index - halfTotal; updateTheReactVersionThatDevToolsReads( - ReactVersion + '-experimental-' + sha + ReactVersion + '-experimental-' + sha + '-' + dateString ); buildForChannel('experimental', nodeTotal, nodeIndex); processExperimental('./build'); @@ -51,12 +63,16 @@ if (process.env.CIRCLE_NODE_TOTAL) { } else { // Running locally, no concurrency. Move each channel's build artifacts into // a temporary directory so that they don't conflict. - updateTheReactVersionThatDevToolsReads(ReactVersion + '-' + sha); + updateTheReactVersionThatDevToolsReads( + ReactVersion + '-' + sha + '-' + dateString + ); buildForChannel('stable', '', ''); const stableDir = tmp.dirSync().name; crossDeviceRenameSync('./build', stableDir); processStable(stableDir); - updateTheReactVersionThatDevToolsReads(ReactVersion + '-experimental-' + sha); + updateTheReactVersionThatDevToolsReads( + ReactVersion + '-experimental-' + sha + '-' + dateString + ); buildForChannel('experimental', '', ''); const experimentalDir = tmp.dirSync().name; crossDeviceRenameSync('./build', experimentalDir); @@ -88,13 +104,13 @@ function buildForChannel(channel, nodeTotal, nodeIndex) { function processStable(buildDir) { if (fs.existsSync(buildDir + '/node_modules')) { - const defaultVersionIfNotFound = '0.0.0' + '-' + sha; + const defaultVersionIfNotFound = '0.0.0' + '-' + sha + '-' + dateString; const versionsMap = new Map(); for (const moduleName in stablePackages) { const version = stablePackages[moduleName]; versionsMap.set( moduleName, - version + '-' + nextChannelLabel + '-' + sha, + version + '-' + nextChannelLabel + '-' + sha + '-' + dateString, defaultVersionIfNotFound ); } @@ -143,7 +159,8 @@ function processStable(buildDir) { function processExperimental(buildDir, version) { if (fs.existsSync(buildDir + '/node_modules')) { - const defaultVersionIfNotFound = '0.0.0' + '-' + 'experimental' + '-' + sha; + const defaultVersionIfNotFound = + '0.0.0' + '-' + 'experimental' + '-' + sha + '-' + dateString; const versionsMap = new Map(); for (const moduleName in stablePackages) { versionsMap.set(moduleName, defaultVersionIfNotFound); @@ -195,7 +212,7 @@ function crossDeviceRenameSync(source, destination) { /* * Grabs the built packages in ${tmp_build_dir}/node_modules and updates the - * `version` key in their package.json to 0.0.0-${commitHash} for the commit + * `version` key in their package.json to 0.0.0-${date}-${commitHash} for the commit * you're building. Also updates the dependencies and peerDependencies * to match this version for all of the 'React' packages * (packages available in this repo).