@samitouri / QOS-React / commits / fad0842fd4

Release scripts documentation (#14863)

* Improve release script process documentation * Improved pre-publish instructions/message based on feedback * Added reminder to attach build artifacts to GitHub release

Brian Vaughn committed Feb 15, 2019 at 10:00 UTC fad0842fd45e4082feb8036922c77529431628ca
8 files changed +96 -44
scripts/release/README.md
+47 -3
@@ -4,15 +4,59 @@ The release process consists of several phases, each one represented by one of t
4
5 A typical release goes like this:
6 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.
7 -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).)
8 -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.)
7 +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).)
8 +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.)
9
10 -One or more release scripts are used for each of the above phases. Learn more about these scripts below:
10 +The high level process of creating releases is [documented below](#process). Individual scripts are documented as well:
11 * [`create-canary`](#create-canary)
12 * [`prepare-canary`](#prepare-canary)
13 * [`prepare-stable`](#prepare-stable)
14 * [`publish`](#publish)
15
16 +# Process
17 +
18 +## Publishing a Canary
19 +
20 +Canaries are meant to be lightweight and published often. In most cases, canaries can be published using artifacts built by Circle CI.
21 +
22 +To prepare a canary for a particular commit:
23 +1. Choose a commit from [the commit log](https://github.com/facebook/react/commits/master).
24 +2. Click the "“✓" icon and click the Circle CI "Details" link.
25 +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**).
26 +5. Run the [`prepare-canary`](#prepare-canary) script with the build ID you found <sup>1</sup>:
27 +```sh
28 +scripts/release/prepare-canary.js --build=13471
29 +```
30 +
31 +Once the canary has been checked out and tested locally, you're ready to publish it:
32 +```sh
33 +scripts/release/publish.js --tags canary
34 +```
35 +
36 +<sup>1: You can omit the `build` param if you just want to release the latest commit as a canary.</sup>
37 +
38 +## Publishing a Stable Release
39 +
40 +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.
41 +
42 +To prepare a stable release, choose a canary version and run the [`prepare-stable`](#prepare-stable) script <sup>1</sup>:
43 +
44 +```sh
45 +scripts/release/prepare-stable.js --version=0.0.0-5bf84d292
46 +```
47 +
48 +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.
49 +
50 +Once this step is complete, you're ready to publish the release:
51 +
52 +```sh
53 +scripts/release/publish.js --tags next latest
54 +```
55 +
56 +<sup>1: You can omit the `version` param if you just want to promote the latest canary to stable.</sup>
57 +
58 +# Scripts
59 +
60 ## `create-canary`
61 Creates a canary build from the current (local) Git revision.
62
scripts/release/create-canary.js
+1 -1
@@ -48,7 +48,7 @@ const run = async () => {
48 await addBuildInfoJSON(params);
49 await buildArtifacts(params);
50 await npmPackAndUnpack(params);
51 - await printPrereleaseSummary(params);
51 + await printPrereleaseSummary(params, false);
52 } catch (error) {
53 handleError(error);
54 }
scripts/release/prepare-canary.js
+1 -1
@@ -31,7 +31,7 @@ const run = async () => {
31 await testTracingFixture(params);
32 }
33
34 - await printPrereleaseSummary(params);
34 + await printPrereleaseSummary(params, false);
35 } catch (error) {
36 handleError(error);
37 }
scripts/release/prepare-stable-commands/get-latest-canary-version.js new
+15
@@ -0,0 +1,15 @@
1 +#!/usr/bin/env node
2 +
3 +'use strict';
4 +
5 +const {execRead, logPromise} = require('../utils');
6 +
7 +const run = async () => {
8 + const version = await execRead('npm info react@canary version');
9 +
10 + return version;
11 +};
12 +
13 +module.exports = async params => {
14 + return logPromise(run(params), 'Determining latest canary release version');
15 +};
scripts/release/prepare-stable-commands/parse-params.js
-25
@@ -3,7 +3,6 @@
3 'use strict';
4
5 const commandLineArgs = require('command-line-args');
6 -const commandLineUsage = require('command-line-usage');
6
7 const paramDefinitions = [
8 {
@@ -29,29 +28,5 @@ const paramDefinitions = [
28 module.exports = () => {
29 const params = commandLineArgs(paramDefinitions);
30
32 - if (!params.version) {
33 - const usage = commandLineUsage([
34 - {
35 - content: 'Prepare a published canary release to be promoted to stable.',
36 - },
37 - {
38 - header: 'Options',
39 - optionList: paramDefinitions,
40 - },
41 - {
42 - header: 'Examples',
43 - content: [
44 - {
45 - desc: 'Example:',
46 - example:
47 - '$ ./prepare-stable.js [bold]{--version=}[underline]{0.0.0-ddaf2b07c}',
48 - },
49 - ],
50 - },
51 - ]);
52 - console.log(usage);
53 - process.exit(1);
54 - }
55 -
31 return params;
32 };
scripts/release/prepare-stable.js
+6 -1
@@ -7,6 +7,7 @@ const {getPublicPackages, handleError} = require('./utils');
7
8 const checkOutPackages = require('./prepare-stable-commands/check-out-packages');
9 const confirmStableVersionNumbers = require('./prepare-stable-commands/confirm-stable-version-numbers');
10 +const getLatestCanaryVersion = require('./prepare-stable-commands/get-latest-canary-version');
11 const guessStableVersionNumbers = require('./prepare-stable-commands/guess-stable-version-numbers');
12 const parseParams = require('./prepare-stable-commands/parse-params');
13 const printPrereleaseSummary = require('./shared-commands/print-prerelease-summary');
@@ -25,6 +26,10 @@ const run = async () => {
26 // The developer running the release later confirms or overrides each version.
27 const versionsMap = new Map();
28
29 + if (!params.version) {
30 + params.version = await getLatestCanaryVersion();
31 + }
32 +
33 await checkOutPackages(params);
34 await guessStableVersionNumbers(params, versionsMap);
35 await confirmStableVersionNumbers(params, versionsMap);
@@ -35,7 +40,7 @@ const run = async () => {
40 await testTracingFixture(params);
41 }
42
38 - await printPrereleaseSummary(params);
43 + await printPrereleaseSummary(params, true);
44 } catch (error) {
45 handleError(error);
46 }
scripts/release/publish-commands/print-follow-up-instructions.js
+4 -1
@@ -78,7 +78,10 @@ const run = async ({cwd, packages, tags}) => {
78 console.log(theme.command` git push origin --tags`);
79
80 console.log();
81 - console.log(theme.header`Lastly, please fill in the release on GitHub:`);
81 + console.log(
82 + theme.header`Lastly, please fill in the release on GitHub. ` +
83 + theme`Don't forget to attach build artifacts from {path build/node_modules/}`
84 + );
85 console.log(
86 theme.link`https://github.com/facebook/react/releases/tag/v%s`,
87 version
scripts/release/shared-commands/print-prerelease-summary.js
+22 -12
@@ -6,7 +6,7 @@ const clear = require('clear');
6 const {join, relative} = require('path');
7 const theme = require('../theme');
8
9 -module.exports = ({cwd}) => {
9 +module.exports = ({cwd}, isStableRelease) => {
10 const publishPath = relative(
11 process.env.PWD,
12 join(__dirname, '../publish.js')
@@ -14,18 +14,28 @@ module.exports = ({cwd}) => {
14
15 clear();
16
17 - console.log(
18 - theme`
19 - {caution A release candidate has been prepared but you're not done yet!}
17 + let message;
18 + if (isStableRelease) {
19 + message = theme`
20 + {caution A stable release candidate has been prepared!}
21
21 - You can review the contents of this release in {path ./build/node_modules/}
22 + You can review the contents of this release in {path build/node_modules/}
23
23 - {header Before publishing, please smoke test the packages!}
24 + {header Before publishing, consider testing this release locally with create-react-app!}
25
25 - Once you have finished smoke testing, you can publish this release by running:
26 - {path ${publishPath}}
27 - `
28 - .replace(/\n +/g, '\n')
29 - .trim()
30 - );
26 + You can publish this release by running:
27 + {path ${publishPath}}
28 + `;
29 + } else {
30 + message = theme`
31 + {caution A canary release candidate has been prepared!}
32 +
33 + You can review the contents of this release in {path build/node_modules/}
34 +
35 + You can publish this release by running:
36 + {path ${publishPath}}
37 + `;
38 + }
39 +
40 + console.log(message.replace(/\n +/g, '\n').trim());
41 };