Overhauled release scripts and docs (#18569)
* Overhauled release scripts and docs
This commit is contained in:
parent
af1b039bdd
commit
8e13f099ab
|
@ -4,16 +4,17 @@ 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. The release is then [**published to the `next` channel**](#publishing-next) using the [`prepare-next`](#prepare-next) 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 "next" release can be [**promoted to stable**](#publishing-a-stable-release)<sup>1</sup> using the [`prepare-stable`](#prepare-stable) and [`publish`](#publish) scripts. (This process is always manual.)
|
||||
2. The release is then [**published to the `next` channel**](#publishing-release) using the [`prepare-release-from-ci`](#prepare-release-from-ci) and [`publish`](#publish) scripts. (Currently this process is manual but might be automated in the future using [GitHub "actions"](https://github.com/features/actions).)
|
||||
1. The release may also be [**published to the `experimental` channel**](#publishing-an-experimental-release) using the the same scripts (but different build artifacts).
|
||||
3. Finally, a "next" release can be [**promoted to stable**](#publishing-a-stable-release)<sup>1</sup> using the [`prepare-release-from-npm`](#prepare-release-from-npm) and [`publish`](#publish) scripts. (This process is always manual.)
|
||||
|
||||
The high level process of creating releases is [documented below](#process). Individual scripts are documented as well:
|
||||
* [`create-next`](#create-next)
|
||||
* [`prepare-next`](#prepare-next)
|
||||
* [`prepare-stable`](#prepare-stable)
|
||||
* [`publish`](#publish)
|
||||
* [`build-release-locally`](#build-release-locally): Build a release locally from the checked out source code.
|
||||
* [`prepare-release-from-ci`](#prepare-release-from-ci): Download a pre-built release from CI.
|
||||
* [`prepare-release-from-npm`](#prepare-release-from-npm): Prepare an NPM "next" release to be published as a "stable" release.
|
||||
* [`publish`](#publish): Publish the downloaded (or prepared) release to NPM.
|
||||
|
||||
<sup>Note that [**creating a patch release**](#creating-a-patch-release) has a slightly different process than a major/minor release.</sup>
|
||||
<sup>1. [**Creating a patch release**](#creating-a-patch-release) has a slightly different process than a major/minor release.</sup>
|
||||
|
||||
# Process
|
||||
|
||||
|
@ -26,13 +27,13 @@ If this is your first time running the release scripts, go to the `scripts/relea
|
|||
To prepare a build 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.
|
||||
3. Select the `build` job (**not** the `build_experimental` job; see the next section).
|
||||
3. Select the `process_artifacts ` job (**not** the `process_artifacts_experimental`job; see the next section)
|
||||
* If it's still pending, you'll need to wait for it to finish. <sup>1</sup>
|
||||
4. Copy the build ID from the URL
|
||||
* e.g. the build ID for commit [241c4467](https://github.com/facebook/react/commit/241c4467eef7c2a8858c96d5dfe4e8ef84c47bad) is [**80592**](https://circleci.com/gh/facebook/react/80592)
|
||||
5. Run the [`prepare-next`](#prepare-next) script with the build ID <sup>2</sup> you found:
|
||||
* e.g. the build ID for commit [e5d06e34b](https://github.com/facebook/react/commit/e5d06e34b) is [**124756**](https://circleci.com/gh/facebook/react/124756)
|
||||
5. Run the [`prepare-release-from-ci`](#prepare-release-from-ci) script with the build ID <sup>2</sup> you found:
|
||||
```sh
|
||||
scripts/release/prepare-next.js --build=80592
|
||||
scripts/release/prepare-release-from-ci.js --build=124756
|
||||
```
|
||||
|
||||
Once the build has been checked out and tested locally, you're ready to publish it:
|
||||
|
@ -49,9 +50,14 @@ If the OTP code expires while publishing, re-run this command and answer "y" to
|
|||
|
||||
Experimental releases are special because they have additional features turned on.
|
||||
|
||||
The steps for publishing an experimental release are almost the same as for publishing a "next" release, except in step 3 you should choose the `build_experimental` job instead of `build` <sup>1</sup> For example, the experimental build ID for commit [241c4467](https://github.com/facebook/react/commit/241c4467eef7c2a8858c96d5dfe4e8ef84c47bad) is [**80590**](https://circleci.com/gh/facebook/react/80590):
|
||||
The steps for publishing an experimental release are almost the same as for publishing a "next" release, except in step 3 you should choose the `process_artifacts_experimental ` job (instead of `process_artifacts`) <sup>1</sup>
|
||||
|
||||
When publishing an experimental release, use the `experimental` tag:
|
||||
For example, the experimental build ID for commit [e5d06e34b](https://github.com/facebook/react/commit/e5d06e34b) is [**124763**](https://circleci.com/gh/facebook/react/124763):
|
||||
```sh
|
||||
scripts/release/prepare-release-from-ci.js --build=124763
|
||||
```
|
||||
|
||||
Once the build has been checked out and tested locally, you're ready to publish it. When publishing an experimental release, use the `experimental` tag:
|
||||
|
||||
```sh
|
||||
scripts/release/publish.js --tags experimental
|
||||
|
@ -65,10 +71,10 @@ If the OTP code expires while publishing, re-run this command and answer "y" to
|
|||
|
||||
Stable releases should always be created from the "next" channel. 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 "next" version and run the [`prepare-stable`](#prepare-stable) script <sup>1</sup>:
|
||||
To prepare a stable release, choose a "next" version and run the [`prepare-release-from-npm`](#prepare-release-from-npm) script <sup>1</sup>:
|
||||
|
||||
```sh
|
||||
scripts/release/prepare-stable.js --version=0.0.0-241c4467e
|
||||
scripts/release/prepare-release-from-npm.js --version=0.0.0-241c4467e
|
||||
```
|
||||
|
||||
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.
|
||||
|
@ -107,13 +113,13 @@ Once you have cherry picked all of the commits you want to include in the releas
|
|||
git push origin 16.8.3
|
||||
```
|
||||
|
||||
Once CI is complete, follow the regular [**next**](#publishing-next) and [**promote to stable**](#publishing-a-stable-release) processes.
|
||||
Once CI is complete, follow the regular [**next**](#publishing-release) and [**promote to stable**](#publishing-a-stable-release) processes.
|
||||
|
||||
<sup>1: The `build-info.json` artifact can also be used to identify the appropriate commit (e.g. [unpkg.com/react@16.8.3/build-info.json](https://unpkg.com/react@16.8.3/build-info.json) shows us that react version 16.8.3 was created from commit [`29b7b775f`](https://github.com/facebook/react/commit/29b7b775f)).</sup>
|
||||
|
||||
# Scripts
|
||||
|
||||
## `create-next`
|
||||
## `build-release-locally`
|
||||
Creates a "next" build from the current (local) Git revision.
|
||||
|
||||
**This script is an escape hatch.** It allows a release to be created without pushing a commit to be verified by Circle CI. **It does not run any automated unit tests.** Testing is solely the responsibility of the release engineer.
|
||||
|
@ -123,21 +129,21 @@ Note that this script git-archives the React repo (at the current revision) to a
|
|||
#### Example usage
|
||||
To create a build from the current branch and revision:
|
||||
```sh
|
||||
scripts/release/create-next.js
|
||||
scripts/release/build-release-locally.js
|
||||
```
|
||||
|
||||
## `prepare-next`
|
||||
Downloads build artifacts from Circle CI in preparation to be published to NPM as a "next" release.
|
||||
## `prepare-release-from-ci`
|
||||
Downloads build artifacts from Circle CI in preparation to be published to NPM as either a "next" or "experimental" release.
|
||||
|
||||
All artifacts built by Circle CI have already been unit-tested (both source and bundles) but these candidates should **always be manually tested** before being published. Upon completion, this script prints manual testing instructions.
|
||||
|
||||
#### Example usage
|
||||
To prepare the artifacts created by [Circle CI build 80592](https://circleci.com/gh/facebook/react/80592#artifacts/containers/0) you would run:
|
||||
To prepare the artifacts created by [Circle CI build 124756](https://circleci.com/gh/facebook/react/124756#artifacts/containers/0) you would run:
|
||||
```sh
|
||||
scripts/release/prepare-next.js --build=80592
|
||||
scripts/release/prepare-release-from-ci.js --build=124756
|
||||
```
|
||||
|
||||
## `prepare-stable`
|
||||
## `prepare-release-from-npm`
|
||||
Checks out a "next" release from NPM and prepares it to be published as a stable release.
|
||||
|
||||
This script prompts for new (stable) release versions for each public package and updates the package contents (both `package.json` and inline version numbers) to match. It also updates inter-package dependencies to account for the new versions.
|
||||
|
@ -147,7 +153,7 @@ This script prompts for new (stable) release versions for each public package an
|
|||
#### Example usage
|
||||
To promote the "next" release `0.0.0-241c4467e` (aka commit [241c4467e](https://github.com/facebook/react/commit/241c4467e)) to stable:
|
||||
```sh
|
||||
scripts/release/prepare-stable.js --version=0.0.0-241c4467e
|
||||
scripts/release/prepare-release-from-npm.js --version=0.0.0-241c4467e
|
||||
```
|
||||
|
||||
## `publish`
|
||||
|
|
|
@ -13,13 +13,13 @@ const {getBuildInfo, handleError} = require('./utils');
|
|||
// It doesn't run all of the tests that the CI environment runs.
|
||||
// You're expected to run those manually before publishing a release.
|
||||
|
||||
const addBuildInfoJSON = require('./create-next-commands/add-build-info-json');
|
||||
const buildArtifacts = require('./create-next-commands/build-artifacts');
|
||||
const confirmAutomatedTesting = require('./create-next-commands/confirm-automated-testing');
|
||||
const copyRepoToTempDirectory = require('./create-next-commands/copy-repo-to-temp-directory');
|
||||
const npmPackAndUnpack = require('./create-next-commands/npm-pack-and-unpack');
|
||||
const addBuildInfoJSON = require('./build-release-locally-commands/add-build-info-json');
|
||||
const buildArtifacts = require('./build-release-locally-commands/build-artifacts');
|
||||
const confirmAutomatedTesting = require('./build-release-locally-commands/confirm-automated-testing');
|
||||
const copyRepoToTempDirectory = require('./build-release-locally-commands/copy-repo-to-temp-directory');
|
||||
const npmPackAndUnpack = require('./build-release-locally-commands/npm-pack-and-unpack');
|
||||
const printPrereleaseSummary = require('./shared-commands/print-prerelease-summary');
|
||||
const updateVersionNumbers = require('./create-next-commands/update-version-numbers');
|
||||
const updateVersionNumbers = require('./build-release-locally-commands/update-version-numbers');
|
||||
|
||||
const run = async () => {
|
||||
try {
|
|
@ -0,0 +1,57 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
'use strict';
|
||||
|
||||
const {tmpdir} = require('os');
|
||||
const {join} = require('path');
|
||||
const {getBuildInfo, handleError} = require('./utils');
|
||||
|
||||
// This script is an escape hatch!
|
||||
// It exists for special case manual builds.
|
||||
// The typical suggested release process is to create a "next" build from a CI artifact.
|
||||
// This build script is optimized for speed and simplicity.
|
||||
// It doesn't run all of the tests that the CI environment runs.
|
||||
// You're expected to run those manually before publishing a release.
|
||||
|
||||
const addBuildInfoJSON = require('./build-release-locally-commands/add-build-info-json');
|
||||
const buildArtifacts = require('./build-release-locally-commands/build-artifacts');
|
||||
const confirmAutomatedTesting = require('./build-release-locally-commands/confirm-automated-testing');
|
||||
const copyRepoToTempDirectory = require('./build-release-locally-commands/copy-repo-to-temp-directory');
|
||||
const npmPackAndUnpack = require('./build-release-locally-commands/npm-pack-and-unpack');
|
||||
const printPrereleaseSummary = require('./shared-commands/print-prerelease-summary');
|
||||
const updateVersionNumbers = require('./build-release-locally-commands/update-version-numbers');
|
||||
|
||||
const run = async () => {
|
||||
try {
|
||||
const cwd = join(__dirname, '..', '..');
|
||||
const {
|
||||
branch,
|
||||
checksum,
|
||||
commit,
|
||||
reactVersion,
|
||||
version,
|
||||
} = await getBuildInfo();
|
||||
const tempDirectory = join(tmpdir(), `react-${commit}`);
|
||||
const params = {
|
||||
branch,
|
||||
checksum,
|
||||
commit,
|
||||
cwd,
|
||||
reactVersion,
|
||||
tempDirectory,
|
||||
version,
|
||||
};
|
||||
|
||||
await confirmAutomatedTesting(params);
|
||||
await copyRepoToTempDirectory(params);
|
||||
await updateVersionNumbers(params);
|
||||
await addBuildInfoJSON(params);
|
||||
await buildArtifacts(params);
|
||||
await npmPackAndUnpack(params);
|
||||
await printPrereleaseSummary(params, false);
|
||||
} catch (error) {
|
||||
handleError(error);
|
||||
}
|
||||
};
|
||||
|
||||
run();
|
|
@ -7,7 +7,7 @@
|
|||
// It exists to share code between the Node release scripts and CI bash scripts.
|
||||
|
||||
// IMPORTANT:
|
||||
// Changes below should be mirrored in ./create-next-commands/add-build-info-json.js
|
||||
// Changes below should be mirrored in ./build-release-locally-commands/add-build-info-json.js
|
||||
|
||||
const {exec} = require('child_process');
|
||||
const {existsSync} = require('fs');
|
||||
|
|
|
@ -5,15 +5,15 @@
|
|||
const {join} = require('path');
|
||||
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 getLatestNextVersion = require('./prepare-stable-commands/get-latest-next-version');
|
||||
const guessStableVersionNumbers = require('./prepare-stable-commands/guess-stable-version-numbers');
|
||||
const parseParams = require('./prepare-stable-commands/parse-params');
|
||||
const checkOutPackages = require('./prepare-release-from-npm-commands/check-out-packages');
|
||||
const confirmStableVersionNumbers = require('./prepare-release-from-npm-commands/confirm-stable-version-numbers');
|
||||
const getLatestNextVersion = require('./prepare-release-from-npm-commands/get-latest-next-version');
|
||||
const guessStableVersionNumbers = require('./prepare-release-from-npm-commands/guess-stable-version-numbers');
|
||||
const parseParams = require('./prepare-release-from-npm-commands/parse-params');
|
||||
const printPrereleaseSummary = require('./shared-commands/print-prerelease-summary');
|
||||
const testPackagingFixture = require('./shared-commands/test-packaging-fixture');
|
||||
const testTracingFixture = require('./shared-commands/test-tracing-fixture');
|
||||
const updateStableVersionNumbers = require('./prepare-stable-commands/update-stable-version-numbers');
|
||||
const updateStableVersionNumbers = require('./prepare-release-from-npm-commands/update-stable-version-numbers');
|
||||
const theme = require('./theme');
|
||||
|
||||
const run = async () => {
|
|
@ -25,7 +25,10 @@ const run = async () => {
|
|||
// https://circleci.com/gh/facebook/react/12707
|
||||
let promise = spawn(
|
||||
'node',
|
||||
['./scripts/release/prepare-next.js', `--build=${CIRCLE_CI_BUILD}`],
|
||||
[
|
||||
'./scripts/release/prepare-release-from-ci.js',
|
||||
`--build=${CIRCLE_CI_BUILD}`,
|
||||
],
|
||||
defaultOptions
|
||||
);
|
||||
logPromise(
|
||||
|
@ -40,7 +43,7 @@ const run = async () => {
|
|||
promise = spawn(
|
||||
'node',
|
||||
[
|
||||
'./scripts/release/prepare-stable.js',
|
||||
'./scripts/release/prepare-release-from-npm.js',
|
||||
`--version=0.0.0-${COMMIT}`,
|
||||
'--local',
|
||||
],
|
||||
|
|
Loading…
Reference in New Issue