diff --git a/.changeset/bright-pots-carry.md b/.changeset/bright-pots-carry.md new file mode 100644 index 0000000000..f34a0186f8 --- /dev/null +++ b/.changeset/bright-pots-carry.md @@ -0,0 +1,6 @@ +--- +"@pnpm/plugin-commands-publishing": patch +"pnpm": patch +--- + +`pnpm publish` should be able to publish from a local tarball [#7950](https://github.com/pnpm/pnpm/issues/7950). diff --git a/releasing/plugin-commands-publishing/src/publish.ts b/releasing/plugin-commands-publishing/src/publish.ts index 9fad16460f..6825cb8a33 100644 --- a/releasing/plugin-commands-publishing/src/publish.ts +++ b/releasing/plugin-commands-publishing/src/publish.ts @@ -207,7 +207,7 @@ Do you want to continue?`, } if (dirInParams?.endsWith('.tgz')) { - const { status } = runNpm(opts.npmPath, ['publish', ...args]) + const { status } = runNpm(opts.npmPath, ['publish', dirInParams, ...args]) return { exitCode: status ?? 0 } } const dir = dirInParams ?? opts.dir ?? process.cwd() diff --git a/releasing/plugin-commands-publishing/test/publish.ts b/releasing/plugin-commands-publishing/test/publish.ts index 8a1ca27378..30c893a1c4 100644 --- a/releasing/plugin-commands-publishing/test/publish.ts +++ b/releasing/plugin-commands-publishing/test/publish.ts @@ -10,7 +10,7 @@ import { REGISTRY_MOCK_PORT } from '@pnpm/registry-mock' import { createTestIpcServer } from '@pnpm/test-ipc-server' import crossSpawn from 'cross-spawn' import { sync as writeYamlFile } from 'write-yaml-file' -import { DEFAULT_OPTS } from './utils' +import { DEFAULT_OPTS, checkPkgExists } from './utils' const skipOnWindowsCI = isCI && isWindows() ? test.skip : test @@ -912,3 +912,29 @@ test('publish: use bearer token helper for authentication', async () => { gitChecks: false, }, []) }) + +test('publish from a tarball', async () => { + const pkg = { + name: 'test-publish-tarball', + version: '0.0.0', + } + prepare(pkg) + + await pack.handler({ + ...DEFAULT_OPTS, + argv: { original: [] }, + dir: process.cwd(), + extraBinPaths: [], + }) + + fs.rmSync('package.json') + + const tarballName = `${pkg.name}-${pkg.version}.tgz` + await publish.handler({ + ...DEFAULT_OPTS, + argv: { original: ['publish', tarballName, ...CREDENTIALS] }, + dir: process.cwd(), + }, [tarballName]) + + await checkPkgExists(pkg.name, pkg.version) +}) diff --git a/releasing/plugin-commands-publishing/test/recursivePublish.ts b/releasing/plugin-commands-publishing/test/recursivePublish.ts index 22584460a5..f4b039fbc1 100644 --- a/releasing/plugin-commands-publishing/test/recursivePublish.ts +++ b/releasing/plugin-commands-publishing/test/recursivePublish.ts @@ -9,7 +9,7 @@ import { type ProjectManifest } from '@pnpm/types' import execa from 'execa' import crossSpawn from 'cross-spawn' import loadJsonFile from 'load-json-file' -import { DEFAULT_OPTS } from './utils' +import { DEFAULT_OPTS, checkPkgExists } from './utils' const CREDENTIALS = `\ registry=http://localhost:${REGISTRY_MOCK_PORT}/ @@ -97,16 +97,8 @@ test('recursive publish', async () => { recursive: true, }, []) - { - const { stdout } = await execa('npm', ['view', pkg1.name, 'versions', '--registry', `http://localhost:${REGISTRY_MOCK_PORT}`, '--json']) - const output = JSON.parse(stdout.toString()) - expect(Array.isArray(output) ? output[0] : output).toStrictEqual(pkg1.version) - } - { - const { stdout } = await execa('npm', ['view', pkg2.name, 'versions', '--registry', `http://localhost:${REGISTRY_MOCK_PORT}`, '--json']) - const output = JSON.parse(stdout.toString()) - expect(Array.isArray(output) ? output[0] : output).toStrictEqual(pkg2.version) - } + await checkPkgExists(pkg1.name, pkg1.version) + await checkPkgExists(pkg2.name, pkg2.version) projects[pkg1.name].writePackageJson({ ...pkg1, version: '2.0.0' }) diff --git a/releasing/plugin-commands-publishing/test/utils/index.ts b/releasing/plugin-commands-publishing/test/utils/index.ts index 1ec75e1d85..fed4cce537 100644 --- a/releasing/plugin-commands-publishing/test/utils/index.ts +++ b/releasing/plugin-commands-publishing/test/utils/index.ts @@ -1,4 +1,5 @@ import { REGISTRY_MOCK_PORT } from '@pnpm/registry-mock' +import execa from 'execa' const REGISTRY = `http://localhost:${REGISTRY_MOCK_PORT}` @@ -47,3 +48,9 @@ export const DEFAULT_OPTS = { workspaceConcurrency: 4, virtualStoreDirMaxLength: 120, } + +export async function checkPkgExists (packageName: string, expectedVersion: string): Promise { + const { stdout } = await execa('npm', ['view', packageName, 'versions', '--registry', `http://localhost:${REGISTRY_MOCK_PORT}`, '--json']) + const output = JSON.parse(stdout.toString()) + expect(Array.isArray(output) ? output[0] : output).toStrictEqual(expectedVersion) +}