diff --git a/README.md b/README.md index 9b116b67..7c726d8b 100644 --- a/README.md +++ b/README.md @@ -125,10 +125,12 @@ General "|" [default: ","] -r, --raw Output only raw output of processes, disables prettifying and concurrently coloring. [boolean] - -s, --success Return exit code of zero or one based on the success or - failure of the "first" child to terminate, the "last - child", or succeed only if "all" child processes succeed. - [choices: "first", "last", "all"] [default: "all"] + -s, --success Return exit code of zero or one based on the success or failure + of the "first" child to terminate, the "last child", "all-but- + first" child success, or succeeed only if "all" child processes + succeed + [choices: "first", "last", "all-but-first", "all"] + [default: "all"] --no-color Disables colors from logging [boolean] Prefix styling diff --git a/bin/concurrently.js b/bin/concurrently.js index 6c558706..deb815b8 100755 --- a/bin/concurrently.js +++ b/bin/concurrently.js @@ -37,9 +37,10 @@ const args = yargs alias: 'success', describe: 'Return exit code of zero or one based on the success or failure ' + - 'of the "first" child to terminate, the "last child", or succeed ' + - 'only if "all" child processes succeed.', - choices: ['first', 'last', 'all'], + 'of the "first" child to terminate, the "last child", all but ' + + 'the first child success, or succeeed only if "all" child ' + + 'processes succeed.', + choices: ['first', 'last', 'all-but-first', 'all'], default: defaults.success }, 'r': { diff --git a/src/completion-listener.js b/src/completion-listener.js index 791a49aa..a5158413 100644 --- a/src/completion-listener.js +++ b/src/completion-listener.js @@ -16,6 +16,10 @@ module.exports = class CompletionListener { case 'last': return exitCodes[exitCodes.length - 1] === 0; + case 'all-but-first': + const [, ...allButFirst] = exitCodes; + return allButFirst.every(code => code === 0); + default: return exitCodes.every(exitCode => exitCode === 0); /* eslint-enable indent */ diff --git a/src/completion-listener.spec.js b/src/completion-listener.spec.js index 5e54e8b7..63078b96 100644 --- a/src/completion-listener.spec.js +++ b/src/completion-listener.spec.js @@ -86,3 +86,33 @@ describe('with success condition set to last', () => { return expect(result).rejects.toEqual([{ exitCode: 0 }, { exitCode: 1 }]); }); }); + +describe('with success condition set to all-but-first', () => { + beforeEach(() => { + commands.push(createFakeCommand('oof')); + }); + + it('succeeds if all but first process to exit has code 0', () => { + const result = createController('all-but-first').listen(commands); + + commands[0].close.next({ exitCode: 1 }); + commands[1].close.next({ exitCode: 0 }); + commands[2].close.next({ exitCode: 0 }); + + scheduler.flush(); + + return expect(result).resolves.toEqual([{ exitCode: 1 }, { exitCode: 0 }, { exitCode: 0 }]); + }); + + it('fails if last process to exit has non-0 code', () => { + const result = createController('first').listen(commands); + + commands[0].close.next({ exitCode: 1 }); + commands[1].close.next({ exitCode: 0 }); + commands[2].close.next({ exitCode: 1 }); + + scheduler.flush(); + + return expect(result).rejects.toEqual([{ exitCode: 1 }, { exitCode: 0 }, { exitCode: 1 }]); + }); +});