Release script tweaks (#11504)
* Added missing params object to execUnlessDry call * Public package names are no longer hard-coded * Added "v" prefix to git tag * Show more accurate in-progress duration * Properly bucket-bridage params * Prettier * Publish command logs stack with error
Brian Vaughn committed
Nov 9, 2017 at 16:29 UTC
ac0e670545bb85770c71154e93ef17dc6c08e8a4
11 files changed
+50
-40
scripts/release/build-commands/add-git-tag.js
+8
-5
@@ -6,15 +6,18 @@ const chalk = require('chalk');
6
const {execUnlessDry, logPromise} = require('../utils');
7
8
const run = async ({cwd, dry, version}) => {
9
- await execUnlessDry(`git tag -a ${version} -m "Tagging ${version} release"`, {
10
- cwd,
11
- dry,
12
- });
9
+ await execUnlessDry(
10
+ `git tag -a v${version} -m "Tagging ${version} release"`,
11
+ {
12
+ cwd,
13
+ dry,
14
+ }
15
+ );
16
};
17
18
module.exports = async ({cwd, dry, version}) => {
19
return logPromise(
20
run({cwd, dry, version}),
18
- `Creating git tag ${chalk.yellow.bold(version)}`
21
+ `Creating git tag ${chalk.yellow.bold(`v${version}`)}`
22
);
23
};
scripts/release/build-commands/build-artifacts.js
+1
-1
@@ -28,5 +28,5 @@ const run = async ({cwd, dry, version}) => {
28
};
29
30
module.exports = async params => {
31
- return logPromise(run(params), 'Building artifacts');
31
+ return logPromise(run(params), 'Building artifacts', true);
32
};
scripts/release/build-commands/check-npm-permissions.js
+2
-3
@@ -4,9 +4,8 @@
4
5
const chalk = require('chalk');
6
const {execRead, logPromise} = require('../utils');
7
-const {projects} = require('../config');
7
9
-module.exports = async () => {
8
+module.exports = async ({packages}) => {
9
const currentUser = await execRead('npm whoami');
10
const failedProjects = [];
11
@@ -22,7 +21,7 @@ module.exports = async () => {
21
};
22
23
await logPromise(
25
- Promise.all(projects.map(checkProject)),
24
+ Promise.all(packages.map(checkProject)),
25
`Checking ${chalk.yellow.bold(currentUser)}'s NPM permissions`
26
);
27
scripts/release/build-commands/check-package-dependencies.js
+6
-6
@@ -5,15 +5,15 @@
5
const chalk = require('chalk');
6
const {readJson} = require('fs-extra');
7
const {join} = require('path');
8
-const {dependencies, projects} = require('../config');
8
+const {dependencies} = require('../config');
9
const {logPromise} = require('../utils');
10
11
-const check = async ({cwd}) => {
11
+const check = async ({cwd, packages}) => {
12
const rootPackage = await readJson(join(cwd, 'package.json'));
13
14
const projectPackages = [];
15
- for (let i = 0; i < projects.length; i++) {
16
- const project = projects[i];
15
+ for (let i = 0; i < packages.length; i++) {
16
+ const project = packages[i];
17
projectPackages.push(
18
await readJson(join(cwd, join('packages', project), 'package.json'))
19
);
@@ -52,6 +52,6 @@ const check = async ({cwd}) => {
52
}
53
};
54
55
-module.exports = async ({cwd}) => {
56
- return logPromise(check({cwd}), 'Checking runtime dependencies');
55
+module.exports = async params => {
56
+ return logPromise(check(params), 'Checking runtime dependencies');
57
};
scripts/release/build-commands/run-automated-tests.js
+2
-1
@@ -28,6 +28,7 @@ module.exports = async ({cwd}) => {
28
);
29
await logPromise(
30
runYarnTask(cwd, 'jest', 'Jest failed'),
31
- 'Running Jest tests'
31
+ 'Running Jest tests',
32
+ true
33
);
34
};
scripts/release/build-commands/update-package-versions.js
+2
-3
@@ -8,10 +8,9 @@ const {readFileSync, writeFileSync} = require('fs');
8
const {readJson, writeJson} = require('fs-extra');
9
const {join} = require('path');
10
const semver = require('semver');
11
-const {projects} = require('../config');
11
const {execUnlessDry, logPromise} = require('../utils');
12
14
-const update = async ({cwd, dry, version}) => {
13
+const update = async ({cwd, dry, packages, version}) => {
14
try {
15
// Update root package.json
16
const packagePath = join(cwd, 'package.json');
@@ -60,7 +59,7 @@ const update = async ({cwd, dry, version}) => {
59
60
await writeJson(path, json, {spaces: 2});
61
};
63
- await Promise.all(projects.map(updateProjectPackage));
62
+ await Promise.all(packages.map(updateProjectPackage));
63
64
// Version sanity check
65
await exec('yarn version-check', {cwd});
scripts/release/build.js
+2
@@ -8,6 +8,7 @@ const {exec} = require('child_process');
8
const run = async () => {
9
const chalk = require('chalk');
10
const logUpdate = require('log-update');
11
+ const {getPublicPackages} = require('./utils');
12
13
const addGitTag = require('./build-commands/add-git-tag');
14
const buildArtifacts = require('./build-commands/build-artifacts');
@@ -27,6 +28,7 @@ const run = async () => {
28
29
try {
30
const params = parseBuildParameters();
31
+ params.packages = getPublicPackages();
32
33
await checkEnvironmentVariables(params);
34
await validateVersion(params);
scripts/release/config.js
-11
@@ -2,16 +2,6 @@
2
3
const dependencies = ['fbjs', 'object-assign', 'prop-types'];
4
5
-// TODO: enumerate all non-private package folders in packages/*?
6
-const projects = [
7
- 'react',
8
- 'react-art',
9
- 'react-call-return',
10
- 'react-dom',
11
- 'react-reconciler',
12
- 'react-test-renderer',
13
-];
14
-
5
const paramDefinitions = [
6
{
7
name: 'dry',
@@ -38,5 +28,4 @@ const paramDefinitions = [
28
module.exports = {
29
dependencies,
30
paramDefinitions,
41
- projects,
31
};
scripts/release/publish-commands/publish-to-npm.js
+4
-5
@@ -7,9 +7,8 @@ const {readJson} = require('fs-extra');
7
const {join} = require('path');
8
const semver = require('semver');
9
const {execRead, execUnlessDry, logPromise} = require('../utils');
10
-const {projects} = require('../config');
10
12
-const push = async ({cwd, dry, version}) => {
11
+const push = async ({cwd, dry, packages, version}) => {
12
const errors = [];
13
const isPrerelease = semver.prerelease(version);
14
const tag = isPrerelease ? 'next' : 'latest';
@@ -60,18 +59,18 @@ const push = async ({cwd, dry, version}) => {
59
}
60
}
61
} catch (error) {
63
- errors.push(error.message);
62
+ errors.push(error.stack);
63
}
64
};
65
67
- await Promise.all(projects.map(publishProject));
66
+ await Promise.all(packages.map(publishProject));
67
68
if (errors.length > 0) {
69
throw Error(
70
chalk`
71
Failure publishing to NPM
72
74
- {white ${errors.join('\n')}}`
73
+ {white ${errors.join('\n\n')}}`
74
);
75
}
76
};
scripts/release/publish.js
+2
@@ -4,6 +4,7 @@
4
5
const chalk = require('chalk');
6
const logUpdate = require('log-update');
7
+const {getPublicPackages} = require('./utils');
8
9
const checkBuildStatus = require('./publish-commands/check-build-status');
10
const commitChangelog = require('./publish-commands/commit-changelog');
@@ -15,6 +16,7 @@ const publishToNpm = require('./publish-commands/publish-to-npm');
16
// Follows the steps outlined in github.com/facebook/react/issues/10620
17
const run = async () => {
18
const params = parsePublishParams();
19
+ params.packages = getPublicPackages();
20
21
try {
22
await checkBuildStatus(params);
scripts/release/utils.js
+21
-5
@@ -3,7 +3,9 @@
3
const chalk = require('chalk');
4
const {dots} = require('cli-spinners');
5
const {exec} = require('child-process-promise');
6
+const {readdirSync, readFileSync} = require('fs');
7
const logUpdate = require('log-update');
8
+const {join} = require('path');
9
10
const execRead = async (command, options) => {
11
const {stdout} = await exec(command, options);
@@ -21,6 +23,17 @@ const execUnlessDry = async (command, {cwd, dry}) => {
23
}
24
};
25
26
+const getPublicPackages = () => {
27
+ const packagesRoot = join(__dirname, '..', '..', 'packages');
28
+
29
+ return readdirSync(packagesRoot).filter(dir => {
30
+ const packagePath = join(packagesRoot, dir, 'package.json');
31
+ const packageJSON = JSON.parse(readFileSync(packagePath));
32
+
33
+ return packageJSON.private !== true;
34
+ });
35
+};
36
+
37
const getUnexecutedCommands = () => {
38
if (unexecutedCommands.length > 0) {
39
return chalk`
@@ -32,17 +45,19 @@ const getUnexecutedCommands = () => {
45
}
46
};
47
35
-const logPromise = async (promise, text, completedLabel = '') => {
48
+const logPromise = async (promise, text, isLongRunningTask = false) => {
49
const {frames, interval} = dots;
50
51
let index = 0;
52
53
+ const inProgressMessage = `- this may take a few ${
54
+ isLongRunningTask ? 'minutes' : 'seconds'
55
+ }`;
56
+
57
const id = setInterval(() => {
58
index = ++index % frames.length;
59
logUpdate(
43
- `${chalk.yellow(frames[index])} ${text} ${chalk.gray(
44
- '- this may take a few seconds'
45
- )}`
60
+ `${chalk.yellow(frames[index])} ${text} ${chalk.gray(inProgressMessage)}`
61
);
62
}, interval);
63
@@ -51,7 +66,7 @@ const logPromise = async (promise, text, completedLabel = '') => {
66
67
clearInterval(id);
68
54
- logUpdate(`${chalk.green('✓')} ${text} ${chalk.gray(completedLabel)}`);
69
+ logUpdate(`${chalk.green('✓')} ${text}`);
70
logUpdate.done();
71
72
return returnValue;
@@ -65,6 +80,7 @@ const logPromise = async (promise, text, completedLabel = '') => {
80
module.exports = {
81
execRead,
82
execUnlessDry,
83
+ getPublicPackages,
84
getUnexecutedCommands,
85
logPromise,
86
};