Revert "Support untagged releases (#19507)" (#19508)
This reverts commit 58b3ee7a889b62fefb9cc64962819795bebce7b8.
Dan Abramov committed
Jul 31, 2020 at 19:57 UTC
5d271fc3b173e9b6d67d6c38af2048be0382408a
10 files changed
+84
-117
scripts/release/README.md
+7
-15
@@ -20,13 +20,9 @@ The high level process of creating releases is [documented below](#process). Ind
20
21
If this is your first time running the release scripts, go to the `scripts/release` directory and run `yarn` to install the dependencies.
22
23
-## Publishing Untagged
23
+## Publishing Without Tags
24
25
-The sections bekow include meaningful `--tag` in the instructions.
26
-
27
-However, keep in mind that **the `--tag` arguments is optional**, and you can omit it if you don't want to tag the release on npm at all. This can be useful when preparing breaking changes.
28
-
29
-Because npm requires a tag on publish, the script does it by creating a temporary tag and deleting it afterwards.
25
+The sections bekow include meaningful `--tags` in the instructions. However, keep in mind that **the `--tags` arguments is optional**, and you can omit it if you don't want to tag the release on npm at all. This can be useful when preparing breaking changes.
26
27
## Publishing Next
28
@@ -46,7 +42,7 @@ scripts/release/prepare-release-from-ci.js --build=124756
42
43
Once the build has been checked out and tested locally, you're ready to publish it:
44
```sh
49
-scripts/release/publish.js --tag next
45
+scripts/release/publish.js --tags next
46
```
47
48
If the OTP code expires while publishing, re-run this command and answer "y" to the questions about whether it was expected for already published packages.
@@ -68,7 +64,7 @@ scripts/release/prepare-release-from-ci.js --build=124763
64
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:
65
66
```sh
71
-scripts/release/publish.js --tag experimental
67
+scripts/release/publish.js --tags experimental
68
```
69
70
If the OTP code expires while publishing, re-run this command and answer "y" to the questions about whether it was expected for already published packages.
@@ -90,13 +86,11 @@ This script will prompt you to select stable version numbers for each of the pac
86
Once this step is complete, you're ready to publish the release:
87
88
```sh
93
-scripts/release/publish.js --tag latest
89
+scripts/release/publish.js --tags latest
90
```
91
92
If the OTP code expires while publishing, re-run this command and answer "y" to the questions about whether it was expected for already published packages.
93
98
-Note that publishing the `latest` tag will always update the `next` tag automatically as well so they're in sync.
99
-
94
After successfully publishing the release, follow the on-screen instructions to ensure that all of the appropriate post-release steps are executed.
95
96
<sup>1: You can omit the `version` param if you just want to promote the latest "next" candidate to stable.</sup>
@@ -176,9 +170,7 @@ Upon completion, this script provides instructions for tagging the Git commit th
170
**Specify a `--dry` flag when running this script if you want to skip the NPM-publish step.** In this event, the script will print the NPM commands but it will not actually run them.
171
172
#### Example usage
179
-To publish a release to NPM as `latest`:
173
+To publish a release to NPM as both `next` and `latest`:
174
```sh
181
-scripts/release/publish.js --tag latest
175
+scripts/release/publish.js --tags latest
176
```
183
-
184
-Note that publishing the `latest` tag will always update the `next` tag automatically as well so they're in sync.
scripts/release/publish-commands/confirm-skipped-packages.js
+1
-1
@@ -6,7 +6,7 @@ const clear = require('clear');
6
const {confirm} = require('../utils');
7
const theme = require('../theme');
8
9
-const run = async ({cwd, packages, skipPackages}) => {
9
+const run = async ({cwd, packages, skipPackages, tags}) => {
10
if (skipPackages.length === 0) {
11
return;
12
}
scripts/release/publish-commands/confirm-version-and-tags.js
renamed
+16
-8
@@ -8,16 +8,24 @@ const {join} = require('path');
8
const {confirm} = require('../utils');
9
const theme = require('../theme');
10
11
-const run = async ({cwd, packages, tag}) => {
11
+const run = async ({cwd, packages, tags}) => {
12
clear();
13
14
- // All latest releases are auto-tagged as next too by the script.
15
- let tags = tag === 'latest' ? ['latest', 'next'] : [tag];
16
- console.log(
17
- theme`{spinnerSuccess ✓} You are about the publish the following packages under the tag {tag ${tags.join(
18
- ', '
19
- )}}:`
20
- );
14
+ if (tags.length === 0) {
15
+ console.log(
16
+ theme`{spinnerSuccess ✓} You are about the publish the following packages without any tags:`
17
+ );
18
+ } else if (tags.length === 1) {
19
+ console.log(
20
+ theme`{spinnerSuccess ✓} You are about the publish the following packages under the tag {tag ${tags}}:`
21
+ );
22
+ } else {
23
+ console.log(
24
+ theme`{spinnerSuccess ✓} You are about the publish the following packages under the tags {tag ${tags.join(
25
+ ', '
26
+ )}}:`
27
+ );
28
+ }
29
30
for (let i = 0; i < packages.length; i++) {
31
const packageName = packages[i];
scripts/release/publish-commands/parse-params.js
+6
-13
@@ -13,10 +13,10 @@ const paramDefinitions = [
13
defaultValue: false,
14
},
15
{
16
- name: 'tag',
16
+ name: 'tags',
17
type: String,
18
- description: 'NPM tag to point to the new release.',
19
- defaultValue: 'untagged',
18
+ multiple: true,
19
+ description: 'NPM tags to point to the new release.',
20
},
21
{
22
name: 'skipPackages',
@@ -29,17 +29,10 @@ const paramDefinitions = [
29
30
module.exports = () => {
31
const params = commandLineArgs(paramDefinitions);
32
- switch (params.tag) {
33
- case 'latest':
34
- case 'next':
35
- case 'experimental':
36
- case 'untagged':
37
- break;
38
- default:
39
- console.error('Unknown tag: "' + params.tag + '"');
40
- process.exit(1);
41
- break;
32
+ if (!params.tags || !params.tags.length) {
33
+ params.tags = [];
34
}
35
splitCommaParams(params.skipPackages);
36
+ splitCommaParams(params.tags);
37
return params;
38
};
scripts/release/publish-commands/print-follow-up-instructions.js
+3
-3
@@ -9,7 +9,7 @@ const {join} = require('path');
9
const theme = require('../theme');
10
const {execRead} = require('../utils');
11
12
-const run = async ({cwd, packages, tag}) => {
12
+const run = async ({cwd, packages, tags}) => {
13
// All packages are built from a single source revision,
14
// so it is safe to read build info from any one of them.
15
const arbitraryPackageName = packages[0];
@@ -24,7 +24,7 @@ const run = async ({cwd, packages, tag}) => {
24
25
clear();
26
27
- if (tag === 'next') {
27
+ if (tags.length === 1 && tags[0] === 'next') {
28
console.log(
29
theme`{header A "next" release} {version ${version}} {header has been published!}`
30
);
@@ -35,7 +35,7 @@ const run = async ({cwd, packages, tag}) => {
35
theme.caution`The release has been published but you're not done yet!`
36
);
37
38
- if (tag === 'latest') {
38
+ if (tags.includes('latest')) {
39
console.log();
40
console.log(
41
theme.header`Please review and commit all local, staged changes.`
scripts/release/publish-commands/publish-to-npm.js
+7
-16
@@ -9,7 +9,7 @@ const {join} = require('path');
9
const {confirm, execRead} = require('../utils');
10
const theme = require('../theme');
11
12
-const run = async ({cwd, dry, packages, tag}, otp) => {
12
+const run = async ({cwd, dry, packages, tags}, otp) => {
13
clear();
14
15
for (let i = 0; i < packages.length; i++) {
@@ -34,34 +34,25 @@ const run = async ({cwd, dry, packages, tag}, otp) => {
34
35
// Publish the package and tag it.
36
if (!dry) {
37
- await exec(`npm publish --tag=${tag} --otp=${otp}`, {
37
+ await exec(`npm publish --tag=${tags[0]} --otp=${otp}`, {
38
cwd: packagePath,
39
});
40
}
41
console.log(theme.command(` cd ${packagePath}`));
42
- console.log(theme.command(` npm publish --tag=${tag} --otp=${otp}`));
42
+ console.log(theme.command(` npm publish --tag=${tags[0]} --otp=${otp}`));
43
44
- if (tag === 'latest') {
45
- // Whenever we publish latest, also tag "next" automatically so they're in sync.
44
+ for (let j = 1; j < tags.length; j++) {
45
if (!dry) {
46
await exec(
48
- `npm dist-tag add ${packageName}@${version} next --otp=${otp}`
47
+ `npm dist-tag add ${packageName}@${version} ${tags[j]} --otp=${otp}`,
48
+ {cwd: packagePath}
49
);
50
}
51
console.log(
52
theme.command(
53
- ` npm dist-tag add ${packageName}@${version} next --otp=${otp}`
53
+ ` npm dist-tag add ${packageName}@${version} ${tags[j]} --otp=${otp}`
54
)
55
);
56
- } else if (tag === 'untagged') {
57
- // npm doesn't let us publish without a tag at all,
58
- // so for one-off publishes we clean it up ourselves.
59
- if (!dry) {
60
- await exec(`npm dist-tag rm ${packageName}@untagged --otp=${otp}`);
61
- }
62
- console.log(
63
- theme.command(`npm dist-tag rm ${packageName}@untagged --otp=${otp}`)
64
- );
56
}
57
}
58
}
scripts/release/publish-commands/update-stable-version-numbers.js
+2
-2
@@ -6,8 +6,8 @@ const {readFileSync, writeFileSync} = require('fs');
6
const {readJson, writeJson} = require('fs-extra');
7
const {join} = require('path');
8
9
-const run = async ({cwd, packages, skipPackages, tag}) => {
10
- if (tag !== 'latest') {
9
+const run = async ({cwd, packages, skipPackages, tags}) => {
10
+ if (!tags.includes('latest')) {
11
// Don't update version numbers for alphas.
12
return;
13
}
scripts/release/publish-commands/validate-tag.js
deleted
-55
@@ -1,55 +0,0 @@
1
-#!/usr/bin/env node
2
-
3
-'use strict';
4
-
5
-const {readJson} = require('fs-extra');
6
-const {join} = require('path');
7
-const theme = require('../theme');
8
-
9
-const run = async ({cwd, packages, tag}) => {
10
- // Prevent a "next" release from ever being published as @latest
11
- // All canaries share a version number, so it's okay to check any of them.
12
- const arbitraryPackageName = packages[0];
13
- const packageJSONPath = join(
14
- cwd,
15
- 'build',
16
- 'node_modules',
17
- arbitraryPackageName,
18
- 'package.json'
19
- );
20
- const {version} = await readJson(packageJSONPath);
21
- const isExperimentalVersion = version.indexOf('experimental') !== -1;
22
- if (version.indexOf('0.0.0') === 0) {
23
- if (tag === 'latest') {
24
- if (isExperimentalVersion) {
25
- console.log(
26
- theme`{error Experimental release} {version ${version}} {error cannot be tagged as} {tag latest}`
27
- );
28
- } else {
29
- console.log(
30
- theme`{error Next release} {version ${version}} {error cannot be tagged as} {tag latest}`
31
- );
32
- }
33
- process.exit(1);
34
- } else if (tag === 'next' && isExperimentalVersion) {
35
- console.log(
36
- theme`{error Experimental release} {version ${version}} {error cannot be tagged as} {tag next}`
37
- );
38
- process.exit(1);
39
- } else if (tag === 'experimental' && !isExperimentalVersion) {
40
- console.log(
41
- theme`{error Next release} {version ${version}} {error cannot be tagged as} {tag experimental}`
42
- );
43
- process.exit(1);
44
- }
45
- } else {
46
- if (tag !== 'latest') {
47
- console.log(
48
- theme`{error Stable release} {version ${version}} {error cannot be tagged as} {tag ${tag}}`
49
- );
50
- process.exit(1);
51
- }
52
- }
53
-};
54
-
55
-module.exports = run;
scripts/release/publish-commands/validate-tags.js
new
+38
@@ -0,0 +1,38 @@
1
+#!/usr/bin/env node
2
+
3
+'use strict';
4
+
5
+const {readJson} = require('fs-extra');
6
+const {join} = require('path');
7
+const theme = require('../theme');
8
+
9
+const run = async ({cwd, packages, tags}) => {
10
+ // Prevent a "next" release from ever being published as @latest
11
+ // All canaries share a version number, so it's okay to check any of them.
12
+ const arbitraryPackageName = packages[0];
13
+ const packageJSONPath = join(
14
+ cwd,
15
+ 'build',
16
+ 'node_modules',
17
+ arbitraryPackageName,
18
+ 'package.json'
19
+ );
20
+ const {version} = await readJson(packageJSONPath);
21
+ if (version.indexOf('0.0.0') === 0) {
22
+ if (tags.includes('latest')) {
23
+ console.log(
24
+ theme`{error Next release} {version ${version}} {error cannot be tagged as} {tag latest}`
25
+ );
26
+ process.exit(1);
27
+ }
28
+ } else {
29
+ if (tags.includes('next')) {
30
+ console.log(
31
+ theme`{error Stable release} {version ${version}} {error cannot be tagged as} {tag next}`
32
+ );
33
+ process.exit(1);
34
+ }
35
+ }
36
+};
37
+
38
+module.exports = run;
scripts/release/publish.js
+4
-4
@@ -8,13 +8,13 @@ const theme = require('./theme');
8
9
const checkNPMPermissions = require('./publish-commands/check-npm-permissions');
10
const confirmSkippedPackages = require('./publish-commands/confirm-skipped-packages');
11
-const confirmVersionAndTag = require('./publish-commands/confirm-version-and-tag');
11
+const confirmVersionAndTags = require('./publish-commands/confirm-version-and-tags');
12
const parseParams = require('./publish-commands/parse-params');
13
const printFollowUpInstructions = require('./publish-commands/print-follow-up-instructions');
14
const promptForOTP = require('./publish-commands/prompt-for-otp');
15
const publishToNPM = require('./publish-commands/publish-to-npm');
16
const updateStableVersionNumbers = require('./publish-commands/update-stable-version-numbers');
17
-const validateTag = require('./publish-commands/validate-tag');
17
+const validateTags = require('./publish-commands/validate-tags');
18
const validateSkipPackages = require('./publish-commands/validate-skip-packages');
19
20
const run = async () => {
@@ -37,9 +37,9 @@ const run = async () => {
37
}
38
});
39
40
- await validateTag(params);
40
+ await validateTags(params);
41
await confirmSkippedPackages(params);
42
- await confirmVersionAndTag(params);
42
+ await confirmVersionAndTags(params);
43
await validateSkipPackages(params);
44
await checkNPMPermissions(params);
45
const otp = await promptForOTP(params);