fix(exec): pnpm exec should return the correct exit code (#3996)

close #3994
This commit is contained in:
Zoltan Kochan
2021-11-16 03:34:18 +02:00
committed by GitHub
parent 5d402ce70e
commit eede95c5c3
4 changed files with 43 additions and 9 deletions

View File

@@ -0,0 +1,6 @@
---
"@pnpm/plugin-commands-script-runners": patch
"pnpm": patch
---
`pnpm exec` should exit with the exit code of the child process. This fixes a regression introduced in pnpm v6.20.4 via [#3951](https://github.com/pnpm/pnpm/pull/3951).

View File

@@ -110,6 +110,7 @@ export async function handler (
const existsPnp = existsInDir.bind(null, '.pnp.cjs')
const workspacePnpPath = opts.workspaceDir && await existsPnp(opts.workspaceDir)
let exitCode = 0
for (const chunk of chunks) {
await Promise.all(chunk.map(async (prefix: string) =>
limitRun(async () => {
@@ -135,9 +136,8 @@ export async function handler (
result.passes++
} catch (err: any) { // eslint-disable-line
if (!opts.recursive && typeof err.exitCode === 'number') {
return {
exitCode: err.exitCode,
}
exitCode = err.exitCode
return
}
logger.info(err)
@@ -156,10 +156,10 @@ export async function handler (
/* eslint-enable @typescript-eslint/dot-notation */
throw err
}
return { exitCode: 0 }
}
)))
}
throwOnCommandFail('pnpm recursive exec', result)
return { exitCode }
}

View File

@@ -135,8 +135,7 @@ export async function handler (
const [scriptName, ...passedThruArgs] = params
if (opts.recursive) {
if (scriptName || Object.keys(opts.selectedProjectsGraph).length > 1) {
await runRecursive(params, opts)
return
return runRecursive(params, opts)
}
dir = Object.keys(opts.selectedProjectsGraph)[0]
} else {
@@ -153,11 +152,10 @@ export async function handler (
if (opts.ifPresent) return
if (opts.fallbackCommandUsed) {
if (opts.argv == null) throw new Error('Could not fallback because opts.argv.original was not passed to the script runner')
await exec({
return exec({
selectedProjectsGraph: {},
...opts,
}, opts.argv.original.slice(1))
return
}
if (opts.workspaceDir) {
const { manifest: rootManifest } = await tryReadProjectManifest(opts.workspaceDir, opts)

View File

@@ -2,7 +2,7 @@ import { promises as fs } from 'fs'
import path from 'path'
import PnpmError from '@pnpm/error'
import { readProjects } from '@pnpm/filter-workspace-packages'
import { exec } from '@pnpm/plugin-commands-script-runners'
import { exec, run } from '@pnpm/plugin-commands-script-runners'
import prepare, { prepareEmpty, preparePackages } from '@pnpm/prepare'
import rimraf from '@zkochan/rimraf'
import execa from 'execa'
@@ -370,6 +370,36 @@ test('pnpm exec on single project', async () => {
expect(outputs).toStrictEqual([])
})
test('pnpm exec on single project should return non-zero exit code when the process fails', async () => {
prepare({})
{
const { exitCode } = await exec.handler({
...DEFAULT_OPTS,
dir: process.cwd(),
recursive: false,
selectedProjectsGraph: {},
}, ['node', '-e', 'process.exitCode=1'])
expect(exitCode).toBe(1)
}
{
const runResult = await run.handler({
...DEFAULT_OPTS,
argv: {
original: ['pnpm', 'node', '-e', 'process.exitCode=1'],
},
dir: process.cwd(),
fallbackCommandUsed: true,
recursive: false,
selectedProjectsGraph: {},
}, ['node'])
expect(runResult['exitCode']).toBe(1)
}
})
test('pnpm exec outside of projects', async () => {
prepareEmpty()