From bc9c3af36f6fb4fc32544edd0f79f330bdcc6ea7 Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Mon, 4 May 2026 17:36:31 +0200 Subject: [PATCH] fix(publish): respect publishConfig.registry in non-recursive publish (#11449) The native publish flow introduced in v11 (replacing the `npm publish` shell-out with `libnpmpublish`) only read the registry from `registries` config, ignoring `publishConfig.registry` from the package's `package.json`. Restore the prior behavior by giving `publishConfig.registry` precedence over the configured registries. Closes #11419 --- .../publish-respect-publishconfig-registry.md | 6 +++++ .../commands/src/publish/publishPackedPkg.ts | 12 +++++++--- releasing/commands/test/publish/publish.ts | 22 +++++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 .changeset/publish-respect-publishconfig-registry.md diff --git a/.changeset/publish-respect-publishconfig-registry.md b/.changeset/publish-respect-publishconfig-registry.md new file mode 100644 index 0000000000..591fbf06cc --- /dev/null +++ b/.changeset/publish-respect-publishconfig-registry.md @@ -0,0 +1,6 @@ +--- +"@pnpm/releasing.commands": patch +"pnpm": patch +--- + +Fixed `pnpm publish` to honor `publishConfig.registry` from `package.json` when publishing a single package. The native publish flow introduced in v11 was reading the registry from `.npmrc` only, ignoring the per-package override [#11419](https://github.com/pnpm/pnpm/issues/11419). diff --git a/releasing/commands/src/publish/publishPackedPkg.ts b/releasing/commands/src/publish/publishPackedPkg.ts index 5b4083a1eb..f3087f49fa 100644 --- a/releasing/commands/src/publish/publishPackedPkg.ts +++ b/releasing/commands/src/publish/publishPackedPkg.ts @@ -59,7 +59,10 @@ export async function publishPackedPkg ( } async function createPublishOptions (manifest: ExportedManifest, options: PublishPackedPkgOptions): Promise { - const { registry, config } = findRegistryInfo(manifest, options) + const publishConfigRegistry = typeof manifest.publishConfig?.registry === 'string' + ? manifest.publishConfig.registry + : undefined + const { registry, config } = findRegistryInfo(manifest, options, publishConfigRegistry) const { creds, tls } = config ?? {} const { @@ -130,16 +133,19 @@ interface RegistryInfo { /** * Find credentials and SSL info for a package's registry. * Follows {@link https://docs.npmjs.com/cli/v10/configuring-npm/npmrc#auth-related-configuration}. + * + * The manifest's `publishConfig.registry`, when set, takes precedence over `registries`. */ function findRegistryInfo ( { name }: ExportedManifest, - { configByUri, registries }: Pick + { configByUri, registries }: Pick, + publishConfigRegistry?: string ): Partial { // eslint-disable-next-line regexp/no-unused-capturing-group const scopedMatches = /@(?[^/]+)\/(?[^/]+)/.exec(name) const registryName = scopedMatches?.groups ? `@${scopedMatches.groups.scope}` : 'default' - const nonNormalizedRegistry = registries[registryName] ?? registries.default + const nonNormalizedRegistry = publishConfigRegistry ?? registries[registryName] ?? registries.default const supportedRegistryInfo = parseSupportedRegistryUrl(nonNormalizedRegistry) if (!supportedRegistryInfo) { diff --git a/releasing/commands/test/publish/publish.ts b/releasing/commands/test/publish/publish.ts index c90506c71f..c8fadd4a82 100644 --- a/releasing/commands/test/publish/publish.ts +++ b/releasing/commands/test/publish/publish.ts @@ -304,6 +304,28 @@ test('publish: package with all possible fields in publishConfig', async () => { }) }) +test('publish: package with publishConfig.registry overrides the default registry', async () => { + const pkgName = `test-publish-config-registry-${Date.now()}` + prepare({ + name: pkgName, + version: '1.0.0', + + publishConfig: { + registry: `http://localhost:${REGISTRY_MOCK_PORT}`, + }, + }) + + await publish.handler({ + ...DEFAULT_OPTS, + argv: { original: ['publish'] }, + configByUri: CONFIG_BY_URI, + dir: process.cwd(), + registries: { default: 'https://__fake_npm_registry__.com' }, + }, []) + + await checkPkgExists(pkgName, '1.0.0') +}) + test('publish: package with publishConfig.directory', async () => { const packages = preparePackages([ {