Skip to content

Commit

Permalink
fix(run): preserve the exit code of the child process (#7820)
Browse files Browse the repository at this point in the history
close #7817
  • Loading branch information
zkochan committed Mar 24, 2024
1 parent cf2040a commit de06d05
Show file tree
Hide file tree
Showing 6 changed files with 24 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .changeset/long-horses-raise.md
@@ -0,0 +1,5 @@
---
"pnpm": patch
---

The exit code of the child process should be preserved on `pnpm run` [#7817](https://github.com/pnpm/pnpm/issues/7817).
3 changes: 2 additions & 1 deletion pnpm/dev/pd.js
Expand Up @@ -85,7 +85,8 @@ const pnpmPackageJson = JSON.parse(fs.readFileSync(pathLib.join(__dirname, 'pack
const nodeBin = process.argv[0]

// Invoke the script just built by esbuild, with Node's sourcemaps enabled
childProcess.spawnSync(nodeBin, ['--enable-source-maps', pathLib.resolve(__dirname, 'dist/pnpm.cjs'), ...process.argv.slice(2)], {
const { status } = childProcess.spawnSync(nodeBin, ['--enable-source-maps', pathLib.resolve(__dirname, 'dist/pnpm.cjs'), ...process.argv.slice(2)], {
stdio: 'inherit'
})
process.exit(status)
})()
6 changes: 3 additions & 3 deletions pnpm/src/errorHandler.ts
Expand Up @@ -39,11 +39,11 @@ export async function errorHandler (error: Error & { code?: string }) {

// Deferring exit. Otherwise, the reporter wouldn't show the error
setTimeout(async () => {
await killProcesses()
await killProcesses('errno' in error && typeof error.errno === 'number' ? error.errno : 1)
}, 0)
}

async function killProcesses () {
async function killProcesses (status: number) {
try {
const descendentProcesses = await getDescendentProcesses(process.pid)
for (const pid of descendentProcesses) {
Expand All @@ -56,5 +56,5 @@ async function killProcesses () {
} catch (err) {
// ignore error here
}
process.exit(1)
process.exit(status)
}
3 changes: 2 additions & 1 deletion pnpm/test/cli.ts
Expand Up @@ -5,6 +5,7 @@ import { prepare, prepareEmpty } from '@pnpm/prepare'
import { fixtures } from '@pnpm/test-fixtures'
import { sync as rimraf } from '@zkochan/rimraf'
import execa from 'execa'
import isWindows from 'is-windows'
import {
execPnpm,
execPnpmSync,
Expand Down Expand Up @@ -63,7 +64,7 @@ test('pnpm fails when an unsupported command is used', async () => {

const { status } = execPnpmSync(['unsupported-command'])

expect(status).toBe(1)
expect(status).toBe(isWindows() ? 1 : 254)
})

test('pnpm fails when no command is specified', async () => {
Expand Down
3 changes: 2 additions & 1 deletion pnpm/test/install/lifecycleScripts.ts
Expand Up @@ -106,7 +106,8 @@ test('dependency should not be added to package.json and lockfile if it was not

const result = execPnpmSync(['install', 'package-that-cannot-be-installed@0.0.0'])

expect(result.status).toBe(1)
expect(typeof result.status).toBe('number')
expect(result.status).not.toBe(0)

expect(project.readCurrentLockfile()).toBeFalsy()
expect(project.readLockfile()).toBeFalsy()
Expand Down
10 changes: 10 additions & 0 deletions pnpm/test/run.ts
Expand Up @@ -77,6 +77,16 @@ test('run: pass all arguments after script name to the build script, even --', a
])
})

test('exit code of child process is preserved', async () => {
prepare({
scripts: {
foo: 'exit 87',
},
})
const result = execPnpmSync(['run', 'foo'])
expect(result.status).toBe(87)
})

test('test -r: pass the args to the command that is specified in the build script of a package.json manifest', async () => {
preparePackages([{
name: 'project',
Expand Down

0 comments on commit de06d05

Please sign in to comment.