fix(build): normalize npm config names in dependency receipts

This commit is contained in:
ethernet
2026-09-12 14:06:35 -04:00
parent 21bf81a1ee
commit 81b4c132b5
2 changed files with 21 additions and 1 deletions

View File

@@ -64,7 +64,9 @@ export function prepareNodeDependencies({ source, workspaces, env = process.env,
const hiddenLock = join(source, 'node_modules/.package-lock.json')
const inputs = createHash('sha256').update(JSON.stringify({
node: process.versions.node, npm: npmVersion, platform: process.platform, arch: process.arch, args,
config: Object.entries(env).filter(([key]) => /^npm_config_/i.test(key) && !/^npm_config_(cache|offline|prefer_offline)$/i.test(key)).sort(),
// npm names are case-insensitive; Windows Python uppercases inherited keys.
config: Object.entries(env).filter(([key]) => /^npm_config_/i.test(key) && !/^npm_config_(cache|offline|prefer_offline)$/i.test(key))
.map(([key, value]) => [key.toLowerCase(), value]).sort(),
}))
const files = ['package-lock.json', '.npmrc', ...Object.keys(lock.packages)
.filter(path => !path.split('/').includes('node_modules'))

View File

@@ -116,3 +116,21 @@ test('reuse respects lifecycle configuration and repairs missing installed packa
prepareNodeDependencies({ ...options, reuse: false })
expect(readFileSync(artifact, 'utf8')).not.toBe(repaired)
}, 30000)
test('npm configuration name casing does not invalidate a completed install', async () => {
const { prepareNodeDependencies } = await import('../scripts/build/node-deps.mjs')
const source = fixture()
const env = Object.fromEntries(Object.entries(process.env).filter(([key]) => key.toLowerCase() !== 'npm_config_prefix'))
Object.assign(env, { npm_config_offline: 'true', npm_config_cache: join(source, '.npm-cache') })
const prefix = join(source, 'npm-prefix')
const options = { source, workspaces: ['web'], reuse: true }
prepareNodeDependencies({ ...options, env: { ...env, npm_config_prefix: prefix } })
const artifact = join(source, 'node_modules/postinstall-output')
writeFileSync(artifact, 'built')
// The Windows runner sets lowercase; Python's os.environ returns uppercase.
prepareNodeDependencies({ ...options, env: { ...env, NPM_CONFIG_PREFIX: prefix } })
expect(readFileSync(artifact, 'utf8')).toBe('built')
// Normalize names, not values: a genuinely changed setting still reinstalls.
prepareNodeDependencies({ ...options, env: { ...env, NPM_CONFIG_PREFIX: join(source, 'other-prefix') } })
expect(existsSync(artifact)).toBe(false)
}, 30000)