From 62274ad40f66b7d42e0acaf5fd8b031d57e773cc Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Fri, 15 Feb 2019 07:59:01 -0800 Subject: [PATCH 1/3] Improve release script process documentation --- scripts/release/README.md | 50 +++++++++++++++++-- .../get-latest-canary-version.js | 15 ++++++ .../prepare-stable-commands/parse-params.js | 25 ---------- scripts/release/prepare-stable.js | 5 ++ 4 files changed, 67 insertions(+), 28 deletions(-) create mode 100644 scripts/release/prepare-stable-commands/get-latest-canary-version.js diff --git a/scripts/release/README.md b/scripts/release/README.md index 00b80e7873dc..f8f2cc7fa540 100644 --- a/scripts/release/README.md +++ b/scripts/release/README.md @@ -4,15 +4,59 @@ The release process consists of several phases, each one represented by one of t A typical release goes like this: 1. When a commit is pushed to the React repo, [Circle CI](https://circleci.com/gh/facebook/react/) will build all release bundles and run unit tests against both the source code and the built bundles. -2. Next the release is published as a canary using the [`prepare-canary`](#prepare-canary) and [`publish`](#publish) scripts. (Currently this process is manual but might be automated in the future using [GitHub "actions"](https://github.com/features/actions).) -3. Finally, a canary releases can be promoted to stable using the [`prepare-stable`](#prepare-stable) and [`publish`](#publish) scripts. (This process is always manual.) +2. Next the release is [**published as a canary**](#publishing-a-canary) using the [`prepare-canary`](#prepare-canary) and [`publish`](#publish) scripts. (Currently this process is manual but might be automated in the future using [GitHub "actions"](https://github.com/features/actions).) +3. Finally, a canary releases can be [**promoted to stable**](#publishing-a-stable-release) using the [`prepare-stable`](#prepare-stable) and [`publish`](#publish) scripts. (This process is always manual.) -One or more release scripts are used for each of the above phases. Learn more about these scripts below: +The high level process of creating releases is [documented below](#process). Individual scripts are documented as well: * [`create-canary`](#create-canary) * [`prepare-canary`](#prepare-canary) * [`prepare-stable`](#prepare-stable) * [`publish`](#publish) +# Process + +## Publishing a Canary + +Canaries are meant to be lightweight and published often. In most cases, canaries can be published using artifacts built by Circle CI. + +To prepare a canary for a particular commit: +1. Choose a commit from [the commit log](https://github.com/facebook/react/commits/master). +2. Click the "“✓" icon and click the Circle CI "Details" link. +4. Copy the build ID from the URL (e.g. the build ID for [circleci.com/gh/facebook/react/13471](https://circleci.com/gh/facebook/react/13471) is **13471**). +5. Run the [`prepare-canary`](#prepare-canary) script with the build ID you found 1: +```sh +scripts/release/prepare-canary.js --build=13471 +``` + +Once the canary has been checked out and tested locally, you're ready to publish it: +```sh +scripts/release/publish.js --tags canary +``` + +1: You can omit the `build` param if you just want to release the latest commit as a canary. + +## Publishing a Stable Release + +Stable releases should always be created from a previously-released canary. This encourages better testing of the actual release artifacts and reduces the chance of unintended changes accidentally being included in a stable release. + +To prepare a stable release, choose a canary version and run the [`prepare-stable`](#prepare-stable) script 1: + +```sh +scripts/release/prepare-stable.js --version=0.0.0-5bf84d292 +``` + +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. + +Once this step is complete, you're ready to publish the release: + +```sh +scripts/release/publish.js --tags next latest +``` + +1: You can omit the `version` param if you just want to promote the latest canary to stable. + +# Scripts + ## `create-canary` Creates a canary build from the current (local) Git revision. diff --git a/scripts/release/prepare-stable-commands/get-latest-canary-version.js b/scripts/release/prepare-stable-commands/get-latest-canary-version.js new file mode 100644 index 000000000000..2972bd877ec2 --- /dev/null +++ b/scripts/release/prepare-stable-commands/get-latest-canary-version.js @@ -0,0 +1,15 @@ +#!/usr/bin/env node + +'use strict'; + +const {execRead, logPromise} = require('../utils'); + +const run = async () => { + const version = await execRead('npm info react@canary version'); + + return version; +}; + +module.exports = async params => { + return logPromise(run(params), 'Determining latest canary release version'); +}; diff --git a/scripts/release/prepare-stable-commands/parse-params.js b/scripts/release/prepare-stable-commands/parse-params.js index 4046d130cb96..c7d12c001eba 100644 --- a/scripts/release/prepare-stable-commands/parse-params.js +++ b/scripts/release/prepare-stable-commands/parse-params.js @@ -3,7 +3,6 @@ 'use strict'; const commandLineArgs = require('command-line-args'); -const commandLineUsage = require('command-line-usage'); const paramDefinitions = [ { @@ -29,29 +28,5 @@ const paramDefinitions = [ module.exports = () => { const params = commandLineArgs(paramDefinitions); - if (!params.version) { - const usage = commandLineUsage([ - { - content: 'Prepare a published canary release to be promoted to stable.', - }, - { - header: 'Options', - optionList: paramDefinitions, - }, - { - header: 'Examples', - content: [ - { - desc: 'Example:', - example: - '$ ./prepare-stable.js [bold]{--version=}[underline]{0.0.0-ddaf2b07c}', - }, - ], - }, - ]); - console.log(usage); - process.exit(1); - } - return params; }; diff --git a/scripts/release/prepare-stable.js b/scripts/release/prepare-stable.js index 4e290574b17d..f0b13403b19b 100755 --- a/scripts/release/prepare-stable.js +++ b/scripts/release/prepare-stable.js @@ -7,6 +7,7 @@ const {getPublicPackages, handleError} = require('./utils'); const checkOutPackages = require('./prepare-stable-commands/check-out-packages'); const confirmStableVersionNumbers = require('./prepare-stable-commands/confirm-stable-version-numbers'); +const getLatestCanaryVersion = require('./prepare-stable-commands/get-latest-canary-version'); const guessStableVersionNumbers = require('./prepare-stable-commands/guess-stable-version-numbers'); const parseParams = require('./prepare-stable-commands/parse-params'); const printPrereleaseSummary = require('./shared-commands/print-prerelease-summary'); @@ -25,6 +26,10 @@ const run = async () => { // The developer running the release later confirms or overrides each version. const versionsMap = new Map(); + if (!params.version) { + params.version = await getLatestCanaryVersion(); + } + await checkOutPackages(params); await guessStableVersionNumbers(params, versionsMap); await confirmStableVersionNumbers(params, versionsMap); From cc1cf9530dc3400862e53514c97523a72cb285ee Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Fri, 15 Feb 2019 08:06:38 -0800 Subject: [PATCH 2/3] Improved pre-publish instructions/message based on feedback --- scripts/release/create-canary.js | 2 +- scripts/release/prepare-canary.js | 2 +- scripts/release/prepare-stable.js | 2 +- .../print-prerelease-summary.js | 34 ++++++++++++------- 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/scripts/release/create-canary.js b/scripts/release/create-canary.js index dc00b3a7b328..663c8101dc23 100755 --- a/scripts/release/create-canary.js +++ b/scripts/release/create-canary.js @@ -48,7 +48,7 @@ const run = async () => { await addBuildInfoJSON(params); await buildArtifacts(params); await npmPackAndUnpack(params); - await printPrereleaseSummary(params); + await printPrereleaseSummary(params, false); } catch (error) { handleError(error); } diff --git a/scripts/release/prepare-canary.js b/scripts/release/prepare-canary.js index ca5dbe849156..37be7b382953 100755 --- a/scripts/release/prepare-canary.js +++ b/scripts/release/prepare-canary.js @@ -31,7 +31,7 @@ const run = async () => { await testTracingFixture(params); } - await printPrereleaseSummary(params); + await printPrereleaseSummary(params, false); } catch (error) { handleError(error); } diff --git a/scripts/release/prepare-stable.js b/scripts/release/prepare-stable.js index f0b13403b19b..04d507fdadfe 100755 --- a/scripts/release/prepare-stable.js +++ b/scripts/release/prepare-stable.js @@ -40,7 +40,7 @@ const run = async () => { await testTracingFixture(params); } - await printPrereleaseSummary(params); + await printPrereleaseSummary(params, true); } catch (error) { handleError(error); } diff --git a/scripts/release/shared-commands/print-prerelease-summary.js b/scripts/release/shared-commands/print-prerelease-summary.js index d981bd28fe44..b6e810c22053 100644 --- a/scripts/release/shared-commands/print-prerelease-summary.js +++ b/scripts/release/shared-commands/print-prerelease-summary.js @@ -6,7 +6,7 @@ const clear = require('clear'); const {join, relative} = require('path'); const theme = require('../theme'); -module.exports = ({cwd}) => { +module.exports = ({cwd}, isStableRelease) => { const publishPath = relative( process.env.PWD, join(__dirname, '../publish.js') @@ -14,18 +14,28 @@ module.exports = ({cwd}) => { clear(); - console.log( - theme` - {caution A release candidate has been prepared but you're not done yet!} + let message; + if (isStableRelease) { + message = theme` + {caution A stable release candidate has been prepared!} - You can review the contents of this release in {path ./build/node_modules/} + You can review the contents of this release in {path ./build/node_modules/} - {header Before publishing, please smoke test the packages!} + {header Before publishing, consider testing this release locally with create-react-app!} - Once you have finished smoke testing, you can publish this release by running: - {path ${publishPath}} - ` - .replace(/\n +/g, '\n') - .trim() - ); + You can publish this release by running: + {path ${publishPath}} + `; + } else { + message = theme` + {caution A canary release candidate has been prepared!} + + You can review the contents of this release in {path ./build/node_modules/} + + You can publish this release by running: + {path ${publishPath}} + `; + } + + console.log(message.replace(/\n +/g, '\n').trim()); }; From 00ade1fcae6780f95566b6bad2ffa999f03d417d Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Fri, 15 Feb 2019 08:10:50 -0800 Subject: [PATCH 3/3] Added reminder to attach build artifacts to GitHub release --- .../release/publish-commands/print-follow-up-instructions.js | 5 ++++- scripts/release/shared-commands/print-prerelease-summary.js | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/scripts/release/publish-commands/print-follow-up-instructions.js b/scripts/release/publish-commands/print-follow-up-instructions.js index d7e26cfb7000..74f696d76fff 100644 --- a/scripts/release/publish-commands/print-follow-up-instructions.js +++ b/scripts/release/publish-commands/print-follow-up-instructions.js @@ -78,7 +78,10 @@ const run = async ({cwd, packages, tags}) => { console.log(theme.command` git push origin --tags`); console.log(); - console.log(theme.header`Lastly, please fill in the release on GitHub:`); + console.log( + theme.header`Lastly, please fill in the release on GitHub. ` + + theme`Don't forget to attach build artifacts from {path build/node_modules/}` + ); console.log( theme.link`https://github.com/facebook/react/releases/tag/v%s`, version diff --git a/scripts/release/shared-commands/print-prerelease-summary.js b/scripts/release/shared-commands/print-prerelease-summary.js index b6e810c22053..2a226dc71f49 100644 --- a/scripts/release/shared-commands/print-prerelease-summary.js +++ b/scripts/release/shared-commands/print-prerelease-summary.js @@ -19,7 +19,7 @@ module.exports = ({cwd}, isStableRelease) => { message = theme` {caution A stable release candidate has been prepared!} - You can review the contents of this release in {path ./build/node_modules/} + You can review the contents of this release in {path build/node_modules/} {header Before publishing, consider testing this release locally with create-react-app!} @@ -30,7 +30,7 @@ module.exports = ({cwd}, isStableRelease) => { message = theme` {caution A canary release candidate has been prepared!} - You can review the contents of this release in {path ./build/node_modules/} + You can review the contents of this release in {path build/node_modules/} You can publish this release by running: {path ${publishPath}}