Add --ci option to publish script (#20727)
When running in CI, the publish script will skip interactive prompts, including the prompt for a one-time password. Instead, CI will need to use an automation access token: https://docs.npmjs.com/using-private-packages-in-a-ci-cd-workflow
Andrew Clark committed
Feb 3, 2021 at 14:17 UTC
3be750eee9cda6c20fc3e69eb454215125609d37
4 files changed
+89
-42
scripts/release/publish-commands/confirm-version-and-tags.js
+4
-2
@@ -8,7 +8,7 @@ const {join} = require('path');
8
const {confirm} = require('../utils');
9
const theme = require('../theme');
10
11
-const run = async ({cwd, packages, tags}) => {
11
+const run = async ({cwd, packages, tags, ci}) => {
12
clear();
13
14
if (tags.length === 0) {
@@ -40,7 +40,9 @@ const run = async ({cwd, packages, tags}) => {
40
);
41
}
42
43
- await confirm('Do you want to proceed?');
43
+ if (!ci) {
44
+ await confirm('Do you want to proceed?');
45
+ }
46
47
clear();
48
};
scripts/release/publish-commands/parse-params.js
+7
-1
@@ -26,6 +26,12 @@ const paramDefinitions = [
26
description: 'Packages to exclude from publishing',
27
defaultValue: [],
28
},
29
+ {
30
+ name: 'ci',
31
+ type: Boolean,
32
+ description: 'Run in automated environment, without interactive prompts.',
33
+ defaultValue: false,
34
+ },
35
];
36
37
module.exports = () => {
@@ -40,7 +46,7 @@ module.exports = () => {
46
case 'untagged':
47
break;
48
default:
43
- console.error('Unknown tag: "' + params.tag + '"');
49
+ console.error('Unsupported tag: "' + tag + '"');
50
process.exit(1);
51
break;
52
}
scripts/release/publish-commands/publish-to-npm.js
+52
-20
@@ -8,7 +8,7 @@ const {join} = require('path');
8
const {confirm, execRead} = require('../utils');
9
const theme = require('../theme');
10
11
-const run = async ({cwd, dry, tags}, packageName, otp) => {
11
+const run = async ({cwd, dry, tags, ci}, packageName, otp) => {
12
const packagePath = join(cwd, 'build/node_modules', packageName);
13
const {version} = readJsonSync(join(packagePath, 'package.json'));
14
@@ -21,42 +21,74 @@ const run = async ({cwd, dry, tags}, packageName, otp) => {
21
console.log(
22
theme`{package ${packageName}} {version ${version}} has already been published.`
23
);
24
- await confirm('Is this expected?');
24
+ if (!ci) {
25
+ await confirm('Is this expected?');
26
+ }
27
} else {
28
console.log(theme`{spinnerSuccess ✓} Publishing {package ${packageName}}`);
29
30
// Publish the package and tag it.
31
if (!dry) {
30
- await exec(`npm publish --tag=${tags[0]} --otp=${otp}`, {
31
- cwd: packagePath,
32
- });
32
+ if (!ci) {
33
+ await exec(`npm publish --tag=${tags[0]} --otp=${otp}`, {
34
+ cwd: packagePath,
35
+ });
36
+ console.log(theme.command(` cd ${packagePath}`));
37
+ console.log(
38
+ theme.command(` npm publish --tag=${tags[0]} --otp=${otp}`)
39
+ );
40
+ } else {
41
+ await exec(`npm publish --tag=${tags[0]}`, {
42
+ cwd: packagePath,
43
+ });
44
+ console.log(theme.command(` cd ${packagePath}`));
45
+ console.log(theme.command(` npm publish --tag=${tags[0]}`));
46
+ }
47
}
34
- console.log(theme.command(` cd ${packagePath}`));
35
- console.log(theme.command(` npm publish --tag=${tags[0]} --otp=${otp}`));
48
49
for (let j = 1; j < tags.length; j++) {
50
if (!dry) {
39
- await exec(
40
- `npm dist-tag add ${packageName}@${version} ${tags[j]} --otp=${otp}`,
41
- {cwd: packagePath}
42
- );
51
+ if (!ci) {
52
+ await exec(
53
+ `npm dist-tag add ${packageName}@${version} ${tags[j]} --otp=${otp}`,
54
+ {cwd: packagePath}
55
+ );
56
+ console.log(
57
+ theme.command(
58
+ ` npm dist-tag add ${packageName}@${version} ${tags[j]} --otp=${otp}`
59
+ )
60
+ );
61
+ } else {
62
+ await exec(`npm dist-tag add ${packageName}@${version} ${tags[j]}`, {
63
+ cwd: packagePath,
64
+ });
65
+ console.log(
66
+ theme.command(
67
+ ` npm dist-tag add ${packageName}@${version} ${tags[j]}`
68
+ )
69
+ );
70
+ }
71
}
44
- console.log(
45
- theme.command(
46
- ` npm dist-tag add ${packageName}@${version} ${tags[j]} --otp=${otp}`
47
- )
48
- );
72
}
73
74
if (tags.includes('untagged')) {
75
// npm doesn't let us publish without a tag at all,
76
// so for one-off publishes we clean it up ourselves.
77
if (!dry) {
55
- await exec(`npm dist-tag rm ${packageName} untagged --otp=${otp}`);
78
+ if (!ci) {
79
+ await exec(`npm dist-tag rm ${packageName} untagged --otp=${otp}`);
80
+ console.log(
81
+ theme.command(
82
+ ` npm dist-tag rm ${packageName} untagged --otp=${otp}`
83
+ )
84
+ );
85
+ } else {
86
+ await exec(`npm dist-tag rm ${packageName} untagged`);
87
+ console.log(
88
+ theme.command(` npm dist-tag rm ${packageName} untagged`)
89
+ );
90
+ }
91
}
57
- console.log(
58
- theme.command(` npm dist-tag rm ${packageName} untagged --otp=${otp}`)
59
- );
92
}
93
}
94
};
scripts/release/publish.js
+26
-19
@@ -50,28 +50,35 @@ const run = async () => {
50
await validateSkipPackages(params);
51
await checkNPMPermissions(params);
52
53
- clear();
54
- let otp = await promptForOTP(params);
53
const packageNames = params.packages;
56
- for (let i = 0; i < packageNames.length; ) {
57
- const packageName = packageNames[i];
58
- try {
59
- await publishToNPM(params, packageName, otp);
60
- i++;
61
- } catch (error) {
62
- console.error(error.message);
63
- console.log();
64
- console.log(
65
- theme.error`Publish failed. Enter a fresh otp code to retry.`
66
- );
67
- otp = await promptForOTP(params);
68
- // Try publishing package again
69
- continue;
54
+
55
+ if (params.ci) {
56
+ for (let i = 0; i < packageNames.length; i++) {
57
+ const packageName = packageNames[i];
58
+ await publishToNPM(params, packageName, null);
59
}
60
+ } else {
61
+ clear();
62
+ let otp = await promptForOTP(params);
63
+ for (let i = 0; i < packageNames.length; ) {
64
+ const packageName = packageNames[i];
65
+ try {
66
+ await publishToNPM(params, packageName, otp);
67
+ i++;
68
+ } catch (error) {
69
+ console.error(error.message);
70
+ console.log();
71
+ console.log(
72
+ theme.error`Publish failed. Enter a fresh otp code to retry.`
73
+ );
74
+ otp = await promptForOTP(params);
75
+ // Try publishing package again
76
+ continue;
77
+ }
78
+ }
79
+ await updateStableVersionNumbers(params);
80
+ await printFollowUpInstructions(params);
81
}
72
-
73
- await updateStableVersionNumbers(params);
74
- await printFollowUpInstructions(params);
82
} catch (error) {
83
handleError(error);
84
}