diff --git a/lib/commands/publish.js b/lib/commands/publish.js index 6bb2dcc6614bb..f4072074898d3 100644 --- a/lib/commands/publish.js +++ b/lib/commands/publish.js @@ -96,6 +96,10 @@ class Publish extends BaseCommand { } const resolved = npa.resolve(manifest.name, manifest.version) + + // make sure tag is valid, this will throw if invalid + npa(`${manifest.name}@${defaultTag}`) + const registry = npmFetch.pickRegistry(resolved, opts) const creds = this.npm.config.getCredentialsByURI(registry) const noCreds = !(creds.token || creds.username || creds.certfile && creds.keyfile) diff --git a/test/lib/commands/publish.js b/test/lib/commands/publish.js index 85a66d88b8b34..9e7ba6b070583 100644 --- a/test/lib/commands/publish.js +++ b/test/lib/commands/publish.js @@ -291,7 +291,7 @@ t.test('shows usage with wrong set of arguments', async t => { await t.rejects(publish.exec(['a', 'b', 'c']), publish.usage) }) -t.test('throws when invalid tag', async t => { +t.test('throws when invalid tag is semver', async t => { const { npm } = await loadMockNpm(t, { config: { tag: '0.0.13', @@ -306,6 +306,24 @@ t.test('throws when invalid tag', async t => { ) }) +t.test('throws when invalid tag when not url encodable', async t => { + const { npm } = await loadMockNpm(t, { + config: { + tag: '@test', + }, + prefixDir: { + 'package.json': JSON.stringify(pkgJson, null, 2), + }, + }) + await t.rejects( + npm.exec('publish', []), + { + /* eslint-disable-next-line max-len */ + message: 'Invalid tag name "@test" of package "test-package@@test": Tags may not have any characters that encodeURIComponent encodes.', + } + ) +}) + t.test('tarball', async t => { const { npm, joinedOutput, logs, home } = await loadMockNpm(t, { config: {