mirror of
https://github.com/pnpm/pnpm.git
synced 2026-06-28 01:45:30 -04:00
fix(config): restore globalconfig lookup (#12252)
* fix(config): restore globalconfig lookup * refactor(config): derive globalconfig path from a single shared helper Extract getGlobalConfigPath into @pnpm/config.reader and use it for both the reader's warning message and 'config get globalconfig' so the reported path cannot drift from the file pnpm actually reads. Add an e2e test that writes a setting to the reported path and reads it back. --------- Co-authored-by: Zoltan Kochan <z@kochan.io>
This commit is contained in:
7
.changeset/fix-config-globalconfig.md
Normal file
7
.changeset/fix-config-globalconfig.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@pnpm/config.commands": patch
|
||||
"@pnpm/config.reader": patch
|
||||
"pnpm": patch
|
||||
---
|
||||
|
||||
Fixed `pnpm config get globalconfig` to return the global `config.yaml` path again [pnpm/pnpm#11962](https://github.com/pnpm/pnpm/issues/11962).
|
||||
@@ -1,4 +1,4 @@
|
||||
import { isIniConfigKey, types } from '@pnpm/config.reader'
|
||||
import { getGlobalConfigPath, isIniConfigKey, types } from '@pnpm/config.reader'
|
||||
import { getObjectValueByPropertyPath } from '@pnpm/object.property-path'
|
||||
import { isCamelCase } from '@pnpm/text.naming-cases'
|
||||
import camelcase from 'camelcase'
|
||||
@@ -35,6 +35,9 @@ function lookupConfig (opts: ConfigCommandOptions, key: string, isScopedKey: boo
|
||||
}
|
||||
return { value: opts.authConfig[key] }
|
||||
}
|
||||
if (key === 'globalconfig') {
|
||||
return { value: getGlobalConfigPath(opts.configDir) }
|
||||
}
|
||||
const kebabKey = isCamelCase(key) ? kebabCase(key) : key
|
||||
// Resolve typed keys from Config — check explicitly set values first,
|
||||
// then fall back to authConfig (for keys like registry set in .npmrc)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import path from 'node:path'
|
||||
|
||||
import { describe, expect, test } from '@jest/globals'
|
||||
import { config } from '@pnpm/config.commands'
|
||||
|
||||
@@ -267,7 +269,18 @@ test('config get with scoped registry key that does not exist', async () => {
|
||||
expect(getOutputString(getResult)).toBe('undefined')
|
||||
})
|
||||
|
||||
// globalconfig and npm-globalconfig tests removed — pnpm no longer exposes these npm-compat properties
|
||||
test('config get globalconfig returns the global config.yaml path', async () => {
|
||||
const configDir = path.join(process.cwd(), 'global-config')
|
||||
const getResult = await config.handler(createConfigCommandOpts({
|
||||
dir: process.cwd(),
|
||||
cliOptions: {},
|
||||
configDir,
|
||||
global: true,
|
||||
authConfig: {},
|
||||
}), ['get', 'globalconfig'])
|
||||
|
||||
expect(getOutputString(getResult)).toBe(path.join(configDir, 'config.yaml'))
|
||||
})
|
||||
|
||||
describe('does not traverse the prototype chain (#10296)', () => {
|
||||
test.each([
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import os from 'node:os'
|
||||
import path from 'node:path'
|
||||
|
||||
import { GLOBAL_CONFIG_YAML_FILENAME } from '@pnpm/constants'
|
||||
|
||||
export function getGlobalConfigPath (configDir: string): string {
|
||||
return path.join(configDir, GLOBAL_CONFIG_YAML_FILENAME)
|
||||
}
|
||||
|
||||
export function getCacheDir (
|
||||
opts: {
|
||||
env: NodeJS.ProcessEnv
|
||||
|
||||
@@ -36,7 +36,7 @@ import type {
|
||||
} from './Config.js'
|
||||
import { isConfigFileKey } from './configFileKey.js'
|
||||
import { extractAndRemoveDependencyBuildOptions, hasDependencyBuildOptions } from './dependencyBuildOptions.js'
|
||||
import { getCacheDir, getConfigDir, getDataDir, getStateDir } from './dirs.js'
|
||||
import { getCacheDir, getConfigDir, getDataDir, getGlobalConfigPath, getStateDir } from './dirs.js'
|
||||
import { parseEnvVars } from './env.js'
|
||||
import { getNetworkConfigs } from './getNetworkConfigs.js'
|
||||
import { getOptionsFromPnpmSettings } from './getOptionsFromRootManifest.js'
|
||||
@@ -52,6 +52,7 @@ import { types } from './types.js'
|
||||
export { types }
|
||||
|
||||
export { getDefaultWorkspaceConcurrency, getWorkspaceConcurrency } from './concurrency.js'
|
||||
export { getGlobalConfigPath } from './dirs.js'
|
||||
export { getDefaultCreds, getNetworkConfigs, type NetworkConfigs } from './getNetworkConfigs.js'
|
||||
export { getOptionsFromPnpmSettings, type OptionsFromRootManifest } from './getOptionsFromRootManifest.js'
|
||||
export type { Creds } from './parseCreds.js'
|
||||
@@ -305,7 +306,7 @@ export async function getConfig (opts: {
|
||||
}
|
||||
}
|
||||
if (ignoredKeys.length > 0) {
|
||||
const globalYamlConfigPath = path.join(configDir, GLOBAL_CONFIG_YAML_FILENAME)
|
||||
const globalYamlConfigPath = getGlobalConfigPath(configDir)
|
||||
warnings.push(`The following settings cannot be set in the global config file ("${globalYamlConfigPath}") and were ignored: ${ignoredKeys.map(k => `"${k}"`).join(', ')}. Move them to a project-level pnpm-workspace.yaml. To share these settings across projects, use config dependencies: https://pnpm.io/11.x/config-dependencies`)
|
||||
}
|
||||
addSettingsFromWorkspaceManifestToConfig(pnpmConfig, {
|
||||
|
||||
@@ -276,6 +276,7 @@ test('pnpm config get shows settings from global config.yaml', () => {
|
||||
expect(configGet('dangerously-allow-all-builds')).toBe('true')
|
||||
expect(configGet('dlxCacheMaxAge')).toBe('1234')
|
||||
expect(configGet('dlx-cache-max-age')).toBe('1234')
|
||||
expect(configGet('globalconfig')).toBe(path.join(configDir, 'config.yaml'))
|
||||
|
||||
// doesn't list CLI options
|
||||
expect(configGet('dev')).toBe('undefined')
|
||||
@@ -289,3 +290,18 @@ test('pnpm config get shows settings from global config.yaml', () => {
|
||||
expect(configGet('packageExtensions')).toBe('undefined')
|
||||
expect(configGet('package-extensions')).toBe('undefined')
|
||||
})
|
||||
|
||||
test('the path from "config get globalconfig" is the file that pnpm actually reads global settings from', () => {
|
||||
prepare()
|
||||
|
||||
const XDG_CONFIG_HOME = path.resolve('.config')
|
||||
const env = { XDG_CONFIG_HOME }
|
||||
const configGet = (key: string) =>
|
||||
execPnpmSync(['config', 'get', key], { expectSuccess: true, env }).stdout.toString().trim()
|
||||
|
||||
const globalConfigPath = configGet('globalconfig')
|
||||
fs.mkdirSync(path.dirname(globalConfigPath), { recursive: true })
|
||||
fs.writeFileSync(globalConfigPath, 'dlxCacheMaxAge: 4321\n')
|
||||
|
||||
expect(configGet('dlx-cache-max-age')).toBe('4321')
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user