Skip to content

Commit 3a43aa5

Browse files
committed
fix!: publishing prerelease requires tag
1 parent 75a3f12 commit 3a43aa5

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed

lib/commands/publish.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,13 @@ class Publish extends BaseCommand {
116116
// note that publishConfig might have changed as well!
117117
manifest = await this.#getManifest(spec, opts, true)
118118

119+
const isPreRelease = Boolean(semver.parse(manifest.version).prerelease.length)
120+
const isDefaultTag = this.npm.config.isDefault('tag')
121+
122+
if (isPreRelease && isDefaultTag) {
123+
throw new Error('You must specify a tag using --tag when publishing a prerelease version')
124+
}
125+
119126
// If we are not in JSON mode then we show the user the contents of the tarball
120127
// before it is published so they can see it while their otp is pending
121128
if (!json) {
@@ -220,6 +227,7 @@ class Publish extends BaseCommand {
220227
Object.entries(manifest.publishConfig).filter(([key]) => !(key in cliFlags)))
221228
flatten(filteredPublishConfig, opts)
222229
}
230+
223231
return manifest
224232
}
225233
}

test/lib/commands/publish.js

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,7 @@ t.test('workspaces', t => {
521521
t.test('all workspaces - no color', async t => {
522522
const { npm, joinedOutput, logs } = await loadMockNpm(t, {
523523
config: {
524+
tag: 'latest',
524525
color: false,
525526
...auth,
526527
workspaces: true,
@@ -551,6 +552,7 @@ t.test('workspaces', t => {
551552
const { npm, joinedOutput, logs } = await loadMockNpm(t, {
552553
config: {
553554
...auth,
555+
tag: 'latest',
554556
color: 'always',
555557
workspaces: true,
556558
},
@@ -580,6 +582,7 @@ t.test('workspaces', t => {
580582
const { npm, joinedOutput } = await loadMockNpm(t, {
581583
config: {
582584
...auth,
585+
tag: 'latest',
583586
workspace: ['workspace-a'],
584587
},
585588
prefixDir: dir,
@@ -601,6 +604,7 @@ t.test('workspaces', t => {
601604
const { npm } = await loadMockNpm(t, {
602605
config: {
603606
...auth,
607+
tag: 'latest',
604608
workspace: ['workspace-a'],
605609
},
606610
prefixDir: dir,
@@ -642,6 +646,7 @@ t.test('workspaces', t => {
642646
const { npm, joinedOutput } = await loadMockNpm(t, {
643647
config: {
644648
...auth,
649+
tag: 'latest',
645650
workspaces: true,
646651
},
647652
prefixDir: testDir,
@@ -663,6 +668,7 @@ t.test('workspaces', t => {
663668
const { npm } = await loadMockNpm(t, {
664669
config: {
665670
...auth,
671+
tag: 'latest',
666672
workspace: ['workspace-x'],
667673
},
668674
prefixDir: dir,
@@ -677,6 +683,7 @@ t.test('workspaces', t => {
677683
const { npm, joinedOutput } = await loadMockNpm(t, {
678684
config: {
679685
...auth,
686+
tag: 'latest',
680687
workspaces: true,
681688
json: true,
682689
},
@@ -725,6 +732,7 @@ t.test('workspaces', t => {
725732
const { npm, joinedOutput } = await loadMockNpm(t, {
726733
config: {
727734
...auth,
735+
tag: 'latest',
728736
},
729737
prefixDir: testDir,
730738
chdir: ({ prefix }) => path.resolve(prefix, './workspace-a'),
@@ -988,3 +996,75 @@ t.test('manifest', async t => {
988996

989997
t.matchSnapshot(manifest, 'manifest')
990998
})
999+
1000+
t.test('aborts when prerelease and no tag', async t => {
1001+
const { npm } = await loadMockNpm(t, {
1002+
config: {
1003+
loglevel: 'silent',
1004+
[`${alternateRegistry.slice(6)}/:_authToken`]: 'test-other-token',
1005+
},
1006+
prefixDir: {
1007+
'package.json': JSON.stringify({
1008+
...pkgJson,
1009+
version: '1.0.0-0',
1010+
publishConfig: { registry: alternateRegistry },
1011+
}, null, 2),
1012+
},
1013+
})
1014+
1015+
await t.rejects(async () => {
1016+
await npm.exec('publish', [])
1017+
}, new Error('You must specify a tag using --tag when publishing a prerelease version'))
1018+
})
1019+
1020+
t.test('does not abort when prerelease and authored tag latest', async t => {
1021+
const prereleasePkg = {
1022+
...pkgJson,
1023+
version: '1.0.0-0',
1024+
}
1025+
const { npm } = await loadMockNpm(t, {
1026+
config: {
1027+
loglevel: 'silent',
1028+
tag: 'latest',
1029+
[`${alternateRegistry.slice(6)}/:_authToken`]: 'test-other-token',
1030+
},
1031+
prefixDir: {
1032+
'package.json': JSON.stringify({
1033+
...prereleasePkg,
1034+
publishConfig: { registry: alternateRegistry },
1035+
}, null, 2),
1036+
},
1037+
})
1038+
const registry = new MockRegistry({
1039+
tap: t,
1040+
registry: alternateRegistry,
1041+
authorization: 'test-other-token',
1042+
})
1043+
registry.nock.put(`/${pkg}`, body => {
1044+
return t.match(body, {
1045+
_id: pkg,
1046+
name: pkg,
1047+
'dist-tags': { latest: prereleasePkg.version },
1048+
access: null,
1049+
versions: {
1050+
[prereleasePkg.version]: {
1051+
name: pkg,
1052+
version: prereleasePkg.version,
1053+
_id: `${pkg}@${prereleasePkg.version}`,
1054+
dist: {
1055+
shasum: /\.*/,
1056+
// eslint-disable-next-line max-len
1057+
tarball: `http:${alternateRegistry.slice(6)}/test-package/-/test-package-${prereleasePkg.version}.tgz`,
1058+
},
1059+
publishConfig: {
1060+
registry: alternateRegistry,
1061+
},
1062+
},
1063+
},
1064+
_attachments: {
1065+
[`${pkg}-${prereleasePkg.version}.tgz`]: {},
1066+
},
1067+
})
1068+
}).reply(200, {})
1069+
await npm.exec('publish', [])
1070+
})

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy