nx 21.0.0-canary.20250419-8619c1d → 21.0.0-canary.20250423-16fc551
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 +11 -11
- package/src/native/index.d.ts +2 -1
- package/src/native/nx.wasm32-wasi.wasm +0 -0
- package/src/tasks-runner/default-tasks-runner.js +1 -1
- package/src/tasks-runner/forked-process-task-runner.js +3 -0
- package/src/tasks-runner/init-tasks-runner.js +2 -1
- package/src/tasks-runner/life-cycle.d.ts +2 -2
- package/src/tasks-runner/life-cycle.js +2 -2
- package/src/tasks-runner/life-cycles/tui-summary-life-cycle.d.ts +2 -1
- package/src/tasks-runner/life-cycles/tui-summary-life-cycle.js +16 -10
- package/src/tasks-runner/run-command.d.ts +2 -1
- package/src/tasks-runner/run-command.js +14 -6
- package/src/tasks-runner/running-tasks/node-child-process.js +4 -11
- package/src/tasks-runner/running-tasks/running-task.d.ts +2 -0
- package/src/tasks-runner/running-tasks/shared-running-task.d.ts +14 -0
- package/src/tasks-runner/running-tasks/shared-running-task.js +30 -0
- package/src/tasks-runner/task-orchestrator.d.ts +6 -3
- package/src/tasks-runner/task-orchestrator.js +57 -17
- package/src/tasks-runner/tasks-runner.d.ts +1 -0
- package/src/tasks-runner/tasks-schedule.d.ts +1 -0
- package/src/tasks-runner/tasks-schedule.js +9 -0
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "nx",
|
3
|
-
"version": "21.0.0-canary.
|
3
|
+
"version": "21.0.0-canary.20250423-16fc551",
|
4
4
|
"private": false,
|
5
5
|
"description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.",
|
6
6
|
"repository": {
|
@@ -83,16 +83,16 @@
|
|
83
83
|
}
|
84
84
|
},
|
85
85
|
"optionalDependencies": {
|
86
|
-
"@nx/nx-darwin-arm64": "21.0.0-canary.
|
87
|
-
"@nx/nx-darwin-x64": "21.0.0-canary.
|
88
|
-
"@nx/nx-freebsd-x64": "21.0.0-canary.
|
89
|
-
"@nx/nx-linux-arm-gnueabihf": "21.0.0-canary.
|
90
|
-
"@nx/nx-linux-arm64-gnu": "21.0.0-canary.
|
91
|
-
"@nx/nx-linux-arm64-musl": "21.0.0-canary.
|
92
|
-
"@nx/nx-linux-x64-gnu": "21.0.0-canary.
|
93
|
-
"@nx/nx-linux-x64-musl": "21.0.0-canary.
|
94
|
-
"@nx/nx-win32-arm64-msvc": "21.0.0-canary.
|
95
|
-
"@nx/nx-win32-x64-msvc": "21.0.0-canary.
|
86
|
+
"@nx/nx-darwin-arm64": "21.0.0-canary.20250423-16fc551",
|
87
|
+
"@nx/nx-darwin-x64": "21.0.0-canary.20250423-16fc551",
|
88
|
+
"@nx/nx-freebsd-x64": "21.0.0-canary.20250423-16fc551",
|
89
|
+
"@nx/nx-linux-arm-gnueabihf": "21.0.0-canary.20250423-16fc551",
|
90
|
+
"@nx/nx-linux-arm64-gnu": "21.0.0-canary.20250423-16fc551",
|
91
|
+
"@nx/nx-linux-arm64-musl": "21.0.0-canary.20250423-16fc551",
|
92
|
+
"@nx/nx-linux-x64-gnu": "21.0.0-canary.20250423-16fc551",
|
93
|
+
"@nx/nx-linux-x64-musl": "21.0.0-canary.20250423-16fc551",
|
94
|
+
"@nx/nx-win32-arm64-msvc": "21.0.0-canary.20250423-16fc551",
|
95
|
+
"@nx/nx-win32-x64-msvc": "21.0.0-canary.20250423-16fc551"
|
96
96
|
},
|
97
97
|
"nx-migrations": {
|
98
98
|
"migrations": "./migrations.json",
|
package/src/native/index.d.ts
CHANGED
Binary file
|
@@ -65,7 +65,7 @@ const defaultTasksRunner = async (tasks, options, context) => {
|
|
65
65
|
};
|
66
66
|
exports.defaultTasksRunner = defaultTasksRunner;
|
67
67
|
async function runAllTasks(options, context) {
|
68
|
-
const orchestrator = new task_orchestrator_1.TaskOrchestrator(context.hasher, context.initiatingProject, context.projectGraph, context.taskGraph, context.nxJson, options, context.nxArgs?.nxBail, context.daemon, context.nxArgs?.outputStyle);
|
68
|
+
const orchestrator = new task_orchestrator_1.TaskOrchestrator(context.hasher, context.initiatingProject, context.initiatingTasks, context.projectGraph, context.taskGraph, context.nxJson, options, context.nxArgs?.nxBail, context.daemon, context.nxArgs?.outputStyle);
|
69
69
|
return orchestrator.run();
|
70
70
|
}
|
71
71
|
exports.default = exports.defaultTasksRunner;
|
@@ -140,6 +140,9 @@ class ForkedProcessTaskRunner {
|
|
140
140
|
}
|
141
141
|
this.pseudoTerminals.delete(pseudoTerminal);
|
142
142
|
this.processes.delete(p);
|
143
|
+
if (!streamOutput) {
|
144
|
+
this.options.lifeCycle.printTaskTerminalOutput(task, code === 0 ? 'success' : 'failure', terminalOutput);
|
145
|
+
}
|
143
146
|
this.writeTerminalOutput(temporaryOutputPath, terminalOutput);
|
144
147
|
});
|
145
148
|
return p;
|
@@ -61,6 +61,7 @@ async function initTasksRunner(nxArgs) {
|
|
61
61
|
nxArgs: { ...nxArgs, parallel: opts.parallel },
|
62
62
|
loadDotEnvFiles: true,
|
63
63
|
initiatingProject: null,
|
64
|
+
initiatingTasks: [],
|
64
65
|
});
|
65
66
|
return {
|
66
67
|
status: Object.values(taskResults).some((taskResult) => taskResult.status === 'failure' || taskResult.status === 'skipped')
|
@@ -98,7 +99,7 @@ async function createOrchestrator(tasks, projectGraph, taskGraphForHashing, nxJs
|
|
98
99
|
return acc;
|
99
100
|
}, {}),
|
100
101
|
};
|
101
|
-
const orchestrator = new task_orchestrator_1.TaskOrchestrator(hasher, null, projectGraph, taskGraph, nxJson, { ...options, parallel: tasks.length, lifeCycle: compositedLifeCycle }, false, client_1.daemonClient, undefined, taskGraphForHashing);
|
102
|
+
const orchestrator = new task_orchestrator_1.TaskOrchestrator(hasher, null, [], projectGraph, taskGraph, nxJson, { ...options, parallel: tasks.length, lifeCycle: compositedLifeCycle }, false, client_1.daemonClient, undefined, taskGraphForHashing);
|
102
103
|
await orchestrator.init();
|
103
104
|
await Promise.all(tasks.map((task) => orchestrator.processTask(task.id)));
|
104
105
|
return orchestrator;
|
@@ -36,7 +36,7 @@ export interface LifeCycle {
|
|
36
36
|
startTasks?(task: Task[], metadata: TaskMetadata): void | Promise<void>;
|
37
37
|
endTasks?(taskResults: TaskResult[], metadata: TaskMetadata): void | Promise<void>;
|
38
38
|
printTaskTerminalOutput?(task: Task, status: TaskStatus, output: string): void;
|
39
|
-
registerRunningTask?(taskId: string, parserAndWriter: ExternalObject<[any, any]>):
|
39
|
+
registerRunningTask?(taskId: string, parserAndWriter: ExternalObject<[any, any]>): void;
|
40
40
|
setTaskStatus?(taskId: string, status: NativeTaskStatus): void;
|
41
41
|
registerForcedShutdownCallback?(callback: () => void): void;
|
42
42
|
}
|
@@ -51,7 +51,7 @@ export declare class CompositeLifeCycle implements LifeCycle {
|
|
51
51
|
startTasks(tasks: Task[], metadata: TaskMetadata): Promise<void>;
|
52
52
|
endTasks(taskResults: TaskResult[], metadata: TaskMetadata): Promise<void>;
|
53
53
|
printTaskTerminalOutput(task: Task, status: TaskStatus, output: string): void;
|
54
|
-
registerRunningTask(taskId: string, parserAndWriter: ExternalObject<[any, any]>):
|
54
|
+
registerRunningTask(taskId: string, parserAndWriter: ExternalObject<[any, any]>): void;
|
55
55
|
setTaskStatus(taskId: string, status: NativeTaskStatus): void;
|
56
56
|
registerForcedShutdownCallback(callback: () => void): void;
|
57
57
|
}
|
@@ -67,10 +67,10 @@ class CompositeLifeCycle {
|
|
67
67
|
}
|
68
68
|
}
|
69
69
|
}
|
70
|
-
|
70
|
+
registerRunningTask(taskId, parserAndWriter) {
|
71
71
|
for (let l of this.lifeCycles) {
|
72
72
|
if (l.registerRunningTask) {
|
73
|
-
|
73
|
+
l.registerRunningTask(taskId, parserAndWriter);
|
74
74
|
}
|
75
75
|
}
|
76
76
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { Task } from '../../config/task-graph';
|
2
2
|
import type { LifeCycle } from '../life-cycle';
|
3
|
-
export declare function getTuiTerminalSummaryLifeCycle({ projectNames, tasks, args, overrides, initiatingProject, resolveRenderIsDonePromise, }: {
|
3
|
+
export declare function getTuiTerminalSummaryLifeCycle({ projectNames, tasks, args, overrides, initiatingProject, initiatingTasks, resolveRenderIsDonePromise, }: {
|
4
4
|
projectNames: string[];
|
5
5
|
tasks: Task[];
|
6
6
|
args: {
|
@@ -10,6 +10,7 @@ export declare function getTuiTerminalSummaryLifeCycle({ projectNames, tasks, ar
|
|
10
10
|
};
|
11
11
|
overrides: Record<string, unknown>;
|
12
12
|
initiatingProject: string;
|
13
|
+
initiatingTasks: Task[];
|
13
14
|
resolveRenderIsDonePromise: (value: void) => void;
|
14
15
|
}): {
|
15
16
|
lifeCycle: Partial<LifeCycle>;
|
@@ -10,7 +10,7 @@ const figures = require("figures");
|
|
10
10
|
const LEFT_PAD = ` `;
|
11
11
|
const SPACER = ` `;
|
12
12
|
const EXTENDED_LEFT_PAD = ` `;
|
13
|
-
function getTuiTerminalSummaryLifeCycle({ projectNames, tasks, args, overrides, initiatingProject, resolveRenderIsDonePromise, }) {
|
13
|
+
function getTuiTerminalSummaryLifeCycle({ projectNames, tasks, args, overrides, initiatingProject, initiatingTasks, resolveRenderIsDonePromise, }) {
|
14
14
|
const lifeCycle = {};
|
15
15
|
const start = process.hrtime();
|
16
16
|
const targets = args.targets;
|
@@ -19,6 +19,7 @@ function getTuiTerminalSummaryLifeCycle({ projectNames, tasks, args, overrides,
|
|
19
19
|
let totalSuccessfulTasks = 0;
|
20
20
|
let totalFailedTasks = 0;
|
21
21
|
let totalCompletedTasks = 0;
|
22
|
+
let totalStoppedTasks = 0;
|
22
23
|
let timeTakenText;
|
23
24
|
const failedTasks = new Set();
|
24
25
|
const inProgressTasks = new Set();
|
@@ -30,14 +31,19 @@ function getTuiTerminalSummaryLifeCycle({ projectNames, tasks, args, overrides,
|
|
30
31
|
}
|
31
32
|
};
|
32
33
|
lifeCycle.printTaskTerminalOutput = (task, taskStatus, terminalOutput) => {
|
33
|
-
tasksToTerminalOutputs[task.id] = { terminalOutput, taskStatus };
|
34
34
|
taskIdsInOrderOfCompletion.push(task.id);
|
35
|
+
tasksToTerminalOutputs[task.id] = { terminalOutput, taskStatus };
|
36
|
+
};
|
37
|
+
lifeCycle.setTaskStatus = (taskId, taskStatus) => {
|
38
|
+
if (taskStatus === 9 /* NativeTaskStatus.Stopped */) {
|
39
|
+
totalStoppedTasks++;
|
40
|
+
}
|
35
41
|
};
|
36
42
|
lifeCycle.endTasks = (taskResults) => {
|
37
|
-
for (
|
43
|
+
for (const { task, status } of taskResults) {
|
38
44
|
totalCompletedTasks++;
|
39
|
-
inProgressTasks.delete(
|
40
|
-
switch (
|
45
|
+
inProgressTasks.delete(task.id);
|
46
|
+
switch (status) {
|
41
47
|
case 'remote-cache':
|
42
48
|
case 'local-cache':
|
43
49
|
case 'local-cache-kept-existing':
|
@@ -49,7 +55,7 @@ function getTuiTerminalSummaryLifeCycle({ projectNames, tasks, args, overrides,
|
|
49
55
|
break;
|
50
56
|
case 'failure':
|
51
57
|
totalFailedTasks++;
|
52
|
-
failedTasks.add(
|
58
|
+
failedTasks.add(task.id);
|
53
59
|
break;
|
54
60
|
}
|
55
61
|
}
|
@@ -75,7 +81,7 @@ function getTuiTerminalSummaryLifeCycle({ projectNames, tasks, args, overrides,
|
|
75
81
|
};
|
76
82
|
const printRunOneSummary = () => {
|
77
83
|
let lines = [];
|
78
|
-
const failure = totalSuccessfulTasks !== totalTasks;
|
84
|
+
const failure = totalSuccessfulTasks + totalStoppedTasks !== totalTasks;
|
79
85
|
// Prints task outputs in the order they were completed
|
80
86
|
// above the summary, since run-one should print all task results.
|
81
87
|
for (const taskId of taskIdsInOrderOfCompletion) {
|
@@ -99,7 +105,7 @@ function getTuiTerminalSummaryLifeCycle({ projectNames, tasks, args, overrides,
|
|
99
105
|
}
|
100
106
|
lines = [output_1.output.colors.green(lines.join(node_os_1.EOL))];
|
101
107
|
}
|
102
|
-
else if (totalCompletedTasks === totalTasks) {
|
108
|
+
else if (totalCompletedTasks + totalStoppedTasks === totalTasks) {
|
103
109
|
let text = `Ran target ${output_1.output.bold(targets[0])} for project ${output_1.output.bold(initiatingProject)}`;
|
104
110
|
if (tasks.length > 1) {
|
105
111
|
text += ` and ${output_1.output.bold(tasks.length - 1)} task(s) they depend on`;
|
@@ -137,7 +143,7 @@ function getTuiTerminalSummaryLifeCycle({ projectNames, tasks, args, overrides,
|
|
137
143
|
const printRunManySummary = () => {
|
138
144
|
console.log('');
|
139
145
|
const lines = [];
|
140
|
-
const failure = totalSuccessfulTasks !== totalTasks;
|
146
|
+
const failure = totalSuccessfulTasks + totalStoppedTasks !== totalTasks;
|
141
147
|
for (const taskId of taskIdsInOrderOfCompletion) {
|
142
148
|
const { terminalOutput, taskStatus } = tasksToTerminalOutputs[taskId];
|
143
149
|
if (taskStatus === 'failure') {
|
@@ -149,7 +155,7 @@ function getTuiTerminalSummaryLifeCycle({ projectNames, tasks, args, overrides,
|
|
149
155
|
}
|
150
156
|
}
|
151
157
|
lines.push(...output_1.output.getVerticalSeparatorLines(failure ? 'red' : 'green'));
|
152
|
-
if (totalSuccessfulTasks === totalTasks) {
|
158
|
+
if (totalSuccessfulTasks + totalStoppedTasks === totalTasks) {
|
153
159
|
const successSummaryRows = [];
|
154
160
|
const text = `Successfully ran ${(0, formatting_utils_1.formatTargetsAndProjects)(projectNames, targets, tasks)}`;
|
155
161
|
const taskOverridesRows = [];
|
@@ -17,7 +17,7 @@ export declare function runCommandForTasks(projectsToRun: ProjectGraphProjectNod
|
|
17
17
|
excludeTaskDependencies: boolean;
|
18
18
|
loadDotEnvFiles: boolean;
|
19
19
|
}): Promise<TaskResults>;
|
20
|
-
export declare function invokeTasksRunner({ tasks, projectGraph, taskGraph, lifeCycle, nxJson, nxArgs, loadDotEnvFiles, initiatingProject, }: {
|
20
|
+
export declare function invokeTasksRunner({ tasks, projectGraph, taskGraph, lifeCycle, nxJson, nxArgs, loadDotEnvFiles, initiatingProject, initiatingTasks, }: {
|
21
21
|
tasks: Task[];
|
22
22
|
projectGraph: ProjectGraph;
|
23
23
|
taskGraph: TaskGraph;
|
@@ -26,6 +26,7 @@ export declare function invokeTasksRunner({ tasks, projectGraph, taskGraph, life
|
|
26
26
|
nxArgs: NxArgs;
|
27
27
|
loadDotEnvFiles: boolean;
|
28
28
|
initiatingProject: string | null;
|
29
|
+
initiatingTasks: Task[];
|
29
30
|
}): Promise<{
|
30
31
|
[id: string]: TaskResult;
|
31
32
|
}>;
|
@@ -46,7 +46,7 @@ const originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
46
46
|
const originalStderrWrite = process.stderr.write.bind(process.stderr);
|
47
47
|
const originalConsoleLog = console.log.bind(console);
|
48
48
|
const originalConsoleError = console.error.bind(console);
|
49
|
-
async function getTerminalOutputLifeCycle(initiatingProject, projectNames, tasks, taskGraph, nxArgs, nxJson, overrides) {
|
49
|
+
async function getTerminalOutputLifeCycle(initiatingProject, initiatingTasks, projectNames, tasks, taskGraph, nxArgs, nxJson, overrides) {
|
50
50
|
const overridesWithoutHidden = { ...overrides };
|
51
51
|
delete overridesWithoutHidden['__overrides_unparsed__'];
|
52
52
|
if ((0, is_tui_enabled_1.isTuiEnabled)(nxJson)) {
|
@@ -82,7 +82,7 @@ async function getTerminalOutputLifeCycle(initiatingProject, projectNames, tasks
|
|
82
82
|
const projectText = projectNames.length === 1 ? 'project' : 'projects';
|
83
83
|
let titleText = '';
|
84
84
|
if (isRunOne) {
|
85
|
-
const mainTaskId =
|
85
|
+
const mainTaskId = initiatingTasks[0].id;
|
86
86
|
pinnedTasks.push(mainTaskId);
|
87
87
|
const mainContinuousDependencies = taskGraph.continuousDependencies[mainTaskId];
|
88
88
|
if (mainContinuousDependencies.length > 0) {
|
@@ -111,6 +111,7 @@ async function getTerminalOutputLifeCycle(initiatingProject, projectNames, tasks
|
|
111
111
|
args: nxArgs,
|
112
112
|
overrides: overridesWithoutHidden,
|
113
113
|
initiatingProject,
|
114
|
+
initiatingTasks,
|
114
115
|
resolveRenderIsDonePromise,
|
115
116
|
});
|
116
117
|
if (tasks.length === 0) {
|
@@ -120,7 +121,6 @@ async function getTerminalOutputLifeCycle(initiatingProject, projectNames, tasks
|
|
120
121
|
process.stderr.write = originalStderrWrite;
|
121
122
|
console.log = originalConsoleLog;
|
122
123
|
console.error = originalConsoleError;
|
123
|
-
printSummary();
|
124
124
|
});
|
125
125
|
}
|
126
126
|
const lifeCycles = [tsLifeCycle];
|
@@ -183,7 +183,6 @@ async function getTerminalOutputLifeCycle(initiatingProject, projectNames, tasks
|
|
183
183
|
process.stderr.write = originalStderrWrite;
|
184
184
|
console.log = originalConsoleLog;
|
185
185
|
console.error = originalConsoleError;
|
186
|
-
printSummary();
|
187
186
|
// Print the intercepted Nx Cloud logs
|
188
187
|
for (const log of interceptedNxCloudLogs) {
|
189
188
|
const logString = log.toString().trimStart();
|
@@ -196,6 +195,7 @@ async function getTerminalOutputLifeCycle(initiatingProject, projectNames, tasks
|
|
196
195
|
}
|
197
196
|
return {
|
198
197
|
lifeCycle: new life_cycle_1.CompositeLifeCycle(lifeCycles),
|
198
|
+
printSummary,
|
199
199
|
renderIsDone,
|
200
200
|
};
|
201
201
|
}
|
@@ -285,9 +285,12 @@ async function runCommand(projectsToRun, currentProjectGraph, { nxJson }, nxArgs
|
|
285
285
|
}
|
286
286
|
async function runCommandForTasks(projectsToRun, currentProjectGraph, { nxJson }, nxArgs, overrides, initiatingProject, extraTargetDependencies, extraOptions) {
|
287
287
|
const projectNames = projectsToRun.map((t) => t.name);
|
288
|
+
const projectNameSet = new Set(projectNames);
|
288
289
|
const { projectGraph, taskGraph } = await ensureWorkspaceIsInSyncAndGetGraphs(currentProjectGraph, nxJson, projectNames, nxArgs, overrides, extraTargetDependencies, extraOptions);
|
289
290
|
const tasks = Object.values(taskGraph.tasks);
|
290
|
-
const
|
291
|
+
const initiatingTasks = tasks.filter((t) => projectNameSet.has(t.target.project) &&
|
292
|
+
nxArgs.targets.includes(t.target.target));
|
293
|
+
const { lifeCycle, renderIsDone, printSummary } = await getTerminalOutputLifeCycle(initiatingProject, initiatingTasks, projectNames, tasks, taskGraph, nxArgs, nxJson, overrides);
|
291
294
|
const taskResults = await invokeTasksRunner({
|
292
295
|
tasks,
|
293
296
|
projectGraph,
|
@@ -297,8 +300,12 @@ async function runCommandForTasks(projectsToRun, currentProjectGraph, { nxJson }
|
|
297
300
|
nxArgs,
|
298
301
|
loadDotEnvFiles: extraOptions.loadDotEnvFiles,
|
299
302
|
initiatingProject,
|
303
|
+
initiatingTasks,
|
300
304
|
});
|
301
305
|
await renderIsDone;
|
306
|
+
if (printSummary) {
|
307
|
+
printSummary();
|
308
|
+
}
|
302
309
|
await (0, nx_key_1.printNxKey)();
|
303
310
|
return taskResults;
|
304
311
|
}
|
@@ -535,7 +542,7 @@ function setEnvVarsBasedOnArgs(nxArgs, loadDotEnvFiles) {
|
|
535
542
|
process.env.NX_LOAD_DOT_ENV_FILES = 'true';
|
536
543
|
}
|
537
544
|
}
|
538
|
-
async function invokeTasksRunner({ tasks, projectGraph, taskGraph, lifeCycle, nxJson, nxArgs, loadDotEnvFiles, initiatingProject, }) {
|
545
|
+
async function invokeTasksRunner({ tasks, projectGraph, taskGraph, lifeCycle, nxJson, nxArgs, loadDotEnvFiles, initiatingProject, initiatingTasks, }) {
|
539
546
|
setEnvVarsBasedOnArgs(nxArgs, loadDotEnvFiles);
|
540
547
|
// this needs to be done before we start to run the tasks
|
541
548
|
const taskDetails = (0, hash_task_1.getTaskDetails)();
|
@@ -555,6 +562,7 @@ async function invokeTasksRunner({ tasks, projectGraph, taskGraph, lifeCycle, nx
|
|
555
562
|
lifeCycle: compositedLifeCycle,
|
556
563
|
}, {
|
557
564
|
initiatingProject: nxArgs.outputStyle === 'compact' ? null : initiatingProject,
|
565
|
+
initiatingTasks,
|
558
566
|
projectGraph,
|
559
567
|
nxJson,
|
560
568
|
nxArgs,
|
@@ -153,18 +153,11 @@ class NodeChildProcessWithDirectOutput {
|
|
153
153
|
this.exitCallbacks.push(cb);
|
154
154
|
}
|
155
155
|
async getResults() {
|
156
|
-
|
157
|
-
|
158
|
-
return Promise.resolve({
|
159
|
-
code: this.exitCode,
|
160
|
-
terminalOutput,
|
161
|
-
});
|
156
|
+
if (!this.exited) {
|
157
|
+
await this.waitForExit();
|
162
158
|
}
|
163
|
-
|
164
|
-
return
|
165
|
-
code: this.exitCode,
|
166
|
-
terminalOutput,
|
167
|
-
});
|
159
|
+
const terminalOutput = this.getTerminalOutput();
|
160
|
+
return { code: this.exitCode, terminalOutput };
|
168
161
|
}
|
169
162
|
waitForExit() {
|
170
163
|
return new Promise((res) => {
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import type { Serializable } from 'child_process';
|
1
2
|
export declare abstract class RunningTask {
|
2
3
|
abstract getResults(): Promise<{
|
3
4
|
code: number;
|
@@ -5,4 +6,5 @@ export declare abstract class RunningTask {
|
|
5
6
|
}>;
|
6
7
|
abstract onExit(cb: (code: number) => void): void;
|
7
8
|
abstract kill(signal?: NodeJS.Signals | number): Promise<void> | void;
|
9
|
+
abstract send?(message: Serializable): void;
|
8
10
|
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import { RunningTask } from './running-task';
|
2
|
+
import { RunningTasksService } from '../../native';
|
3
|
+
export declare class SharedRunningTask implements RunningTask {
|
4
|
+
private runningTasksService;
|
5
|
+
private exitCallbacks;
|
6
|
+
constructor(runningTasksService: RunningTasksService, taskId: string);
|
7
|
+
getResults(): Promise<{
|
8
|
+
code: number;
|
9
|
+
terminalOutput: string;
|
10
|
+
}>;
|
11
|
+
kill(): void;
|
12
|
+
onExit(cb: (code: number) => void): void;
|
13
|
+
private waitForTaskToFinish;
|
14
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.SharedRunningTask = void 0;
|
4
|
+
class SharedRunningTask {
|
5
|
+
constructor(runningTasksService, taskId) {
|
6
|
+
this.runningTasksService = runningTasksService;
|
7
|
+
this.exitCallbacks = [];
|
8
|
+
this.waitForTaskToFinish(taskId).then(() => {
|
9
|
+
// notify exit callbacks
|
10
|
+
this.exitCallbacks.forEach((cb) => cb(0));
|
11
|
+
});
|
12
|
+
}
|
13
|
+
async getResults() {
|
14
|
+
throw new Error('Results cannot be retrieved from a shared task');
|
15
|
+
}
|
16
|
+
kill() {
|
17
|
+
this.exitCallbacks.forEach((cb) => cb(0));
|
18
|
+
}
|
19
|
+
onExit(cb) {
|
20
|
+
this.exitCallbacks.push(cb);
|
21
|
+
}
|
22
|
+
async waitForTaskToFinish(taskId) {
|
23
|
+
console.log(`Waiting for ${taskId} in another nx process`);
|
24
|
+
// wait for the running task to finish
|
25
|
+
do {
|
26
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
27
|
+
} while (this.runningTasksService.getRunningTasks([taskId]).length);
|
28
|
+
}
|
29
|
+
}
|
30
|
+
exports.SharedRunningTask = SharedRunningTask;
|
@@ -7,9 +7,11 @@ import { NxArgs } from '../utils/command-line-utils';
|
|
7
7
|
import { DefaultTasksRunnerOptions } from './default-tasks-runner';
|
8
8
|
import { RunningTask } from './running-tasks/running-task';
|
9
9
|
import { TaskStatus } from './tasks-runner';
|
10
|
+
import { SharedRunningTask } from './running-tasks/shared-running-task';
|
10
11
|
export declare class TaskOrchestrator {
|
11
12
|
private readonly hasher;
|
12
13
|
private readonly initiatingProject;
|
14
|
+
private readonly initiatingTasks;
|
13
15
|
private readonly projectGraph;
|
14
16
|
private readonly taskGraph;
|
15
17
|
private readonly nxJson;
|
@@ -26,6 +28,7 @@ export declare class TaskOrchestrator {
|
|
26
28
|
private tasksSchedule;
|
27
29
|
private batchEnv;
|
28
30
|
private reverseTaskDeps;
|
31
|
+
private initializingTaskIds;
|
29
32
|
private processedTasks;
|
30
33
|
private processedBatches;
|
31
34
|
private completedTasks;
|
@@ -33,8 +36,7 @@ export declare class TaskOrchestrator {
|
|
33
36
|
private groups;
|
34
37
|
private bailed;
|
35
38
|
private runningContinuousTasks;
|
36
|
-
|
37
|
-
constructor(hasher: TaskHasher, initiatingProject: string | undefined, projectGraph: ProjectGraph, taskGraph: TaskGraph, nxJson: NxJsonConfiguration, options: NxArgs & DefaultTasksRunnerOptions, bail: boolean, daemon: DaemonClient, outputStyle: string, taskGraphForHashing?: TaskGraph);
|
39
|
+
constructor(hasher: TaskHasher, initiatingProject: string | undefined, initiatingTasks: Task[], projectGraph: ProjectGraph, taskGraph: TaskGraph, nxJson: NxJsonConfiguration, options: NxArgs & DefaultTasksRunnerOptions, bail: boolean, daemon: DaemonClient, outputStyle: string, taskGraphForHashing?: TaskGraph);
|
38
40
|
init(): Promise<void>;
|
39
41
|
run(): Promise<{
|
40
42
|
[id: string]: TaskStatus;
|
@@ -55,7 +57,7 @@ export declare class TaskOrchestrator {
|
|
55
57
|
}>;
|
56
58
|
private runTask;
|
57
59
|
private runTaskInForkedProcess;
|
58
|
-
startContinuousTask(task: Task, groupId: number): Promise<RunningTask>;
|
60
|
+
startContinuousTask(task: Task, groupId: number): Promise<RunningTask | SharedRunningTask>;
|
59
61
|
private preRunSteps;
|
60
62
|
private postRunSteps;
|
61
63
|
private scheduleNextTasksAndReleaseThreads;
|
@@ -67,5 +69,6 @@ export declare class TaskOrchestrator {
|
|
67
69
|
private shouldCopyOutputsFromCache;
|
68
70
|
private recordOutputsHash;
|
69
71
|
private cleanup;
|
72
|
+
private cleanUpUnneededContinuousTasks;
|
70
73
|
}
|
71
74
|
export declare function getThreadCount(options: NxArgs & DefaultTasksRunnerOptions, taskGraph: TaskGraph): number;
|
@@ -21,11 +21,13 @@ const noop_child_process_1 = require("./running-tasks/noop-child-process");
|
|
21
21
|
const task_env_1 = require("./task-env");
|
22
22
|
const tasks_schedule_1 = require("./tasks-schedule");
|
23
23
|
const utils_1 = require("./utils");
|
24
|
+
const shared_running_task_1 = require("./running-tasks/shared-running-task");
|
24
25
|
class TaskOrchestrator {
|
25
26
|
// endregion internal state
|
26
|
-
constructor(hasher, initiatingProject, projectGraph, taskGraph, nxJson, options, bail, daemon, outputStyle, taskGraphForHashing = taskGraph) {
|
27
|
+
constructor(hasher, initiatingProject, initiatingTasks, projectGraph, taskGraph, nxJson, options, bail, daemon, outputStyle, taskGraphForHashing = taskGraph) {
|
27
28
|
this.hasher = hasher;
|
28
29
|
this.initiatingProject = initiatingProject;
|
30
|
+
this.initiatingTasks = initiatingTasks;
|
29
31
|
this.projectGraph = projectGraph;
|
30
32
|
this.taskGraph = taskGraph;
|
31
33
|
this.nxJson = nxJson;
|
@@ -43,6 +45,7 @@ class TaskOrchestrator {
|
|
43
45
|
// region internal state
|
44
46
|
this.batchEnv = (0, task_env_1.getEnvVariablesForBatchProcess)(this.options.skipNxCache, this.options.captureStderr);
|
45
47
|
this.reverseTaskDeps = (0, utils_1.calculateReverseDeps)(this.taskGraph);
|
48
|
+
this.initializingTaskIds = new Set(this.initiatingTasks.map((t) => t.id));
|
46
49
|
this.processedTasks = new Map();
|
47
50
|
this.processedBatches = new Map();
|
48
51
|
this.completedTasks = {};
|
@@ -50,7 +53,6 @@ class TaskOrchestrator {
|
|
50
53
|
this.groups = [];
|
51
54
|
this.bailed = false;
|
52
55
|
this.runningContinuousTasks = new Map();
|
53
|
-
this.cleaningUp = false;
|
54
56
|
}
|
55
57
|
async init() {
|
56
58
|
// Init the ForkedProcessTaskRunner, TasksSchedule, and Cache
|
@@ -397,15 +399,27 @@ class TaskOrchestrator {
|
|
397
399
|
if (this.tuiEnabled) {
|
398
400
|
this.options.lifeCycle.setTaskStatus(task.id, 8 /* NativeTaskStatus.Shared */);
|
399
401
|
}
|
402
|
+
const runningTask = new shared_running_task_1.SharedRunningTask(this.runningTasksService, task.id);
|
403
|
+
this.runningContinuousTasks.set(task.id, runningTask);
|
404
|
+
runningTask.onExit(() => {
|
405
|
+
this.runningContinuousTasks.delete(task.id);
|
406
|
+
});
|
400
407
|
// task is already running by another process, we schedule the next tasks
|
401
408
|
// and release the threads
|
402
409
|
await this.scheduleNextTasksAndReleaseThreads();
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
410
|
+
if (this.initializingTaskIds.has(task.id)) {
|
411
|
+
await new Promise((res) => {
|
412
|
+
runningTask.onExit((code) => {
|
413
|
+
if (!this.tuiEnabled) {
|
414
|
+
if (code > 128) {
|
415
|
+
process.exit(code);
|
416
|
+
}
|
417
|
+
}
|
418
|
+
res();
|
419
|
+
});
|
420
|
+
});
|
421
|
+
}
|
422
|
+
return runningTask;
|
409
423
|
}
|
410
424
|
const taskSpecificEnv = await this.processedTasks.get(task.id);
|
411
425
|
await this.preRunSteps([task], { groupId });
|
@@ -425,14 +439,20 @@ class TaskOrchestrator {
|
|
425
439
|
this.runningContinuousTasks.set(task.id, childProcess);
|
426
440
|
childProcess.onExit(() => {
|
427
441
|
this.runningTasksService.removeRunningTask(task.id);
|
442
|
+
this.runningContinuousTasks.delete(task.id);
|
428
443
|
});
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
444
|
+
await this.scheduleNextTasksAndReleaseThreads();
|
445
|
+
if (this.initializingTaskIds.has(task.id)) {
|
446
|
+
await new Promise((res) => {
|
447
|
+
childProcess.onExit((code) => {
|
448
|
+
if (!this.tuiEnabled) {
|
449
|
+
if (code > 128) {
|
450
|
+
process.exit(code);
|
451
|
+
}
|
452
|
+
}
|
453
|
+
res();
|
454
|
+
});
|
455
|
+
});
|
436
456
|
}
|
437
457
|
return childProcess;
|
438
458
|
}
|
@@ -505,6 +525,7 @@ class TaskOrchestrator {
|
|
505
525
|
}
|
506
526
|
complete(taskResults) {
|
507
527
|
this.tasksSchedule.complete(taskResults.map(({ taskId }) => taskId));
|
528
|
+
this.cleanUpUnneededContinuousTasks();
|
508
529
|
for (const { taskId, status } of taskResults) {
|
509
530
|
if (this.completedTasks[taskId] === undefined) {
|
510
531
|
this.completedTasks[taskId] = status;
|
@@ -571,10 +592,10 @@ class TaskOrchestrator {
|
|
571
592
|
}
|
572
593
|
// endregion utils
|
573
594
|
async cleanup() {
|
574
|
-
this.cleaningUp = true;
|
575
595
|
await Promise.all(Array.from(this.runningContinuousTasks).map(async ([taskId, t]) => {
|
576
596
|
try {
|
577
|
-
|
597
|
+
await t.kill();
|
598
|
+
this.options.lifeCycle.setTaskStatus(taskId, 9 /* NativeTaskStatus.Stopped */);
|
578
599
|
}
|
579
600
|
catch (e) {
|
580
601
|
console.error(`Unable to terminate ${taskId}\nError:`, e);
|
@@ -584,6 +605,25 @@ class TaskOrchestrator {
|
|
584
605
|
}
|
585
606
|
}));
|
586
607
|
}
|
608
|
+
cleanUpUnneededContinuousTasks() {
|
609
|
+
const incompleteTasks = this.tasksSchedule.getIncompleteTasks();
|
610
|
+
const neededContinuousTasks = new Set(this.initializingTaskIds);
|
611
|
+
for (const task of incompleteTasks) {
|
612
|
+
const continuousDependencies = this.taskGraph.continuousDependencies[task.id];
|
613
|
+
for (const continuousDependency of continuousDependencies) {
|
614
|
+
neededContinuousTasks.add(continuousDependency);
|
615
|
+
}
|
616
|
+
}
|
617
|
+
for (const taskId of this.runningContinuousTasks.keys()) {
|
618
|
+
if (!neededContinuousTasks.has(taskId)) {
|
619
|
+
const runningTask = this.runningContinuousTasks.get(taskId);
|
620
|
+
if (runningTask) {
|
621
|
+
runningTask.kill();
|
622
|
+
this.options.lifeCycle.setTaskStatus(taskId, 9 /* NativeTaskStatus.Stopped */);
|
623
|
+
}
|
624
|
+
}
|
625
|
+
}
|
626
|
+
}
|
587
627
|
}
|
588
628
|
exports.TaskOrchestrator = TaskOrchestrator;
|
589
629
|
function getThreadCount(options, taskGraph) {
|
@@ -12,6 +12,7 @@ export type TaskStatus = 'success' | 'failure' | 'skipped' | 'local-cache-kept-e
|
|
12
12
|
export type TasksRunner<T = unknown> = (tasks: Task[], options: T, context?: {
|
13
13
|
target?: string;
|
14
14
|
initiatingProject?: string | null;
|
15
|
+
initiatingTasks: Task[];
|
15
16
|
projectGraph: ProjectGraph;
|
16
17
|
nxJson: NxJsonConfiguration;
|
17
18
|
nxArgs: NxArgs;
|
@@ -68,6 +68,15 @@ class TasksSchedule {
|
|
68
68
|
? this.scheduledBatches.shift()
|
69
69
|
: null;
|
70
70
|
}
|
71
|
+
getIncompleteTasks() {
|
72
|
+
const incompleteTasks = [];
|
73
|
+
for (const taskId in this.taskGraph.tasks) {
|
74
|
+
if (!this.completedTasks.has(taskId)) {
|
75
|
+
incompleteTasks.push(this.taskGraph.tasks[taskId]);
|
76
|
+
}
|
77
|
+
}
|
78
|
+
return incompleteTasks;
|
79
|
+
}
|
71
80
|
async scheduleTasks() {
|
72
81
|
if (this.options.batch || process.env.NX_BATCH_MODE === 'true') {
|
73
82
|
await this.scheduleBatches();
|