test(update): prove probe-era receipts reuse under the manifest npm version
The receipt key hashes the npm version. Cover the transition from the child-probe lane to the manifest lane: an install completed under the probed version must still be recognized as complete once the version is read from npm's package.json (same string for standard npm), and that reuse must hold when `--version` can no longer spawn — the #123933 lane on a Windows Job Object — without running npm ci again. A changed npm version still invalidates the receipt. Runs without symlinks so Windows CI exercises it too. Co-authored-by: JoaoMarcos44 <joaomarcosdias444@gmail.com>
This commit is contained in:
@@ -245,12 +245,13 @@ function fakeNpmTree(source, { manifest }) {
|
||||
json(join(fake, 'real/node_modules/semver/package.json'), { name: 'semver', version: '1.0.0', main: 'index.js' })
|
||||
writeFileSync(join(fake, 'real/node_modules/semver/index.js'), 'module.exports = { satisfies: () => true }\n')
|
||||
const spawned = join(source, 'spawned.jsonl')
|
||||
writeFileSync(join(npmRoot, 'bin/npm-cli.js'), [
|
||||
const armProbe = ({ exit }) => writeFileSync(join(npmRoot, 'bin/npm-cli.js'), [
|
||||
`const { appendFileSync } = require('node:fs')`,
|
||||
`appendFileSync(${JSON.stringify(spawned)}, process.argv[2] + '\\n')`,
|
||||
`if (process.argv[2] === '--version') { console.log('10.8.2'); process.exit(${manifest ? 3 : 0}) }`,
|
||||
`if (process.argv[2] === '--version') { console.log('10.8.2'); process.exit(${exit}) }`,
|
||||
].join('\n'))
|
||||
return { fake, npmRoot, spawned }
|
||||
armProbe({ exit: manifest ? 3 : 0 })
|
||||
return { fake, npmRoot, spawned, armProbe }
|
||||
}
|
||||
|
||||
test.skipIf(process.platform === 'win32')('the npm version reads from the manifest without a child spawn, through a symlinked npm_execpath', async () => {
|
||||
@@ -284,3 +285,26 @@ test('an npm layout without a readable manifest falls back to the child version
|
||||
// The unresolvable manifest kept the pre-fix behavior: probe first, then ci.
|
||||
expect(readFileSync(spawned, 'utf8')).toBe('--version\nci\n')
|
||||
}, 30000)
|
||||
|
||||
// The receipt key hashes the npm version. An install completed by the probe
|
||||
// lane must still count as complete once the manifest supplies the version,
|
||||
// or every user re-runs npm ci after this change — and, as in #123933, that
|
||||
// reuse must not depend on a version probe that can no longer spawn.
|
||||
test('a receipt keyed by the probed version reuses under the manifest version, even when the probe fails', async () => {
|
||||
const { prepareNodeDependencies } = await import('../scripts/build/node-deps.mjs')
|
||||
const source = fixture()
|
||||
const { npmRoot, spawned, armProbe } = fakeNpmTree(source, { manifest: null })
|
||||
mkdirSync(join(source, 'node_modules'))
|
||||
writeFileSync(join(source, 'node_modules/.package-lock.json'), '{"packages": {}}')
|
||||
const options = { source, workspaces: ['web'], reuse: true,
|
||||
env: { ...process.env, npm_config_cache: join(source, '.npm-cache'), npm_execpath: join(npmRoot, 'bin/npm-cli.js') } }
|
||||
prepareNodeDependencies(options)
|
||||
expect(readFileSync(spawned, 'utf8')).toBe('--version\nci\n')
|
||||
json(join(npmRoot, 'package.json'), { name: 'npm', version: '10.8.2' })
|
||||
armProbe({ exit: 1 })
|
||||
prepareNodeDependencies({ ...options, install: false })
|
||||
expect(readFileSync(spawned, 'utf8')).toBe('--version\nci\n')
|
||||
// A genuinely different npm still invalidates the receipt.
|
||||
json(join(npmRoot, 'package.json'), { name: 'npm', version: '10.8.3' })
|
||||
expect(() => prepareNodeDependencies({ ...options, install: false })).toThrow(/disabled/)
|
||||
}, 30000)
|
||||
|
||||
Reference in New Issue
Block a user