@samitouri / QOS-React-2 / commits / 3be750eee9

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 }