diff --git a/lib/commands/publish.js b/lib/commands/publish.js index c59588fefb241..510e351a931dc 100644 --- a/lib/commands/publish.js +++ b/lib/commands/publish.js @@ -117,7 +117,7 @@ class Publish extends BaseCommand { manifest = await this.#getManifest(spec, opts, true) const isPreRelease = Boolean(semver.parse(manifest.version).prerelease.length) - const isDefaultTag = this.npm.config.isDefault('tag') + const isDefaultTag = this.npm.config.isDefault('tag') && !manifest.publishConfig?.tag if (isPreRelease && isDefaultTag) { throw new Error('You must specify a tag using --tag when publishing a prerelease version.') @@ -157,7 +157,7 @@ class Publish extends BaseCommand { } } - const latestVersion = await this.#latestPublishedVersion(resolved, registry) + const latestVersion = await this.#highestPublishedVersion(resolved, registry) const latestSemverIsGreater = !!latestVersion && semver.gte(latestVersion, manifest.version) if (latestSemverIsGreater && isDefaultTag) { @@ -204,7 +204,7 @@ class Publish extends BaseCommand { } } - async #latestPublishedVersion (spec, registry) { + async #highestPublishedVersion (spec, registry) { try { const packument = await pacote.packument(spec, { ...this.npm.flatOptions, diff --git a/tap-snapshots/test/lib/commands/publish.js.test.cjs b/tap-snapshots/test/lib/commands/publish.js.test.cjs index 1599f1dd5c394..81c7dbe908d24 100644 --- a/tap-snapshots/test/lib/commands/publish.js.test.cjs +++ b/tap-snapshots/test/lib/commands/publish.js.test.cjs @@ -6,7 +6,7 @@ */ 'use strict' exports[`test/lib/commands/publish.js TAP _auth config default registry > new package version 1`] = ` -+ test-package@1.0.0 ++ @npmcli/test-package@1.0.0 ` exports[`test/lib/commands/publish.js TAP bare _auth and registry config > new package version 1`] = ` @@ -15,15 +15,15 @@ exports[`test/lib/commands/publish.js TAP bare _auth and registry config > new p exports[`test/lib/commands/publish.js TAP dry-run > must match snapshot 1`] = ` Array [ - "package: test-package@1.0.0", + "package: @npmcli/test-package@1.0.0", "Tarball Contents", - "87B package.json", + "95B package.json", "Tarball Details", - "name: test-package", + "name: @npmcli/test-package", "version: 1.0.0", - "filename: test-package-1.0.0.tgz", + "filename: npmcli-test-package-1.0.0.tgz", "package size: {size}", - "unpacked size: 87 B", + "unpacked size: 95 B", "shasum: {sha}", "integrity: {integrity} "total files: 1", @@ -76,7 +76,7 @@ exports[`test/lib/commands/publish.js TAP has token auth for scope configured re ` exports[`test/lib/commands/publish.js TAP ignore-scripts > new package version 1`] = ` -+ test-package@1.0.0 ++ @npmcli/test-package@1.0.0 ` exports[`test/lib/commands/publish.js TAP json > must match snapshot 1`] = ` @@ -87,14 +87,14 @@ Array [ exports[`test/lib/commands/publish.js TAP json > new package json 1`] = ` { - "id": "test-package@1.0.0", - "name": "test-package", + "id": "@npmcli/test-package@1.0.0", + "name": "@npmcli/test-package", "version": "1.0.0", "size": "{size}", - "unpackedSize": 87, + "unpackedSize": 95, "shasum": "{sha}", "integrity": "{integrity}", - "filename": "test-package-1.0.0.tgz", + "filename": "npmcli-test-package-1.0.0.tgz", "files": [ { "path": "package.json", @@ -249,7 +249,7 @@ Object { ` exports[`test/lib/commands/publish.js TAP no auth dry-run > must match snapshot 1`] = ` -+ test-package@1.0.0 ++ @npmcli/test-package@1.0.0 ` exports[`test/lib/commands/publish.js TAP no auth dry-run > warns about auth being needed 1`] = ` @@ -259,7 +259,7 @@ Array [ ` exports[`test/lib/commands/publish.js TAP prioritize CLI flags over publishConfig > new package version 1`] = ` -+ test-package@1.0.0 ++ @npmcli/test-package@1.0.0 ` exports[`test/lib/commands/publish.js TAP public access > must match snapshot 1`] = ` @@ -285,7 +285,7 @@ exports[`test/lib/commands/publish.js TAP public access > new package version 1` ` exports[`test/lib/commands/publish.js TAP re-loads publishConfig.registry if added during script process > new package version 1`] = ` -+ test-package@1.0.0 ++ @npmcli/test-package@1.0.0 ` exports[`test/lib/commands/publish.js TAP respects publishConfig.registry, runs appropriate scripts > new package version 1`] = ` diff --git a/test/lib/commands/publish.js b/test/lib/commands/publish.js index 10dc9b33deda4..0ede4ffc20c83 100644 --- a/test/lib/commands/publish.js +++ b/test/lib/commands/publish.js @@ -6,7 +6,7 @@ const Arborist = require('@npmcli/arborist') const path = require('node:path') const fs = require('node:fs') -const pkg = 'test-package' +const pkg = '@npmcli/test-package' const token = 'test-auth-token' const auth = { '//registry.npmjs.org/:_authToken': token } const alternateRegistry = 'https://other.registry.npmjs.org' @@ -238,8 +238,7 @@ t.test('throws when invalid tag when not url encodable', async t => { 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.', + message: `Invalid tag name "@test" of package "${pkg}@@test": Tags may not have any characters that encodeURIComponent encodes.`, } ) }) @@ -857,8 +856,8 @@ t.test('prerelease dist tag', (t) => { t.end() }) -t.test('latest dist tag', (t) => { - const init = (version) => ({ +t.test('semver highest dist tag', async t => { + const init = ({ version, pkgExtra = {} }) => ({ config: { loglevel: 'silent', ...auth, @@ -866,6 +865,7 @@ t.test('latest dist tag', (t) => { prefixDir: { 'package.json': JSON.stringify({ ...pkgJson, + ...pkgExtra, version, }, null, 2), }, @@ -879,46 +879,57 @@ t.test('latest dist tag', (t) => { { version: '105.0.0-pre' }, ] - t.test('PREVENTS publish when latest version is HIGHER than publishing version', async t => { + await t.test('PREVENTS publish when highest version is HIGHER than publishing version', async t => { const version = '99.0.0' - const { npm, registry } = await loadNpmWithRegistry(t, init(version)) + const { npm, registry } = await loadNpmWithRegistry(t, init({ version })) registry.publish(pkg, { noPut: true, packuments }) await t.rejects(async () => { await npm.exec('publish', []) - /* eslint-disable-next-line max-len */ }, new Error('Cannot implicitly apply the "latest" tag because published version 100.0.0 is higher than the new version 99.0.0. You must specify a tag using --tag.')) }) - t.test('ALLOWS publish when latest is HIGHER than publishing version and flag', async t => { + await t.test('ALLOWS publish when highest is HIGHER than publishing version and flag', async t => { const version = '99.0.0' const { npm, registry } = await loadNpmWithRegistry(t, { - ...init(version), + ...init({ version }), argv: ['--tag', 'latest'], }) registry.publish(pkg, { packuments }) await npm.exec('publish', []) }) - t.test('ALLOWS publish when latest versions are LOWER than publishing version', async t => { + await t.test('ALLOWS publish when highest versions are LOWER than publishing version', async t => { const version = '101.0.0' - const { npm, registry } = await loadNpmWithRegistry(t, init(version)) + const { npm, registry } = await loadNpmWithRegistry(t, init({ version })) registry.publish(pkg, { packuments }) await npm.exec('publish', []) }) - t.test('ALLOWS publish when packument has empty versions (for coverage)', async t => { + await t.test('ALLOWS publish when packument has empty versions (for coverage)', async t => { const version = '1.0.0' - const { npm, registry } = await loadNpmWithRegistry(t, init(version)) + const { npm, registry } = await loadNpmWithRegistry(t, init({ version })) registry.publish(pkg, { manifest: { versions: { } } }) await npm.exec('publish', []) }) - t.test('ALLOWS publish when packument has empty manifest (for coverage)', async t => { + await t.test('ALLOWS publish when packument has empty manifest (for coverage)', async t => { const version = '1.0.0' - const { npm, registry } = await loadNpmWithRegistry(t, init(version)) + const { npm, registry } = await loadNpmWithRegistry(t, init({ version })) registry.publish(pkg, { manifest: {} }) await npm.exec('publish', []) }) - t.end() + await t.test('ALLOWS publish when highest version is HIGHER than publishing version with publishConfig', async t => { + const version = '99.0.0' + const { npm, registry } = await loadNpmWithRegistry(t, init({ + version, + pkgExtra: { + publishConfig: { + tag: 'next', + }, + }, + })) + registry.publish(pkg, { packuments }) + await npm.exec('publish', []) + }) })