Skip to content

Commit 6e8d450

Browse files
dgp1130alan-agius4
authored andcommitted
ci: require --tag flag for release and validate it
`--tag` now must be explicitly specified rather than defaulting to `latest`. It is also validated to be one of the expected set of tags. There is a new `--tagCheck false` flag that will skip this in order to handle one-off custom tags if necessary in the future. Apparently NPM requires that all releases have tags (defaulting to `latest` if not explicitly specified), so there is no way to choose **not** to push a new tag. That means that you can't push `10.0.x` and then push `9.0.x` without either using `v9-lts` or clobbering `latest`. The `--tag` requirement should hopefully enforce this restriction to avoid a potential release footgun.
1 parent b699a1e commit 6e8d450

File tree

2 files changed

+37
-7
lines changed

2 files changed

+37
-7
lines changed

scripts/publish.ts

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import build from './build';
1515

1616
export interface PublishArgs {
1717
tag?: string;
18+
tagCheck?: boolean;
1819
branchCheck?: boolean;
1920
versionCheck?: boolean;
2021
registry?: string;
@@ -41,6 +42,24 @@ function _exec(command: string, args: string[], opts: { cwd?: string }, logger:
4142
}
4243
}
4344

45+
/** Returns whether or not the given tag is valid to be used. */
46+
function _tagCheck(tag: string) {
47+
if (tag === 'latest') {
48+
return; // Valid
49+
}
50+
if (tag === 'next') {
51+
return; // Valid
52+
}
53+
if (/v\d+-lts/.test(tag)) {
54+
return; // Valid
55+
}
56+
57+
throw new Error(tags.oneLine`
58+
--tag should be "latest", "next", or "vX-lts". Use \`--no-tagCheck false\`
59+
to skip this check if necessary.
60+
`);
61+
}
62+
4463

4564
function _branchCheck(args: PublishArgs, logger: logging.Logger) {
4665
logger.info('Checking branch...');
@@ -90,6 +109,18 @@ function _versionCheck(args: PublishArgs, logger: logging.Logger) {
90109
}
91110

92111
export default async function (args: PublishArgs, logger: logging.Logger) {
112+
const { tag } = args;
113+
if (!tag) {
114+
// NPM requires that all releases have a tag associated, defaulting to
115+
// `latest`, so there is no way to allow a publish without a tag.
116+
// https://github.com/npm/npm/issues/10625#issuecomment-162106553
117+
throw new Error('--tag is required.');
118+
}
119+
120+
if (args.tagCheck ?? true) {
121+
_tagCheck(tag);
122+
}
123+
93124
if (args.branchCheck ?? true) {
94125
_branchCheck(args, logger);
95126
}
@@ -98,6 +129,9 @@ export default async function (args: PublishArgs, logger: logging.Logger) {
98129
_versionCheck(args, logger);
99130
}
100131

132+
// If no registry is provided, the wombat proxy should be used.
133+
const registry = args.registry ?? wombat;
134+
101135
logger.info('Building...');
102136
await build({}, logger.createChild('build'));
103137

@@ -113,13 +147,7 @@ export default async function (args: PublishArgs, logger: logging.Logger) {
113147
.then(() => {
114148
logger.info(name);
115149

116-
const publishArgs = ['publish'];
117-
if (args.tag) {
118-
publishArgs.push('--tag', args.tag);
119-
}
120-
121-
// If no registry is provided, the wombat proxy should be used.
122-
publishArgs.push('--registry', args.registry ?? wombat);
150+
const publishArgs = [ 'publish', '--tag', tag, '--registry', registry ];
123151

124152
return _exec('npm', publishArgs, {
125153
cwd: pkg.dist,

tests/legacy-cli/e2e/setup/010-local-publish.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ export default async function() {
1616
const pre = prerelease(packages['@angular/cli'].version);
1717
if (pre && pre.length > 0) {
1818
publishArgs.push('--tag', 'next');
19+
} else {
20+
publishArgs.push('--tag', 'latest');
1921
}
2022

2123
await npm(...publishArgs);

0 commit comments

Comments
 (0)