diff --git a/.changeset/khaki-cars-return.md b/.changeset/khaki-cars-return.md new file mode 100644 index 0000000000..2b6024db58 --- /dev/null +++ b/.changeset/khaki-cars-return.md @@ -0,0 +1,6 @@ +--- +"@pnpm/plugin-commands-env": minor +"pnpm": minor +--- + +If pnpm previously failed to install node when the `use-node-version` option is set, that download and install will now be re-attempted when pnpm is ran again. diff --git a/packages/plugin-commands-env/src/node.ts b/packages/plugin-commands-env/src/node.ts index 8a9cab942e..a00425f5b2 100644 --- a/packages/plugin-commands-env/src/node.ts +++ b/packages/plugin-commands-env/src/node.ts @@ -67,7 +67,6 @@ export async function getNodeDir (fetch: FetchFromRegistry, opts: NvmNodeCommand } async function installNode (fetch: FetchFromRegistry, wantedNodeVersion: string, versionDir: string, opts: NvmNodeCommandOptions & { releaseDir?: string }) { - await fs.promises.mkdir(versionDir, { recursive: true }) const nodeMirror = getNodeMirror(opts.rawConfig, opts.releaseDir ?? 'release') const { tarball, pkgName } = getNodeJSTarball(wantedNodeVersion, nodeMirror) if (tarball.endsWith('.zip')) { diff --git a/packages/plugin-commands-env/test/env.test.ts b/packages/plugin-commands-env/test/env.test.ts index 4c58964b37..05f39fc639 100644 --- a/packages/plugin-commands-env/test/env.test.ts +++ b/packages/plugin-commands-env/test/env.test.ts @@ -98,3 +98,38 @@ test('fail if a non-existend Node.js LTS is tried to be installed', async () => }, ['use', 'boo']) ).rejects.toEqual(new PnpmError('COULD_NOT_RESOLVE_NODEJS', 'Couldn\'t find Node.js version matching boo')) }) + +// Regression test for https://github.com/pnpm/pnpm/issues/4104 +test('it re-attempts failed downloads', async () => { + tempDir() + + // This fixture was retrieved from http://nodejs.org/download/release/index.json on 2021-12-12. + const testReleaseInfoPath = path.join(__dirname, './fixtures/node-16.4.0-release-info.json') + + const nockScope = nock('https://nodejs.org') + // Using nock's persist option since the default fetcher retries requests. + .persist() + .get('/download/release/index.json') + .replyWithFile(200, testReleaseInfoPath) + .persist() + .get(uri => uri.startsWith('/download/release/v16.4.0/')) + .replyWithError('Intentionally failing response for test') + + try { + const attempts = 2 + for (let i = 0; i < attempts; i++) { + await expect( + env.handler({ + bin: process.cwd(), + global: true, + pnpmHomeDir: process.cwd(), + rawConfig: {}, + }, ['use', '16.4.0']) + ).rejects.toThrow('Intentionally failing response for test') + } + + expect(nockScope.isDone()).toBeTruthy() + } finally { + nock.cleanAll() + } +}) diff --git a/packages/plugin-commands-env/test/fixtures/node-16.4.0-release-info.json b/packages/plugin-commands-env/test/fixtures/node-16.4.0-release-info.json new file mode 100644 index 0000000000..e5e455e912 --- /dev/null +++ b/packages/plugin-commands-env/test/fixtures/node-16.4.0-release-info.json @@ -0,0 +1,35 @@ +[ + { + "version": "v16.4.0", + "date": "2021-06-23", + "files": [ + "aix-ppc64", + "headers", + "linux-arm64", + "linux-armv7l", + "linux-ppc64le", + "linux-s390x", + "linux-x64", + "osx-arm64-tar", + "osx-x64-pkg", + "osx-x64-tar", + "src", + "win-x64-7z", + "win-x64-exe", + "win-x64-msi", + "win-x64-zip", + "win-x86-7z", + "win-x86-exe", + "win-x86-msi", + "win-x86-zip" + ], + "npm": "7.18.1", + "v8": "9.1.269.36", + "uv": "1.41.0", + "zlib": "1.2.11", + "openssl": "1.1.1k+quic", + "modules": "93", + "lts": false, + "security": false + } +]