@dotcom-tool-kit/parallel 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.toolkitrc.yml +4 -0
- package/lib/tasks/parallel.d.ts +22 -0
- package/lib/tasks/parallel.d.ts.map +1 -0
- package/lib/tasks/parallel.js +100 -0
- package/package.json +36 -0
- package/readme.md +65 -0
package/.toolkitrc.yml
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Task, TaskRunContext } from '@dotcom-tool-kit/base';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
declare const ParallelSchema: z.ZodObject<{
|
|
4
|
+
tasks: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>, "many">;
|
|
5
|
+
onError: z.ZodDefault<z.ZodUnion<[z.ZodLiteral<"stop-all">, z.ZodLiteral<"wait-for-others">]>>;
|
|
6
|
+
}, "strip", z.ZodTypeAny, {
|
|
7
|
+
tasks: Record<string, Record<string, unknown>>[];
|
|
8
|
+
onError: "stop-all" | "wait-for-others";
|
|
9
|
+
}, {
|
|
10
|
+
tasks: Record<string, Record<string, unknown>>[];
|
|
11
|
+
onError?: "stop-all" | "wait-for-others" | undefined;
|
|
12
|
+
}>;
|
|
13
|
+
export { ParallelSchema as schema };
|
|
14
|
+
export default class Parallel extends Task<{
|
|
15
|
+
task: typeof ParallelSchema;
|
|
16
|
+
}> {
|
|
17
|
+
taskInstances: Task<any>[];
|
|
18
|
+
run(context: TaskRunContext): Promise<void>;
|
|
19
|
+
stop(): Promise<void>;
|
|
20
|
+
assertUnreachable(label: string, value: never): asserts value is never;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=parallel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parallel.d.ts","sourceRoot":"","sources":["../../src/tasks/parallel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAE5D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,QAAA,MAAM,cAAc;;;;;;;;;EAsClB,CAAA;AAEF,OAAO,EAAE,cAAc,IAAI,MAAM,EAAE,CAAA;AAEnC,MAAM,CAAC,OAAO,OAAO,QAAS,SAAQ,IAAI,CAAC;IAAE,IAAI,EAAE,OAAO,cAAc,CAAA;CAAE,CAAC;IACzE,aAAa,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAK;IAEzB,GAAG,CAAC,OAAO,EAAE,cAAc;IAsD3B,IAAI;IAWV,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK;CAKvE"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.schema = void 0;
|
|
4
|
+
const base_1 = require("@dotcom-tool-kit/base");
|
|
5
|
+
const logger_1 = require("@dotcom-tool-kit/logger");
|
|
6
|
+
const zod_1 = require("zod");
|
|
7
|
+
const tasks_1 = require("dotcom-tool-kit/lib/tasks");
|
|
8
|
+
const error_1 = require("@dotcom-tool-kit/error");
|
|
9
|
+
const ParallelSchema = zod_1.z.object({
|
|
10
|
+
tasks: zod_1.z.array(zod_1.z.record(zod_1.z.record(zod_1.z.unknown()))),
|
|
11
|
+
onError: zod_1.z.union([zod_1.z.literal('stop-all'), zod_1.z.literal('wait-for-others')]).default('wait-for-others')
|
|
12
|
+
}).describe(`Run Tool Kit tasks in parallel
|
|
13
|
+
|
|
14
|
+
### Task options
|
|
15
|
+
|
|
16
|
+
#### \`tasks\`
|
|
17
|
+
|
|
18
|
+
An array listing the tasks to run in parallel, and the options to run each task with. Each element in the array is an object with a single key and value; the key is the name of the task to run, and the value is the options object for that task. Other tasks' options are documented in their plugin's readme.
|
|
19
|
+
|
|
20
|
+
##### Example
|
|
21
|
+
|
|
22
|
+
~~~yaml
|
|
23
|
+
commands:
|
|
24
|
+
run:local:
|
|
25
|
+
- Parallel:
|
|
26
|
+
tasks:
|
|
27
|
+
- Node:
|
|
28
|
+
entry: server/index.js
|
|
29
|
+
- Webpack:
|
|
30
|
+
watch: true
|
|
31
|
+
~~~
|
|
32
|
+
|
|
33
|
+
#### \`onError\`
|
|
34
|
+
|
|
35
|
+
_optional_
|
|
36
|
+
|
|
37
|
+
| Value | Description |
|
|
38
|
+
|-|-|
|
|
39
|
+
| \`'wait-for-others'\` (default) | If any task errors, wait for the other tasks to complete, and print all the errors at the end. |
|
|
40
|
+
| \`'stop-all'\` | If any task errors, immediately stop the other tasks, and print the error. |
|
|
41
|
+
|
|
42
|
+
For long-running tasks, e.g. a Node server and Webpack in \`watch\` mode, it's possible for one task to error, but its error logging to be buried by the other tasks' output, meaning you might have missed an error and aren't aware that not everything you expect to be running is still running. In these cases, set \`onError: stop-all\`; Tool Kit will exit every \`Parallel\` task if one of them errors, so you're always in a consistent state and don't miss any errors.
|
|
43
|
+
|
|
44
|
+
If you're using \`Parallel\` to run shorter tasks in parallel as an optimisation, keep this as the default \`wait-for-others\` so every task runs to completion and Tool Kit can show the final results of all the tasks.
|
|
45
|
+
|
|
46
|
+
<!-- hide autogenerated schema docs -->
|
|
47
|
+
`);
|
|
48
|
+
exports.schema = ParallelSchema;
|
|
49
|
+
class Parallel extends base_1.Task {
|
|
50
|
+
taskInstances = [];
|
|
51
|
+
async run(context) {
|
|
52
|
+
const tasks = this.options.tasks.flatMap((entry) => Object.entries(entry).map(([task, options]) => ({ task, options, plugin: this.plugin })));
|
|
53
|
+
this.logger.info(`running tasks in parallel:
|
|
54
|
+
${tasks
|
|
55
|
+
.map((task) => ` - ${logger_1.styles.task(task.task)} ${logger_1.styles.dim(`(with options ${logger_1.styles.code(JSON.stringify(task.options))})`)}`)
|
|
56
|
+
.join('\n')}
|
|
57
|
+
`);
|
|
58
|
+
this.taskInstances = (await (0, tasks_1.loadTasks)(this.logger, tasks, context.config)).unwrap('tasks are invalid!');
|
|
59
|
+
switch (this.options.onError) {
|
|
60
|
+
case 'stop-all': {
|
|
61
|
+
try {
|
|
62
|
+
await Promise.all(this.taskInstances.map((task) => task.run(context)));
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
this.stop();
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
case 'wait-for-others': {
|
|
71
|
+
const errors = [];
|
|
72
|
+
await Promise.all(this.taskInstances.map((task) => task.run(context).catch((error) => {
|
|
73
|
+
errors.push({
|
|
74
|
+
task: task.id,
|
|
75
|
+
error
|
|
76
|
+
});
|
|
77
|
+
})));
|
|
78
|
+
if (errors.length > 0) {
|
|
79
|
+
(0, tasks_1.handleTaskErrors)(errors, context.command);
|
|
80
|
+
}
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
default: {
|
|
84
|
+
this.assertUnreachable('Parallel.options.onError', this.options.onError);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
async stop() {
|
|
89
|
+
await Promise.all(this.taskInstances.map((task) => task.stop().catch((error) => {
|
|
90
|
+
this.logger.warn(`error stopping ${logger_1.styles.task(task.id)}:
|
|
91
|
+
${error.message}`);
|
|
92
|
+
})));
|
|
93
|
+
}
|
|
94
|
+
assertUnreachable(label, value) {
|
|
95
|
+
const error = new error_1.ToolKitError(`Unexpected value for ${label}, received ${value}`);
|
|
96
|
+
error.details = 'This should never happen! Talk to #cp-platforms-team, something weird af is going on';
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
exports.default = Parallel;
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dotcom-tool-kit/parallel",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "lib",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [],
|
|
10
|
+
"author": "FT.com Platforms Team <platforms-team.customer-products@ft.com>",
|
|
11
|
+
"license": "ISC",
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "https://github.com/financial-times/dotcom-tool-kit.git",
|
|
15
|
+
"directory": "plugins/parallel"
|
|
16
|
+
},
|
|
17
|
+
"bugs": "https://github.com/financial-times/dotcom-tool-kit/issues",
|
|
18
|
+
"homepage": "https://github.com/financial-times/dotcom-tool-kit/tree/main/plugins/parallel",
|
|
19
|
+
"files": [
|
|
20
|
+
"/lib",
|
|
21
|
+
".toolkitrc.yml"
|
|
22
|
+
],
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": "20.x || 22.x"
|
|
25
|
+
},
|
|
26
|
+
"volta": {
|
|
27
|
+
"extends": "../../package.json"
|
|
28
|
+
},
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"dotcom-tool-kit": "^4.8.1"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@dotcom-tool-kit/base": "^1.3.0",
|
|
34
|
+
"zod": "^3.25.67"
|
|
35
|
+
}
|
|
36
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# @dotcom-tool-kit/parallel
|
|
2
|
+
|
|
3
|
+
This plugin allows you to run Tool Kit tasks in parallel. By default, Tool Kit tasks run sequentially in the order they are specified in a command.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Install `@dotcom-tool-kit/parallel` as a `devDependency` in your app:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install --save-dev @dotcom-tool-kit/parallel
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Add the plugin to your [Tool Kit configuration](https://github.com/financial-times/dotcom-tool-kit/blob/main/readme.md#configuration):
|
|
14
|
+
|
|
15
|
+
```yaml
|
|
16
|
+
plugins:
|
|
17
|
+
- '@dotcom-tool-kit/parallel'
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
To run tasks in parallel, pass them in as the `tasks` option to the [`Parallel` task](#parallel).
|
|
23
|
+
|
|
24
|
+
<!-- begin autogenerated docs -->
|
|
25
|
+
## Tasks
|
|
26
|
+
|
|
27
|
+
### `Parallel`
|
|
28
|
+
|
|
29
|
+
Run Tool Kit tasks in parallel
|
|
30
|
+
|
|
31
|
+
#### Task options
|
|
32
|
+
|
|
33
|
+
##### `tasks`
|
|
34
|
+
|
|
35
|
+
An array listing the tasks to run in parallel, and the options to run each task with. Each element in the array is an object with a single key and value; the key is the name of the task to run, and the value is the options object for that task. Other tasks' options are documented in their plugin's readme.
|
|
36
|
+
|
|
37
|
+
###### Example
|
|
38
|
+
|
|
39
|
+
~~~yaml
|
|
40
|
+
commands:
|
|
41
|
+
run:local:
|
|
42
|
+
- Parallel:
|
|
43
|
+
tasks:
|
|
44
|
+
- Node:
|
|
45
|
+
entry: server/index.js
|
|
46
|
+
- Webpack:
|
|
47
|
+
watch: true
|
|
48
|
+
~~~
|
|
49
|
+
|
|
50
|
+
##### `onError`
|
|
51
|
+
|
|
52
|
+
_optional_
|
|
53
|
+
|
|
54
|
+
| Value | Description |
|
|
55
|
+
|-|-|
|
|
56
|
+
| `'wait-for-others'` (default) | If any task errors, wait for the other tasks to complete, and print all the errors at the end. |
|
|
57
|
+
| `'stop-all'` | If any task errors, immediately stop the other tasks, and print the error. |
|
|
58
|
+
|
|
59
|
+
For long-running tasks, e.g. a Node server and Webpack in `watch` mode, it's possible for one task to error, but its error logging to be buried by the other tasks' output, meaning you might have missed an error and aren't aware that not everything you expect to be running is still running. In these cases, set `onError: stop-all`; Tool Kit will exit every `Parallel` task if one of them errors, so you're always in a consistent state and don't miss any errors.
|
|
60
|
+
|
|
61
|
+
If you're using `Parallel` to run shorter tasks in parallel as an optimisation, keep this as the default `wait-for-others` so every task runs to completion and Tool Kit can show the final results of all the tasks.
|
|
62
|
+
|
|
63
|
+
<!-- hide autogenerated schema docs -->
|
|
64
|
+
|
|
65
|
+
<!-- end autogenerated docs -->
|