nx 20.5.0-canary.20250201-05e0679 → 21.0.0-beta.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/package.json +12 -11
- package/plugins/package-json.js +2 -1
- package/schemas/nx-schema.json +7 -0
- package/src/command-line/graph/graph.js +2 -0
- package/src/commands-runner/get-command-projects.js +17 -2
- package/src/config/schema-utils.js +4 -4
- package/src/config/task-graph.d.ts +5 -0
- package/src/config/workspace-json-project-json.d.ts +6 -0
- package/src/executors/run-commands/run-commands.impl.d.ts +16 -13
- package/src/executors/run-commands/run-commands.impl.js +24 -263
- package/src/executors/run-commands/running-tasks.d.ts +38 -0
- package/src/executors/run-commands/running-tasks.js +349 -0
- package/src/native/index.d.ts +1 -0
- package/src/native/nx.wasm32-wasi.wasm +0 -0
- package/src/plugins/js/project-graph/build-dependencies/target-project-locator.d.ts +2 -1
- package/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +11 -3
- package/src/plugins/js/utils/packages.d.ts +6 -1
- package/src/plugins/js/utils/packages.js +59 -12
- package/src/plugins/package-json/create-nodes.d.ts +3 -3
- package/src/plugins/package-json/create-nodes.js +8 -12
- package/src/project-graph/file-utils.js +2 -1
- package/src/project-graph/plugins/resolve-plugin.js +11 -2
- package/src/tasks-runner/create-task-graph.d.ts +3 -0
- package/src/tasks-runner/create-task-graph.js +36 -5
- package/src/tasks-runner/forked-process-task-runner.d.ts +6 -12
- package/src/tasks-runner/forked-process-task-runner.js +110 -263
- package/src/tasks-runner/init-tasks-runner.js +4 -0
- package/src/tasks-runner/pseudo-terminal.d.ts +7 -1
- package/src/tasks-runner/pseudo-terminal.js +26 -12
- package/src/tasks-runner/running-tasks/batch-process.d.ts +14 -0
- package/src/tasks-runner/running-tasks/batch-process.js +70 -0
- package/src/tasks-runner/running-tasks/node-child-process.d.ts +36 -0
- package/src/tasks-runner/running-tasks/node-child-process.js +184 -0
- package/src/tasks-runner/running-tasks/noop-child-process.d.ts +15 -0
- package/src/tasks-runner/running-tasks/noop-child-process.js +19 -0
- package/src/tasks-runner/running-tasks/running-task.d.ts +8 -0
- package/src/tasks-runner/running-tasks/running-task.js +6 -0
- package/src/tasks-runner/task-orchestrator.d.ts +7 -1
- package/src/tasks-runner/task-orchestrator.js +137 -82
- package/src/tasks-runner/tasks-schedule.js +5 -1
- package/src/tasks-runner/utils.d.ts +0 -8
- package/src/tasks-runner/utils.js +12 -4
- package/src/utils/package-json.d.ts +1 -1
- package/src/utils/package-json.js +4 -2
@@ -17,6 +17,7 @@ class ProcessTasks {
|
|
17
17
|
this.seen = new Set();
|
18
18
|
this.tasks = {};
|
19
19
|
this.dependencies = {};
|
20
|
+
this.continuousDependencies = {};
|
20
21
|
const allTargetNames = new Set();
|
21
22
|
for (const projectName in projectGraph.nodes) {
|
22
23
|
const project = projectGraph.nodes[projectName];
|
@@ -36,6 +37,7 @@ class ProcessTasks {
|
|
36
37
|
const task = this.createTask(id, project, target, resolvedConfiguration, overrides);
|
37
38
|
this.tasks[task.id] = task;
|
38
39
|
this.dependencies[task.id] = [];
|
40
|
+
this.continuousDependencies[task.id] = [];
|
39
41
|
}
|
40
42
|
}
|
41
43
|
}
|
@@ -50,11 +52,15 @@ class ProcessTasks {
|
|
50
52
|
if (!initialTasks[t]) {
|
51
53
|
delete this.tasks[t];
|
52
54
|
delete this.dependencies[t];
|
55
|
+
delete this.continuousDependencies[t];
|
53
56
|
}
|
54
57
|
}
|
55
58
|
for (let d of Object.keys(this.dependencies)) {
|
56
59
|
this.dependencies[d] = this.dependencies[d].filter((dd) => !!initialTasks[dd]);
|
57
60
|
}
|
61
|
+
for (let d of Object.keys(this.continuousDependencies)) {
|
62
|
+
this.continuousDependencies[d] = this.continuousDependencies[d].filter((dd) => !!initialTasks[dd]);
|
63
|
+
}
|
58
64
|
}
|
59
65
|
filterDummyTasks(this.dependencies);
|
60
66
|
for (const taskId of Object.keys(this.dependencies)) {
|
@@ -64,7 +70,16 @@ class ProcessTasks {
|
|
64
70
|
];
|
65
71
|
}
|
66
72
|
}
|
67
|
-
|
73
|
+
filterDummyTasks(this.continuousDependencies);
|
74
|
+
for (const taskId of Object.keys(this.continuousDependencies)) {
|
75
|
+
if (this.continuousDependencies[taskId].length > 0) {
|
76
|
+
this.continuousDependencies[taskId] = [
|
77
|
+
...new Set(this.continuousDependencies[taskId].filter((d) => d !== taskId)).values(),
|
78
|
+
];
|
79
|
+
}
|
80
|
+
}
|
81
|
+
return Object.keys(this.tasks).filter((d) => this.dependencies[d].length === 0 &&
|
82
|
+
this.continuousDependencies[d].length === 0);
|
68
83
|
}
|
69
84
|
processTask(task, projectUsedToDeriveDependencies, configuration, overrides) {
|
70
85
|
const seenKey = `${task.id}-${projectUsedToDeriveDependencies}`;
|
@@ -106,15 +121,21 @@ class ProcessTasks {
|
|
106
121
|
if ((0, project_graph_utils_1.projectHasTarget)(selfProject, dependencyConfig.target)) {
|
107
122
|
const resolvedConfiguration = this.resolveConfiguration(selfProject, dependencyConfig.target, configuration);
|
108
123
|
const selfTaskId = this.getId(selfProject.name, dependencyConfig.target, resolvedConfiguration);
|
109
|
-
if (task.id !== selfTaskId) {
|
110
|
-
this.dependencies[task.id].push(selfTaskId);
|
111
|
-
}
|
112
124
|
if (!this.tasks[selfTaskId]) {
|
113
125
|
const newTask = this.createTask(selfTaskId, selfProject, dependencyConfig.target, resolvedConfiguration, taskOverrides);
|
114
126
|
this.tasks[selfTaskId] = newTask;
|
115
127
|
this.dependencies[selfTaskId] = [];
|
128
|
+
this.continuousDependencies[selfTaskId] = [];
|
116
129
|
this.processTask(newTask, newTask.target.project, configuration, overrides);
|
117
130
|
}
|
131
|
+
if (task.id !== selfTaskId) {
|
132
|
+
if (this.tasks[selfTaskId].continuous) {
|
133
|
+
this.continuousDependencies[task.id].push(selfTaskId);
|
134
|
+
}
|
135
|
+
else {
|
136
|
+
this.dependencies[task.id].push(selfTaskId);
|
137
|
+
}
|
138
|
+
}
|
118
139
|
}
|
119
140
|
}
|
120
141
|
processTasksForDependencies(projectUsedToDeriveDependencies, dependencyConfig, configuration, task, taskOverrides, overrides) {
|
@@ -129,13 +150,20 @@ class ProcessTasks {
|
|
129
150
|
if ((0, project_graph_utils_1.projectHasTarget)(depProject, dependencyConfig.target)) {
|
130
151
|
const resolvedConfiguration = this.resolveConfiguration(depProject, dependencyConfig.target, configuration);
|
131
152
|
const depTargetId = this.getId(depProject.name, dependencyConfig.target, resolvedConfiguration);
|
153
|
+
const depTargetConfiguration = this.projectGraph.nodes[depProject.name].data.targets[dependencyConfig.target];
|
132
154
|
if (task.id !== depTargetId) {
|
133
|
-
|
155
|
+
if (depTargetConfiguration.continuous) {
|
156
|
+
this.continuousDependencies[task.id].push(depTargetId);
|
157
|
+
}
|
158
|
+
else {
|
159
|
+
this.dependencies[task.id].push(depTargetId);
|
160
|
+
}
|
134
161
|
}
|
135
162
|
if (!this.tasks[depTargetId]) {
|
136
163
|
const newTask = this.createTask(depTargetId, depProject, dependencyConfig.target, resolvedConfiguration, taskOverrides);
|
137
164
|
this.tasks[depTargetId] = newTask;
|
138
165
|
this.dependencies[depTargetId] = [];
|
166
|
+
this.continuousDependencies[depTargetId] = [];
|
139
167
|
this.processTask(newTask, newTask.target.project, configuration, overrides);
|
140
168
|
}
|
141
169
|
}
|
@@ -147,6 +175,7 @@ class ProcessTasks {
|
|
147
175
|
DUMMY_TASK_TARGET, undefined);
|
148
176
|
this.dependencies[task.id].push(dummyId);
|
149
177
|
this.dependencies[dummyId] ??= [];
|
178
|
+
this.continuousDependencies[dummyId] ??= [];
|
150
179
|
const noopTask = this.createDummyTask(dummyId, task);
|
151
180
|
this.processTask(noopTask, depProject.name, configuration, overrides);
|
152
181
|
}
|
@@ -179,6 +208,7 @@ class ProcessTasks {
|
|
179
208
|
outputs: (0, utils_1.getOutputs)(this.projectGraph.nodes, qualifiedTarget, interpolatedOverrides),
|
180
209
|
cache: project.data.targets[target].cache,
|
181
210
|
parallelism: project.data.targets[target].parallelism ?? true,
|
211
|
+
continuous: project.data.targets[target].continuous ?? false,
|
182
212
|
};
|
183
213
|
}
|
184
214
|
resolveConfiguration(project, target, configuration) {
|
@@ -204,6 +234,7 @@ function createTaskGraph(projectGraph, extraTargetDependencies, projectNames, ta
|
|
204
234
|
roots,
|
205
235
|
tasks: p.tasks,
|
206
236
|
dependencies: p.dependencies,
|
237
|
+
continuousDependencies: p.continuousDependencies,
|
207
238
|
};
|
208
239
|
}
|
209
240
|
function mapTargetDefaultsToDependencies(defaults) {
|
@@ -1,7 +1,9 @@
|
|
1
1
|
import { DefaultTasksRunnerOptions } from './default-tasks-runner';
|
2
2
|
import { Batch } from './tasks-schedule';
|
3
|
-
import { BatchResults } from './batch/batch-messages';
|
4
3
|
import { Task, TaskGraph } from '../config/task-graph';
|
4
|
+
import { PseudoTtyProcess } from './pseudo-terminal';
|
5
|
+
import { BatchProcess } from './running-tasks/batch-process';
|
6
|
+
import { RunningTask } from './running-tasks/running-task';
|
5
7
|
export declare class ForkedProcessTaskRunner {
|
6
8
|
private readonly options;
|
7
9
|
cliPath: string;
|
@@ -10,17 +12,14 @@ export declare class ForkedProcessTaskRunner {
|
|
10
12
|
private pseudoTerminal;
|
11
13
|
constructor(options: DefaultTasksRunnerOptions);
|
12
14
|
init(): Promise<void>;
|
13
|
-
forkProcessForBatch({ executorName, taskGraph: batchTaskGraph }: Batch, fullTaskGraph: TaskGraph, env: NodeJS.ProcessEnv): Promise<
|
15
|
+
forkProcessForBatch({ executorName, taskGraph: batchTaskGraph }: Batch, fullTaskGraph: TaskGraph, env: NodeJS.ProcessEnv): Promise<BatchProcess>;
|
14
16
|
forkProcessLegacy(task: Task, { temporaryOutputPath, streamOutput, pipeOutput, taskGraph, env, }: {
|
15
17
|
temporaryOutputPath: string;
|
16
18
|
streamOutput: boolean;
|
17
19
|
pipeOutput: boolean;
|
18
20
|
taskGraph: TaskGraph;
|
19
21
|
env: NodeJS.ProcessEnv;
|
20
|
-
}): Promise<
|
21
|
-
code: number;
|
22
|
-
terminalOutput: string;
|
23
|
-
}>;
|
22
|
+
}): Promise<RunningTask>;
|
24
23
|
forkProcess(task: Task, { temporaryOutputPath, streamOutput, taskGraph, env, disablePseudoTerminal, }: {
|
25
24
|
temporaryOutputPath: string;
|
26
25
|
streamOutput: boolean;
|
@@ -28,15 +27,10 @@ export declare class ForkedProcessTaskRunner {
|
|
28
27
|
taskGraph: TaskGraph;
|
29
28
|
env: NodeJS.ProcessEnv;
|
30
29
|
disablePseudoTerminal: boolean;
|
31
|
-
}): Promise<
|
32
|
-
code: number;
|
33
|
-
terminalOutput: string;
|
34
|
-
}>;
|
30
|
+
}): Promise<RunningTask | PseudoTtyProcess>;
|
35
31
|
private forkProcessWithPseudoTerminal;
|
36
|
-
private forkProcessPipeOutputCapture;
|
37
32
|
private forkProcessWithPrefixAndNotTTY;
|
38
33
|
private forkProcessDirectOutputCapture;
|
39
|
-
private readTerminalOutput;
|
40
34
|
private writeTerminalOutput;
|
41
35
|
private setupProcessEventListeners;
|
42
36
|
}
|
@@ -3,15 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ForkedProcessTaskRunner = void 0;
|
4
4
|
const fs_1 = require("fs");
|
5
5
|
const child_process_1 = require("child_process");
|
6
|
-
const chalk = require("chalk");
|
7
6
|
const output_1 = require("../utils/output");
|
8
7
|
const utils_1 = require("./utils");
|
9
8
|
const path_1 = require("path");
|
10
9
|
const batch_messages_1 = require("./batch/batch-messages");
|
11
10
|
const strip_indents_1 = require("../utils/strip-indents");
|
12
|
-
const stream_1 = require("stream");
|
13
11
|
const pseudo_terminal_1 = require("./pseudo-terminal");
|
14
12
|
const exit_codes_1 = require("../utils/exit-codes");
|
13
|
+
const node_child_process_1 = require("./running-tasks/node-child-process");
|
14
|
+
const batch_process_1 = require("./running-tasks/batch-process");
|
15
15
|
const forkScript = (0, path_1.join)(__dirname, './fork.js');
|
16
16
|
const workerPath = (0, path_1.join)(__dirname, './batch/run-batch.js');
|
17
17
|
class ForkedProcessTaskRunner {
|
@@ -31,76 +31,42 @@ class ForkedProcessTaskRunner {
|
|
31
31
|
this.setupProcessEventListeners();
|
32
32
|
}
|
33
33
|
// TODO: vsavkin delegate terminal output printing
|
34
|
-
forkProcessForBatch({ executorName, taskGraph: batchTaskGraph }, fullTaskGraph, env) {
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
success: false,
|
59
|
-
terminalOutput: '',
|
60
|
-
};
|
61
|
-
}
|
62
|
-
rej(new Error(`"${executorName}" exited unexpectedly with code: ${code}`));
|
63
|
-
}
|
64
|
-
});
|
65
|
-
p.on('message', (message) => {
|
66
|
-
switch (message.type) {
|
67
|
-
case batch_messages_1.BatchMessageType.CompleteBatchExecution: {
|
68
|
-
res(message.results);
|
69
|
-
break;
|
70
|
-
}
|
71
|
-
case batch_messages_1.BatchMessageType.RunTasks: {
|
72
|
-
break;
|
73
|
-
}
|
74
|
-
default: {
|
75
|
-
// Re-emit any non-batch messages from the task process
|
76
|
-
if (process.send) {
|
77
|
-
process.send(message);
|
78
|
-
}
|
79
|
-
}
|
80
|
-
}
|
81
|
-
});
|
82
|
-
// Start the tasks
|
83
|
-
p.send({
|
84
|
-
type: batch_messages_1.BatchMessageType.RunTasks,
|
85
|
-
executorName,
|
86
|
-
batchTaskGraph,
|
87
|
-
fullTaskGraph,
|
88
|
-
});
|
89
|
-
}
|
90
|
-
catch (e) {
|
91
|
-
rej(e);
|
92
|
-
}
|
34
|
+
async forkProcessForBatch({ executorName, taskGraph: batchTaskGraph }, fullTaskGraph, env) {
|
35
|
+
const count = Object.keys(batchTaskGraph.tasks).length;
|
36
|
+
if (count > 1) {
|
37
|
+
output_1.output.logSingleLine(`Running ${output_1.output.bold(count)} ${output_1.output.bold('tasks')} with ${output_1.output.bold(executorName)}`);
|
38
|
+
}
|
39
|
+
else {
|
40
|
+
const args = (0, utils_1.getPrintableCommandArgsForTask)(Object.values(batchTaskGraph.tasks)[0]);
|
41
|
+
output_1.output.logCommand(args.join(' '));
|
42
|
+
}
|
43
|
+
const p = (0, child_process_1.fork)(workerPath, {
|
44
|
+
stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
|
45
|
+
env,
|
46
|
+
});
|
47
|
+
const cp = new batch_process_1.BatchProcess(p, executorName);
|
48
|
+
this.processes.add(cp);
|
49
|
+
cp.onExit(() => {
|
50
|
+
this.processes.delete(cp);
|
51
|
+
});
|
52
|
+
// Start the tasks
|
53
|
+
cp.send({
|
54
|
+
type: batch_messages_1.BatchMessageType.RunTasks,
|
55
|
+
executorName,
|
56
|
+
batchTaskGraph,
|
57
|
+
fullTaskGraph,
|
93
58
|
});
|
59
|
+
return cp;
|
94
60
|
}
|
95
61
|
async forkProcessLegacy(task, { temporaryOutputPath, streamOutput, pipeOutput, taskGraph, env, }) {
|
96
62
|
return pipeOutput
|
97
|
-
?
|
63
|
+
? this.forkProcessWithPrefixAndNotTTY(task, {
|
98
64
|
temporaryOutputPath,
|
99
65
|
streamOutput,
|
100
66
|
taskGraph,
|
101
67
|
env,
|
102
68
|
})
|
103
|
-
:
|
69
|
+
: this.forkProcessDirectOutputCapture(task, {
|
104
70
|
temporaryOutputPath,
|
105
71
|
streamOutput,
|
106
72
|
taskGraph,
|
@@ -154,158 +120,96 @@ class ForkedProcessTaskRunner {
|
|
154
120
|
p.onOutput((msg) => {
|
155
121
|
terminalOutput += msg;
|
156
122
|
});
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
this.writeTerminalOutput(temporaryOutputPath, terminalOutput);
|
164
|
-
res({
|
165
|
-
code,
|
166
|
-
terminalOutput,
|
167
|
-
});
|
168
|
-
});
|
169
|
-
});
|
170
|
-
}
|
171
|
-
forkProcessPipeOutputCapture(task, { streamOutput, temporaryOutputPath, taskGraph, env, }) {
|
172
|
-
return this.forkProcessWithPrefixAndNotTTY(task, {
|
173
|
-
streamOutput,
|
174
|
-
temporaryOutputPath,
|
175
|
-
taskGraph,
|
176
|
-
env,
|
123
|
+
p.onExit((code) => {
|
124
|
+
if (code > 128) {
|
125
|
+
process.exit(code);
|
126
|
+
}
|
127
|
+
this.processes.delete(p);
|
128
|
+
this.writeTerminalOutput(temporaryOutputPath, terminalOutput);
|
177
129
|
});
|
130
|
+
return p;
|
178
131
|
}
|
179
132
|
forkProcessWithPrefixAndNotTTY(task, { streamOutput, temporaryOutputPath, taskGraph, env, }) {
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
if (process.env.NX_PREFIX_OUTPUT === 'true') {
|
206
|
-
const color = getColor(task.target.project);
|
207
|
-
const prefixText = `${task.target.project}:`;
|
208
|
-
p.stdout
|
209
|
-
.pipe(logClearLineToPrefixTransformer(color.bold(prefixText) + ' '))
|
210
|
-
.pipe(addPrefixTransformer(color.bold(prefixText)))
|
211
|
-
.pipe(process.stdout);
|
212
|
-
p.stderr
|
213
|
-
.pipe(logClearLineToPrefixTransformer(color(prefixText) + ' '))
|
214
|
-
.pipe(addPrefixTransformer(color(prefixText)))
|
215
|
-
.pipe(process.stderr);
|
216
|
-
}
|
217
|
-
else {
|
218
|
-
p.stdout.pipe(addPrefixTransformer()).pipe(process.stdout);
|
219
|
-
p.stderr.pipe(addPrefixTransformer()).pipe(process.stderr);
|
220
|
-
}
|
133
|
+
try {
|
134
|
+
const args = (0, utils_1.getPrintableCommandArgsForTask)(task);
|
135
|
+
if (streamOutput) {
|
136
|
+
output_1.output.logCommand(args.join(' '));
|
137
|
+
}
|
138
|
+
const p = (0, child_process_1.fork)(this.cliPath, {
|
139
|
+
stdio: ['inherit', 'pipe', 'pipe', 'ipc'],
|
140
|
+
env,
|
141
|
+
});
|
142
|
+
// Send message to run the executor
|
143
|
+
p.send({
|
144
|
+
targetDescription: task.target,
|
145
|
+
overrides: task.overrides,
|
146
|
+
taskGraph,
|
147
|
+
isVerbose: this.verbose,
|
148
|
+
});
|
149
|
+
const cp = new node_child_process_1.NodeChildProcessWithNonDirectOutput(p, {
|
150
|
+
streamOutput,
|
151
|
+
prefix: task.target.project,
|
152
|
+
});
|
153
|
+
this.processes.add(cp);
|
154
|
+
cp.onExit((code, terminalOutput) => {
|
155
|
+
this.processes.delete(cp);
|
156
|
+
if (!streamOutput) {
|
157
|
+
this.options.lifeCycle.printTaskTerminalOutput(task, code === 0 ? 'success' : 'failure', terminalOutput);
|
221
158
|
}
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
159
|
+
this.writeTerminalOutput(temporaryOutputPath, terminalOutput);
|
160
|
+
});
|
161
|
+
return cp;
|
162
|
+
}
|
163
|
+
catch (e) {
|
164
|
+
console.error(e);
|
165
|
+
throw e;
|
166
|
+
}
|
167
|
+
}
|
168
|
+
forkProcessDirectOutputCapture(task, { streamOutput, temporaryOutputPath, taskGraph, env, }) {
|
169
|
+
try {
|
170
|
+
const args = (0, utils_1.getPrintableCommandArgsForTask)(task);
|
171
|
+
if (streamOutput) {
|
172
|
+
output_1.output.logCommand(args.join(' '));
|
173
|
+
}
|
174
|
+
const p = (0, child_process_1.fork)(this.cliPath, {
|
175
|
+
stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
|
176
|
+
env,
|
177
|
+
});
|
178
|
+
const cp = new node_child_process_1.NodeChildProcessWithDirectOutput(p, temporaryOutputPath);
|
179
|
+
this.processes.add(cp);
|
180
|
+
// Send message to run the executor
|
181
|
+
p.send({
|
182
|
+
targetDescription: task.target,
|
183
|
+
overrides: task.overrides,
|
184
|
+
taskGraph,
|
185
|
+
isVerbose: this.verbose,
|
186
|
+
});
|
187
|
+
cp.onExit((code, signal) => {
|
188
|
+
this.processes.delete(cp);
|
189
|
+
// we didn't print any output as we were running the command
|
190
|
+
// print all the collected output
|
191
|
+
try {
|
192
|
+
const terminalOutput = cp.getTerminalOutput();
|
236
193
|
if (!streamOutput) {
|
237
194
|
this.options.lifeCycle.printTaskTerminalOutput(task, code === 0 ? 'success' : 'failure', terminalOutput);
|
238
195
|
}
|
239
|
-
this.writeTerminalOutput(temporaryOutputPath, terminalOutput);
|
240
|
-
res({ code, terminalOutput });
|
241
|
-
});
|
242
|
-
}
|
243
|
-
catch (e) {
|
244
|
-
console.error(e);
|
245
|
-
rej(e);
|
246
|
-
}
|
247
|
-
});
|
248
|
-
}
|
249
|
-
forkProcessDirectOutputCapture(task, { streamOutput, temporaryOutputPath, taskGraph, env, }) {
|
250
|
-
return new Promise((res, rej) => {
|
251
|
-
try {
|
252
|
-
const args = (0, utils_1.getPrintableCommandArgsForTask)(task);
|
253
|
-
if (streamOutput) {
|
254
|
-
output_1.output.logCommand(args.join(' '));
|
255
196
|
}
|
256
|
-
|
257
|
-
|
258
|
-
env,
|
259
|
-
});
|
260
|
-
this.processes.add(p);
|
261
|
-
// Re-emit any messages from the task process
|
262
|
-
p.on('message', (message) => {
|
263
|
-
if (process.send) {
|
264
|
-
process.send(message);
|
265
|
-
}
|
266
|
-
});
|
267
|
-
// Send message to run the executor
|
268
|
-
p.send({
|
269
|
-
targetDescription: task.target,
|
270
|
-
overrides: task.overrides,
|
271
|
-
taskGraph,
|
272
|
-
isVerbose: this.verbose,
|
273
|
-
});
|
274
|
-
p.on('exit', (code, signal) => {
|
275
|
-
if (code === null)
|
276
|
-
code = (0, exit_codes_1.signalToCode)(signal);
|
277
|
-
// we didn't print any output as we were running the command
|
278
|
-
// print all the collected output
|
279
|
-
let terminalOutput = '';
|
280
|
-
try {
|
281
|
-
terminalOutput = this.readTerminalOutput(temporaryOutputPath);
|
282
|
-
if (!streamOutput) {
|
283
|
-
this.options.lifeCycle.printTaskTerminalOutput(task, code === 0 ? 'success' : 'failure', terminalOutput);
|
284
|
-
}
|
285
|
-
}
|
286
|
-
catch (e) {
|
287
|
-
console.log((0, strip_indents_1.stripIndents) `
|
197
|
+
catch (e) {
|
198
|
+
console.log((0, strip_indents_1.stripIndents) `
|
288
199
|
Unable to print terminal output for Task "${task.id}".
|
289
200
|
Task failed with Exit Code ${code} and Signal "${signal}".
|
290
201
|
|
291
202
|
Received error message:
|
292
203
|
${e.message}
|
293
204
|
`);
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
console.error(e);
|
303
|
-
rej(e);
|
304
|
-
}
|
305
|
-
});
|
306
|
-
}
|
307
|
-
readTerminalOutput(outputPath) {
|
308
|
-
return (0, fs_1.readFileSync)(outputPath).toString();
|
205
|
+
}
|
206
|
+
});
|
207
|
+
return cp;
|
208
|
+
}
|
209
|
+
catch (e) {
|
210
|
+
console.error(e);
|
211
|
+
throw e;
|
212
|
+
}
|
309
213
|
}
|
310
214
|
writeTerminalOutput(outputPath, content) {
|
311
215
|
(0, fs_1.writeFileSync)(outputPath, content);
|
@@ -318,12 +222,11 @@ class ForkedProcessTaskRunner {
|
|
318
222
|
}
|
319
223
|
// When the nx process gets a message, it will be sent into the task's process
|
320
224
|
process.on('message', (message) => {
|
321
|
-
// this.publisher.publish(message.toString());
|
322
225
|
if (this.pseudoTerminal) {
|
323
226
|
this.pseudoTerminal.sendMessageToChildren(message);
|
324
227
|
}
|
325
228
|
this.processes.forEach((p) => {
|
326
|
-
if ('
|
229
|
+
if ('send' in p) {
|
327
230
|
p.send(message);
|
328
231
|
}
|
329
232
|
});
|
@@ -331,34 +234,26 @@ class ForkedProcessTaskRunner {
|
|
331
234
|
// Terminate any task processes on exit
|
332
235
|
process.on('exit', () => {
|
333
236
|
this.processes.forEach((p) => {
|
334
|
-
|
335
|
-
p.kill();
|
336
|
-
}
|
237
|
+
p.kill();
|
337
238
|
});
|
338
239
|
});
|
339
240
|
process.on('SIGINT', () => {
|
340
241
|
this.processes.forEach((p) => {
|
341
|
-
|
342
|
-
p.kill('SIGTERM');
|
343
|
-
}
|
242
|
+
p.kill('SIGTERM');
|
344
243
|
});
|
345
244
|
// we exit here because we don't need to write anything to cache.
|
346
245
|
process.exit((0, exit_codes_1.signalToCode)('SIGINT'));
|
347
246
|
});
|
348
247
|
process.on('SIGTERM', () => {
|
349
248
|
this.processes.forEach((p) => {
|
350
|
-
|
351
|
-
p.kill('SIGTERM');
|
352
|
-
}
|
249
|
+
p.kill('SIGTERM');
|
353
250
|
});
|
354
251
|
// no exit here because we expect child processes to terminate which
|
355
252
|
// will store results to the cache and will terminate this process
|
356
253
|
});
|
357
254
|
process.on('SIGHUP', () => {
|
358
255
|
this.processes.forEach((p) => {
|
359
|
-
|
360
|
-
p.kill('SIGTERM');
|
361
|
-
}
|
256
|
+
p.kill('SIGTERM');
|
362
257
|
});
|
363
258
|
// no exit here because we expect child processes to terminate which
|
364
259
|
// will store results to the cache and will terminate this process
|
@@ -366,51 +261,3 @@ class ForkedProcessTaskRunner {
|
|
366
261
|
}
|
367
262
|
}
|
368
263
|
exports.ForkedProcessTaskRunner = ForkedProcessTaskRunner;
|
369
|
-
const colors = [
|
370
|
-
chalk.green,
|
371
|
-
chalk.greenBright,
|
372
|
-
chalk.red,
|
373
|
-
chalk.redBright,
|
374
|
-
chalk.cyan,
|
375
|
-
chalk.cyanBright,
|
376
|
-
chalk.yellow,
|
377
|
-
chalk.yellowBright,
|
378
|
-
chalk.magenta,
|
379
|
-
chalk.magentaBright,
|
380
|
-
];
|
381
|
-
function getColor(projectName) {
|
382
|
-
let code = 0;
|
383
|
-
for (let i = 0; i < projectName.length; ++i) {
|
384
|
-
code += projectName.charCodeAt(i);
|
385
|
-
}
|
386
|
-
const colorIndex = code % colors.length;
|
387
|
-
return colors[colorIndex];
|
388
|
-
}
|
389
|
-
/**
|
390
|
-
* Prevents terminal escape sequence from clearing line prefix.
|
391
|
-
*/
|
392
|
-
function logClearLineToPrefixTransformer(prefix) {
|
393
|
-
let prevChunk = null;
|
394
|
-
return new stream_1.Transform({
|
395
|
-
transform(chunk, _encoding, callback) {
|
396
|
-
if (prevChunk && prevChunk.toString() === '\x1b[2K') {
|
397
|
-
chunk = chunk.toString().replace(/\x1b\[1G/g, (m) => m + prefix);
|
398
|
-
}
|
399
|
-
this.push(chunk);
|
400
|
-
prevChunk = chunk;
|
401
|
-
callback();
|
402
|
-
},
|
403
|
-
});
|
404
|
-
}
|
405
|
-
function addPrefixTransformer(prefix) {
|
406
|
-
const newLineSeparator = process.platform.startsWith('win') ? '\r\n' : '\n';
|
407
|
-
return new stream_1.Transform({
|
408
|
-
transform(chunk, _encoding, callback) {
|
409
|
-
const list = chunk.toString().split(/\r\n|[\n\v\f\r\x85\u2028\u2029]/g);
|
410
|
-
list
|
411
|
-
.filter(Boolean)
|
412
|
-
.forEach((m) => this.push(prefix ? prefix + ' ' + m + newLineSeparator : m + newLineSeparator));
|
413
|
-
callback();
|
414
|
-
},
|
415
|
-
});
|
416
|
-
}
|
@@ -36,6 +36,10 @@ async function initTasksRunner(nxArgs) {
|
|
36
36
|
acc[task.id] = [];
|
37
37
|
return acc;
|
38
38
|
}, {}),
|
39
|
+
continuousDependencies: opts.tasks.reduce((acc, task) => {
|
40
|
+
acc[task.id] = [];
|
41
|
+
return acc;
|
42
|
+
}, {}),
|
39
43
|
};
|
40
44
|
const taskResults = await (0, run_command_1.invokeTasksRunner)({
|
41
45
|
tasks: opts.tasks,
|
@@ -31,8 +31,14 @@ export declare class PseudoTerminal {
|
|
31
31
|
export declare class PseudoTtyProcess {
|
32
32
|
private childProcess;
|
33
33
|
isAlive: boolean;
|
34
|
-
exitCallbacks
|
34
|
+
private exitCallbacks;
|
35
|
+
private outputCallbacks;
|
36
|
+
private terminalOutput;
|
35
37
|
constructor(childProcess: ChildProcess);
|
38
|
+
getResults(): Promise<{
|
39
|
+
code: number;
|
40
|
+
terminalOutput: string;
|
41
|
+
}>;
|
36
42
|
onExit(callback: (code: number) => void): void;
|
37
43
|
onOutput(callback: (message: string) => void): void;
|
38
44
|
kill(): void;
|