Skip to content

Commit 0a93527

Browse files
committed
Update: --continue-on-error option (fixes #34)
1 parent 4837ae3 commit 0a93527

File tree

8 files changed

+171
-22
lines changed

8 files changed

+171
-22
lines changed

README.md

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,30 @@ npm install npm-run-all
3333
## Usage
3434

3535
```
36-
Usage: npm-run-all [OPTIONS] [...tasks]
36+
Usage: npm-run-all [...tasks] [OPTIONS]
3737
3838
Run specified tasks.
3939
4040
Options:
4141
-h, --help Print this text.
42-
-p, --parallel [...tasks] Run a group of tasks in parallel.
43-
-s, --sequential [...tasks] Run a group of tasks in sequencial.
44-
--serial [...tasks] '--serial' is a synonym of '--sequential'.
4542
-v, --version Print version number.
43+
44+
-c, --continue-on-error Set the flag to ignore errors to the current
45+
group of tasks.
4646
--silent Set "silent" to the log level of npm.
47+
48+
-p, --parallel [...tasks] Run a group of tasks in parallel.
49+
e.g. 'npm-run-all -p foo bar' is similar to
50+
'npm run foo & npm run bar'.
51+
-P [...tasks] Run a group of tasks in parallel as ignoring
52+
errors. This is shorthand of '-p -c [...tasks]'.
53+
54+
-s, --sequential [...tasks] Run a group of tasks in sequential.
55+
--serial [...tasks] '--serial' is a synonym of '--sequential'.
56+
e.g. 'npm-run-all -s foo bar' is similar to
57+
'npm run foo && npm run bar'.
58+
-S [...tasks] Run a group of tasks in sequential as ignoring
59+
errors. This is shorthand of '-s -c [...tasks]'.
4760
```
4861

4962
### Run tasks sequentially / serially
@@ -123,6 +136,25 @@ If we use a globstar `**`, runs both sub tasks and sub-sub tasks.
123136
This matching rule is similar to [glob](https://www.npmjs.com/package/glob#glob-primer).
124137
The Difference is one -- the separator is `:`, instead of `/`.
125138

139+
### Continue on error
140+
141+
We can use `--continue-on-error` option to ignore errors.
142+
143+
```
144+
npm-run-all --sequential --continue-on-error foo bar
145+
npm-run-all --parallel --continue-on-error foo bar
146+
```
147+
148+
`npm-run-all` stops subsequence when a task exited with non-zero code by default.
149+
But when `--continue-on-error` was specified, `npm-run-all` continues subsequence on error.
150+
151+
There are shorthands.
152+
153+
```
154+
npm-run-all -S foo bar
155+
npm-run-all -P foo bar
156+
```
157+
126158
## Node API
127159

128160
```
@@ -142,6 +174,9 @@ Run npm-scripts.
142174
- **options.parallel** `boolean` --
143175
A flag to run tasks in parallel.
144176
Default is `false`.
177+
- **options.continueOnError** `boolean` --
178+
A flag to ignore errors.
179+
Default is `false`.
145180
- **options.stdin** `stream.Readable|null` --
146181
A readable stream to send to the stdin of npm-scripts.
147182
Default is nothing.

src/bin/help.js

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,31 @@
1313
*/
1414
export default function printHelp(output) {
1515
output.write(`
16-
Usage: npm-run-all [OPTIONS] [...tasks]
16+
Usage: npm-run-all [...tasks] [OPTIONS]
1717
1818
Run specified tasks.
1919
2020
Options:
2121
-h, --help Print this text.
22-
-p, --parallel [...tasks] Run a group of tasks in parallel.
23-
-s, --sequential [...tasks] Run a group of tasks in sequencial.
24-
--serial [...tasks] '--serial' is a synonym of '--sequential'.
2522
-v, --version Print version number.
23+
24+
-c, --continue-on-error Set the flag to ignore errors to the current
25+
group of tasks.
2626
--silent Set "silent" to the log level of npm.
2727
28+
-p, --parallel [...tasks] Run a group of tasks in parallel.
29+
e.g. 'npm-run-all -p foo bar' is similar to
30+
'npm run foo & npm run bar'.
31+
-P [...tasks] Run a group of tasks in parallel as ignoring
32+
errors. This is shorthand of '-p -c [...tasks]'.
33+
34+
-s, --sequential [...tasks] Run a group of tasks in sequential.
35+
--serial [...tasks] '--serial' is a synonym of '--sequential'.
36+
e.g. 'npm-run-all -s foo bar' is similar to
37+
'npm run foo && npm run bar'.
38+
-S [...tasks] Run a group of tasks in sequential as ignoring
39+
errors. This is shorthand of '-s -c [...tasks]'.
40+
2841
See Also:
2942
https://github.com/mysticatea/npm-run-all#readme
3043
`);

src/bin/main.js

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,27 +51,51 @@ function createPackageConfig() {
5151
* Parses arguments.
5252
*
5353
* @param {string[]} args - Arguments to parse.
54-
* @returns {{parallel: boolean, patterns: string[], packageConfig: object}[]} A running plan.
54+
* @returns {{
55+
* groups: {
56+
* parallel: boolean,
57+
* continueOnError: boolean,
58+
* patterns: string[]
59+
* }[],
60+
* packageConfig: object
61+
* }} A running plan.
5562
*/
5663
function parse(args) {
5764
const packageConfig = createPackageConfig();
58-
const queue = [{parallel: false, patterns: [], packageConfig}];
65+
const groups = [{
66+
parallel: false,
67+
continueOnError: false,
68+
patterns: []
69+
}];
5970

6071
for (let i = 0; i < args.length; ++i) {
6172
const arg = args[i];
6273

6374
switch (arg) {
75+
case "-S":
6476
case "-s":
6577
case "--sequential":
6678
case "--serial":
67-
if (queue[queue.length - 1].parallel) {
68-
queue.push({parallel: false, patterns: [], packageConfig});
69-
}
79+
groups.push({
80+
parallel: false,
81+
continueOnError: arg === "-S",
82+
patterns: []
83+
});
7084
break;
7185

86+
case "-P":
7287
case "-p":
7388
case "--parallel":
74-
queue.push({parallel: true, patterns: [], packageConfig});
89+
groups.push({
90+
parallel: true,
91+
continueOnError: arg === "-P",
92+
patterns: []
93+
});
94+
break;
95+
96+
case "-c":
97+
case "--continue-on-error":
98+
groups[groups.length - 1].continueOnError = true;
7599
break;
76100

77101
case "--silent":
@@ -92,14 +116,14 @@ function parse(args) {
92116
throw new Error(`Invalid Option: ${arg}`);
93117
}
94118
else {
95-
queue[queue.length - 1].patterns.push(arg);
119+
groups[groups.length - 1].patterns.push(arg);
96120
}
97121
break;
98122
}
99123
}
100124
}
101125

102-
return queue;
126+
return {groups, packageConfig};
103127
}
104128

105129
/**
@@ -118,9 +142,10 @@ export default function npmRunAll(args, stdout, stderr) {
118142
args.indexOf("--silent") !== -1 ||
119143
process.env.npm_config_loglevel === "silent"
120144
);
145+
const {groups, packageConfig} = parse(args);
121146

122-
return parse(args).reduce(
123-
(prev, {patterns, parallel, packageConfig}) => {
147+
return groups.reduce(
148+
(prev, {patterns, parallel, continueOnError}) => {
124149
if (patterns.length === 0) {
125150
return prev;
126151
}
@@ -131,6 +156,7 @@ export default function npmRunAll(args, stdout, stderr) {
131156
stderr,
132157
stdin,
133158
parallel,
159+
continueOnError,
134160
packageConfig,
135161
silent
136162
}

src/lib/npm-run-all.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ function toOverwriteOptions(config) {
8787
* @param {boolean} options.silent -
8888
* The flag to set `silent` to the log level of npm.
8989
* Default is `false`.
90+
* @param {boolean} options.continueOnError -
91+
* The flag to ignore errors.
92+
* Default is `false`.
9093
* @returns {Promise}
9194
* A promise object which becomes fullfilled when all npm-scripts are completed.
9295
*/
@@ -99,7 +102,8 @@ export default function npmRunAll(
99102
stderr = null,
100103
taskList = null,
101104
packageConfig = null,
102-
silent = false
105+
silent = false,
106+
continueOnError = false
103107
} = {}
104108
) {
105109
try {
@@ -121,7 +125,7 @@ export default function npmRunAll(
121125

122126
const tasks = matchTasks(taskList || readTasks(), patterns);
123127
const runTasks = parallel ? runTasksInParallel : runTasksInSequencial;
124-
return runTasks(tasks, stdin, stdout, stderr, prefixOptions);
128+
return runTasks(tasks, stdin, stdout, stderr, prefixOptions, continueOnError);
125129
}
126130
catch (err) {
127131
return Promise.reject(new Error(err.message));

src/lib/run-tasks-in-parallel.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,20 @@ import runTask from "./run-task";
2828
* Otherwise, makes a pipe.
2929
* @param {string[]} prefixOptions -
3030
* An array of options which are inserted before the task name.
31+
* @param {boolean} continueOnError -
32+
* The flag to ignore errors.
3133
* @returns {Promise}
3234
* A promise object which becomes fullfilled when all npm-scripts are completed.
3335
* @private
3436
*/
35-
export default function runTasksInParallel(tasks, stdin, stdout, stderr, prefixOptions) {
37+
export default function runTasksInParallel(tasks, stdin, stdout, stderr, prefixOptions, continueOnError) {
3638
// When one of tasks exited with non-zero, abort all tasks.
3739
// And wait for all tasks exit.
3840
let nonZeroExited = null;
3941
const taskPromises = tasks.map(task => runTask(task, stdin, stdout, stderr, prefixOptions));
42+
if (continueOnError) {
43+
return Promise.all(taskPromises);
44+
}
4045
const parallelPromise = Promise.all(taskPromises.map(p =>
4146
p.then(item => {
4247
if (nonZeroExited == null && item.code) {

src/lib/run-tasks-in-sequencial.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,19 @@ function rejectIfNonZeroExit(result) {
4242
* Otherwise, makes a pipe.
4343
* @param {string[]} prefixOptions -
4444
* An array of options which are inserted before the task name.
45+
* @param {boolean} continueOnError -
46+
* The flag to ignore errors.
4547
* @returns {Promise}
4648
* A promise object which becomes fullfilled when all npm-scripts are completed.
4749
* @private
4850
*/
49-
export default function runTasksInSequencial(tasks, stdin, stdout, stderr, prefixOptions) {
51+
export default function runTasksInSequencial(tasks, stdin, stdout, stderr, prefixOptions, continueOnError) {
52+
if (continueOnError) {
53+
return tasks.reduce(
54+
(prev, task) => prev.then(() => runTask(task, stdin, stdout, stderr, prefixOptions)),
55+
START_PROMISE
56+
);
57+
}
5058
return tasks.reduce(
5159
(prev, task) => prev.then(result => {
5260
rejectIfNonZeroExit(result);

test/parallel.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,4 +102,39 @@ describe("[parallel] npm-run-all", () => {
102102
assert(result() == null || result() === "a");
103103
})
104104
);
105+
106+
describe("should continue on error when --continue-on-error option was specified:", () => {
107+
it("lib version", () =>
108+
runAll(["test-task:append a", "test-task:error", "test-task:append b"], {parallel: true, continueOnError: true})
109+
.then(() => {
110+
assert(
111+
result() === "abab" ||
112+
result() === "baba" ||
113+
result() === "abba" ||
114+
result() === "baab");
115+
})
116+
);
117+
118+
it("command version", () =>
119+
command(["--parallel", "test-task:append a", "test-task:error", "test-task:append b", "--continue-on-error"])
120+
.then(() => {
121+
assert(
122+
result() === "abab" ||
123+
result() === "baba" ||
124+
result() === "abba" ||
125+
result() === "baab");
126+
})
127+
);
128+
129+
it("command version (-P shorthand)", () =>
130+
command(["-P", "test-task:append a", "test-task:error", "test-task:append b"])
131+
.then(() => {
132+
assert(
133+
result() === "abab" ||
134+
result() === "baba" ||
135+
result() === "abba" ||
136+
result() === "baab");
137+
})
138+
);
139+
});
105140
});

test/sequential.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,27 @@ describe("[sequencial] npm-run-all", () => {
6969
assert(result() == null || result() === "a");
7070
})
7171
);
72+
73+
describe("should continue on error when --continue-on-error option was specified:", () => {
74+
it("lib version", () =>
75+
runAll(["test-task:append a", "test-task:error", "test-task:append b"], {continueOnError: true})
76+
.then(() => {
77+
assert(result() === "aabb");
78+
})
79+
);
80+
81+
it("command version", () =>
82+
command(["test-task:append a", "test-task:error", "test-task:append b", "--continue-on-error"])
83+
.then(() => {
84+
assert(result() === "aabb");
85+
})
86+
);
87+
88+
it("command version (-S shorthand)", () =>
89+
command(["-S", "test-task:append a", "test-task:error", "test-task:append b"])
90+
.then(() => {
91+
assert(result() === "aabb");
92+
})
93+
);
94+
});
7295
});

0 commit comments

Comments
 (0)