nx 21.0.0-canary.20250422-8619c1d → 21.0.0-canary.20250424-e23b25f

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.
Files changed (31) hide show
  1. package/package.json +11 -11
  2. package/src/command-line/init/configure-plugins.js +5 -3
  3. package/src/command-line/init/implementation/utils.d.ts +2 -1
  4. package/src/command-line/init/implementation/utils.js +2 -1
  5. package/src/command-line/init/init-v2.js +8 -7
  6. package/src/core/graph/main.js +1 -1
  7. package/src/executors/run-commands/run-commands.impl.d.ts +1 -2
  8. package/src/executors/run-commands/run-commands.impl.js +1 -1
  9. package/src/executors/run-commands/running-tasks.d.ts +5 -2
  10. package/src/executors/run-commands/running-tasks.js +42 -6
  11. package/src/native/index.d.ts +4 -1
  12. package/src/native/nx.wasm32-wasi.wasm +0 -0
  13. package/src/tasks-runner/default-tasks-runner.js +1 -1
  14. package/src/tasks-runner/forked-process-task-runner.js +3 -0
  15. package/src/tasks-runner/init-tasks-runner.js +2 -1
  16. package/src/tasks-runner/life-cycle.d.ts +6 -2
  17. package/src/tasks-runner/life-cycle.js +16 -2
  18. package/src/tasks-runner/life-cycles/tui-summary-life-cycle.d.ts +2 -1
  19. package/src/tasks-runner/life-cycles/tui-summary-life-cycle.js +16 -10
  20. package/src/tasks-runner/run-command.d.ts +2 -1
  21. package/src/tasks-runner/run-command.js +14 -6
  22. package/src/tasks-runner/running-tasks/node-child-process.js +4 -11
  23. package/src/tasks-runner/running-tasks/running-task.d.ts +3 -0
  24. package/src/tasks-runner/running-tasks/shared-running-task.d.ts +14 -0
  25. package/src/tasks-runner/running-tasks/shared-running-task.js +30 -0
  26. package/src/tasks-runner/task-orchestrator.d.ts +6 -3
  27. package/src/tasks-runner/task-orchestrator.js +79 -23
  28. package/src/tasks-runner/tasks-runner.d.ts +1 -0
  29. package/src/tasks-runner/tasks-schedule.d.ts +1 -0
  30. package/src/tasks-runner/tasks-schedule.js +9 -0
  31. package/src/tasks-runner/utils.js +2 -0
@@ -1,5 +1,4 @@
1
1
  import { ExecutorContext } from '../../config/misc-interfaces';
2
- import { PseudoTtyProcess } from '../../tasks-runner/pseudo-terminal';
3
2
  import { ParallelRunningTasks, SeriallyRunningTasks } from './running-tasks';
4
3
  export declare const LARGE_BUFFER: number;
5
4
  export type Json = {
@@ -55,5 +54,5 @@ export default function (options: RunCommandsOptions, context: ExecutorContext):
55
54
  success: boolean;
56
55
  terminalOutput: string;
57
56
  }>;
58
- export declare function runCommands(options: RunCommandsOptions, context: ExecutorContext): Promise<PseudoTtyProcess | ParallelRunningTasks | SeriallyRunningTasks>;
57
+ export declare function runCommands(options: RunCommandsOptions, context: ExecutorContext): Promise<import("../../tasks-runner/pseudo-terminal").PseudoTtyProcess | ParallelRunningTasks | SeriallyRunningTasks>;
59
58
  export declare function interpolateArgsIntoCommand(command: string, opts: Pick<NormalizedRunCommandsOptions, 'args' | 'parsedArgs' | '__unparsed__' | 'unknownOptions' | 'unparsedCommandArgs'>, forwardAllArgs: boolean): string;
@@ -57,7 +57,7 @@ async function runCommands(options, context) {
57
57
  const runningTask = isSingleCommandAndCanUsePseudoTerminal
58
58
  ? await (0, running_tasks_1.runSingleCommandWithPseudoTerminal)(normalized, context)
59
59
  : options.parallel
60
- ? new running_tasks_1.ParallelRunningTasks(normalized, context, tuiEnabled)
60
+ ? new running_tasks_1.ParallelRunningTasks(normalized, context)
61
61
  : new running_tasks_1.SeriallyRunningTasks(normalized, context, tuiEnabled);
62
62
  return runningTask;
63
63
  }
