diff --git a/commands/exec/index.js b/commands/exec/index.js index c26a3e532e..2c50df3aa8 100644 --- a/commands/exec/index.js +++ b/commands/exec/index.js @@ -1,5 +1,7 @@ "use strict"; +const os = require("os"); + const ChildProcessUtilities = require("@lerna/child-process"); const Command = require("@lerna/command"); const batchPackages = require("@lerna/batch-packages"); @@ -85,7 +87,18 @@ class ExecCommand extends Command { /* istanbul ignore else */ if (results.some(result => result.failed)) { // propagate "highest" error code, it's probably the most useful - const codes = results.filter(result => result.failed).map(result => result.code); + const codes = results + .filter(result => result.failed) + .map(result => { + switch (typeof result.code) { + case "number": + return result.code; + case "string": + return os.constants.errno[result.code]; + default: + throw new TypeError("Received unexpected exit code value"); + } + }); const exitCode = Math.max(...codes, 1); this.logger.error("", "Received non-zero exit code %d during execution", exitCode); diff --git a/integration/lerna-exec.test.js b/integration/lerna-exec.test.js index 81e3be1c8a..53b6b67416 100644 --- a/integration/lerna-exec.test.js +++ b/integration/lerna-exec.test.js @@ -175,4 +175,17 @@ success! expect.hasAssertions(); }); + + test("string node error code is not swallowed", async () => { + const cwd = await initFixture("lerna-exec"); + const args = ["exec", "--no-bail", "--concurrency=1", "--", "thing-that-is-missing"]; + + try { + await cliRunner(cwd)(...args); + } catch (err) { + expect(err.code).toBeGreaterThan(0); + } + + expect.hasAssertions(); + }); });