@@ -4,16 +4,17 @@ import { PseudoTtyProcess } from '../../tasks-runner/pseudo-terminal';
4
4
  import { RunningTask } from '../../tasks-runner/running-tasks/running-task';
5
5
  import { NormalizedRunCommandsOptions } from './run-commands.impl';
6
6
  export declare class ParallelRunningTasks implements RunningTask {
7
- private readonly tuiEnabled;
8
7
  private readonly childProcesses;
9
8
  private readyWhenStatus;
10
9
  private readonly streamOutput;
11
10
  private exitCallbacks;
12
- constructor(options: NormalizedRunCommandsOptions, context: ExecutorContext, tuiEnabled: boolean);
11
+ private outputCallbacks;
12
+ constructor(options: NormalizedRunCommandsOptions, context: ExecutorContext);
13
13
  getResults(): Promise<{
14
14
  code: number;
15
15
  terminalOutput: string;
16
16
  }>;
17
+ onOutput(cb: (terminalOutput: string) => void): void;
17
18
  onExit(cb: (code: number, terminalOutput: string) => void): void;
18
19
  send(message: Serializable): void;
19
20
  kill(signal?: NodeJS.Signals | number): Promise<void>;
@@ -26,12 +27,14 @@ export declare class SeriallyRunningTasks implements RunningTask {
26
27
  private exitCallbacks;
27
28
  private code;
28
29
  private error;
30
+ private outputCallbacks;
29
31
  constructor(options: NormalizedRunCommandsOptions, context: ExecutorContext, tuiEnabled: boolean);
30
32
  getResults(): Promise<{
31
33
  code: number;
32
34
  terminalOutput: string;
33
35
  }>;
34
36
  onExit(cb: (code: number, terminalOutput: string) => void): void;
37
+ onOutput(cb: (terminalOutput: string) => void): void;
35
38
  send(message: Serializable): void;
36
39
  kill(signal?: NodeJS.Signals | number): void | Promise<void>;
37
40
  private run;
@@ -12,9 +12,9 @@ const task_env_1 = require("../../tasks-runner/task-env");
12
12
  const exit_codes_1 = require("../../utils/exit-codes");
13
13
  const run_commands_impl_1 = require("./run-commands.impl");
14
14
  class ParallelRunningTasks {
15
- constructor(options, context, tuiEnabled) {
16
- this.tuiEnabled = tuiEnabled;
15
+ constructor(options, context) {
17
16
  this.exitCallbacks = [];
17
+ this.outputCallbacks = [];
18
18
  this.childProcesses = options.commands.map((commandConfig) => new RunningNodeProcess(commandConfig, options.color, calculateCwd(options.cwd, context), options.env ?? {}, options.readyWhenStatus, options.streamOutput, options.envFile));
19
19
  this.readyWhenStatus = options.readyWhenStatus;
20
20
  this.streamOutput = options.streamOutput;
@@ -27,6 +27,9 @@ class ParallelRunningTasks {
27
27
  });
28
28
  });
29
29
  }
30
+ onOutput(cb) {
31
+ this.outputCallbacks.push(cb);
32
+ }
30
33
  onExit(cb) {
31
34
  this.exitCallbacks.push(cb);
32
35
  }
@@ -48,6 +51,11 @@ class ParallelRunningTasks {
48
51
  async run() {
49
52
  if (this.readyWhenStatus.length) {
50
53
  let { childProcess, result: { code, terminalOutput }, } = await Promise.race(this.childProcesses.map((childProcess) => new Promise((res) => {
54
+ childProcess.onOutput((terminalOutput) => {
55
+ for (const cb of this.outputCallbacks) {
56
+ cb(terminalOutput);
57
+ }
58
+ });
51
59
  childProcess.onExit((code, terminalOutput) => {
52
60
  res({
53
61
  childProcess,
@@ -67,10 +75,18 @@ class ParallelRunningTasks {
67
75
  }
68
76
  }
69
77
  else {
70
- const results = await Promise.all(this.childProcesses.map((childProcess) => childProcess.getResults().then((result) => ({
71
- childProcess,
72
- result,
73
- }))));
78
+ const results = await Promise.all(this.childProcesses.map(async (childProcess) => {
79
+ childProcess.onOutput((terminalOutput) => {
80
+ for (const cb of this.outputCallbacks) {
81
+ cb(terminalOutput);
82
+ }
83
+ });
84
+ const result = await childProcess.getResults();
85
+ return {
86
+ childProcess,
87
+ result,
88
+ };
89
+ }));
74
90
  let terminalOutput = results
75
91
  .map((r) => r.result.terminalOutput)
76
92
  .join('\r\n');
@@ -103,6 +119,7 @@ class SeriallyRunningTasks {
103
119
  this.currentProcess = null;
104
120
  this.exitCallbacks = [];
105
121
  this.code = 0;
122
+ this.outputCallbacks = [];
106
123
  this.run(options, context)
107
124
  .catch((e) => {
108
125
  this.error = e;
@@ -128,6 +145,9 @@ class SeriallyRunningTasks {
128
145
  onExit(cb) {
129
146
  this.exitCallbacks.push(cb);
130
147
  }
148
+ onOutput(cb) {
149
+ this.outputCallbacks.push(cb);
150
+ }
131
151
  send(message) {
132
152
  throw new Error('Not implemented');
133
153
  }
@@ -138,6 +158,11 @@ class SeriallyRunningTasks {
138
158
  for (const c of options.commands) {
139
159
  const childProcess = await this.createProcess(c, options.color, calculateCwd(options.cwd, context), options.processEnv ?? options.env ?? {}, options.usePty, options.streamOutput, options.tty, options.envFile);
140
160
  this.currentProcess = childProcess;
161
+ childProcess.onOutput((output) => {
162
+ for (const cb of this.outputCallbacks) {
163
+ cb(output);
164
+ }
165
+ });
141
166
  let { code, terminalOutput } = await childProcess.getResults();
142
167
  this.terminalOutput += terminalOutput;
143
168
  this.code = code;
@@ -173,6 +198,7 @@ class RunningNodeProcess {
173
198
  this.readyWhenStatus = readyWhenStatus;
174
199
  this.terminalOutput = '';
175
200
  this.exitCallbacks = [];
201
+ this.outputCallbacks = [];
176
202
  env = processEnv(color, cwd, env, envFile);
177
203
  this.command = commandConfig.command;
178
204
  this.terminalOutput = chalk.dim('> ') + commandConfig.command + '\r\n\r\n';
@@ -194,6 +220,9 @@ class RunningNodeProcess {
194
220
  });
195
221
  });
196
222
  }
223
+ onOutput(cb) {
224
+ this.outputCallbacks.push(cb);
225
+ }
197
226
  onExit(cb) {
198
227
  this.exitCallbacks.push(cb);
199
228
  }
@@ -212,10 +241,16 @@ class RunningNodeProcess {
212
241
  });
213
242
  });
214
243
  }
244
+ triggerOutputListeners(output) {
245
+ for (const cb of this.outputCallbacks) {
246
+ cb(output);
247
+ }
248
+ }
215
249
  addListeners(commandConfig, streamOutput) {
216
250
  this.childProcess.stdout.on('data', (data) => {
217
251
  const output = addColorAndPrefix(data, commandConfig);
218
252
  this.terminalOutput += output;
253
+ this.triggerOutputListeners(output);
219
254
  if (streamOutput) {
220
255
  process.stdout.write(output);
221
256
  }
@@ -229,6 +264,7 @@ class RunningNodeProcess {
229
264
  this.childProcess.stderr.on('data', (err) => {
230
265
  const output = addColorAndPrefix(err, commandConfig);
231
266
  this.terminalOutput += output;
267
+ this.triggerOutputListeners(output);
232
268
  if (streamOutput) {
233
269
  process.stderr.write(output);
234
270
  }
@@ -17,6 +17,8 @@ export declare class AppLifeCycle {
17
17
  endCommand(): void
18
18
  __init(doneCallback: () => any): void
19
19
  registerRunningTask(taskId: string, parserAndWriter: ExternalObject<[ParserArc, WriterArc]>): void
20
+ registerRunningTaskWithEmptyParser(taskId: string): void
21
+ appendTaskOutput(taskId: string, output: string): void
20
22
  setTaskStatus(taskId: string, status: TaskStatus): void
21
23
  registerForcedShutdownCallback(forcedShutdownCallback: () => any): void
22
24
  __setCloudMessage(message: string): Promise<void>
@@ -322,7 +324,8 @@ export declare const enum TaskStatus {
322
324
  RemoteCache = 5,
323
325
  NotStarted = 6,
324
326
  InProgress = 7,
325
- Shared = 8
327
+ Shared = 8,
328
+ Stopped = 9
326
329
  }
327
330
 
328
331
  export interface TaskTarget {
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,9 @@ 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]>): Promise<void>;
39
+ registerRunningTask?(taskId: string, parserAndWriter: ExternalObject<[any, any]>): void;
40
+ registerRunningTaskWithEmptyParser?(taskId: string): void;
41
+ appendTaskOutput?(taskId: string, output: string): void;
40
42
  setTaskStatus?(taskId: string, status: NativeTaskStatus): void;
41
43
  registerForcedShutdownCallback?(callback: () => void): void;
42
44
  }
@@ -51,7 +53,9 @@ export declare class CompositeLifeCycle implements LifeCycle {
51
53
  startTasks(tasks: Task[], metadata: TaskMetadata): Promise<void>;
52
54
  endTasks(taskResults: TaskResult[], metadata: TaskMetadata): Promise<void>;
53
55
  printTaskTerminalOutput(task: Task, status: TaskStatus, output: string): void;
54
- registerRunningTask(taskId: string, parserAndWriter: ExternalObject<[any, any]>): Promise<void>;
56
+ registerRunningTask(taskId: string, parserAndWriter: ExternalObject<[any, any]>): void;
57
+ registerRunningTaskWithEmptyParser(taskId: string): void;
58
+ appendTaskOutput(taskId: string, output: string): void;
55
59
  setTaskStatus(taskId: string, status: NativeTaskStatus): void;
56
60
  registerForcedShutdownCallback(callback: () => void): void;
57
61
  }
@@ -67,10 +67,24 @@ class CompositeLifeCycle {
67
67
  }
68
68
  }
69
69
  }
70
- async registerRunningTask(taskId, parserAndWriter) {
70
+ registerRunningTask(taskId, parserAndWriter) {
71
71
  for (let l of this.lifeCycles) {
72
72
  if (l.registerRunningTask) {
73
- await l.registerRunningTask(taskId, parserAndWriter);
73
+ l.registerRunningTask(taskId, parserAndWriter);
74
+ }
75
+ }
76
+ }
77
+ registerRunningTaskWithEmptyParser(taskId) {
78
+ for (let l of this.lifeCycles) {
79
+ if (l.registerRunningTaskWithEmptyParser) {
80
+ l.registerRunningTaskWithEmptyParser(taskId);
81
+ }
82
+ }
83
+ }
84
+ appendTaskOutput(taskId, output) {
85
+ for (let l of this.lifeCycles) {
86
+ if (l.appendTaskOutput) {
87
+ l.appendTaskOutput(taskId, output);
74
88
  }
75
89
  }
76
90
  }
@@ -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 (let t of taskResults) {
43
+ for (const { task, status } of taskResults) {
38
44
  totalCompletedTasks++;
39
- inProgressTasks.delete(t.task.id);
40
- switch (t.status) {
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(t.task.id);
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 = (0, create_task_graph_1.createTaskId)(initiatingProject, nxArgs.targets[0], nxArgs.configuration);
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 { lifeCycle, renderIsDone } = await getTerminalOutputLifeCycle(initiatingProject, projectNames, tasks, taskGraph, nxArgs, nxJson, overrides);
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
- const terminalOutput = this.getTerminalOutput();
157
- if (this.exited) {
158
- return Promise.resolve({
159
- code: this.exitCode,
160
- terminalOutput,
161
- });
156
+ if (!this.exited) {
157
+ await this.waitForExit();
162
158
  }
163
- await this.waitForExit();
164
- return Promise.resolve({
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,6 @@ 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 onOutput?(cb: (output: string) => void): void;
10
+ abstract send?(message: Serializable): void;
8
11
  }
@@ -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
- private cleaningUp;
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;