nx 21.0.0-beta.0 → 21.0.0-beta.10

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 (242) hide show
  1. package/.eslintrc.json +5 -1
  2. package/migrations.json +5 -35
  3. package/package.json +12 -12
  4. package/release/index.d.ts +1 -1
  5. package/release/index.js +2 -1
  6. package/schemas/nx-schema.json +182 -35
  7. package/schemas/project-schema.json +5 -0
  8. package/src/adapter/compat.d.ts +1 -1
  9. package/src/adapter/compat.js +3 -0
  10. package/src/command-line/add/add.js +6 -16
  11. package/src/command-line/affected/command-object.js +6 -6
  12. package/src/command-line/examples.js +0 -4
  13. package/src/command-line/exec/command-object.js +1 -1
  14. package/src/command-line/generate/generator-utils.js +8 -3
  15. package/src/command-line/import/import.js +1 -1
  16. package/src/command-line/init/command-object.js +18 -6
  17. package/src/command-line/init/configure-plugins.d.ts +6 -7
  18. package/src/command-line/init/configure-plugins.js +52 -38
  19. package/src/command-line/init/implementation/add-nx-to-turborepo.d.ts +4 -0
  20. package/src/command-line/init/implementation/add-nx-to-turborepo.js +49 -0
  21. package/src/command-line/init/implementation/check-compatible-with-plugins.js +7 -1
  22. package/src/command-line/init/implementation/deduce-default-base.d.ts +1 -0
  23. package/src/command-line/init/implementation/deduce-default-base.js +53 -0
  24. package/src/command-line/init/implementation/react/add-vite-commands-to-package-scripts.js +6 -4
  25. package/src/command-line/init/implementation/react/index.d.ts +1 -1
  26. package/src/command-line/init/implementation/react/index.js +32 -185
  27. package/src/command-line/init/implementation/react/write-vite-config.js +19 -3
  28. package/src/command-line/init/implementation/utils.d.ts +6 -2
  29. package/src/command-line/init/implementation/utils.js +110 -45
  30. package/src/command-line/init/init-v1.js +1 -1
  31. package/src/command-line/init/init-v2.d.ts +1 -0
  32. package/src/command-line/init/init-v2.js +70 -39
  33. package/src/command-line/migrate/migrate-ui-api.d.ts +58 -0
  34. package/src/command-line/migrate/migrate-ui-api.js +227 -0
  35. package/src/command-line/migrate/migrate.d.ts +16 -3
  36. package/src/command-line/migrate/migrate.js +134 -101
  37. package/src/command-line/nx-commands.js +19 -5
  38. package/src/command-line/register/command-object.d.ts +6 -0
  39. package/src/command-line/{activate-powerpack → register}/command-object.js +9 -9
  40. package/src/command-line/register/register.d.ts +2 -0
  41. package/src/command-line/register/register.js +9 -0
  42. package/src/command-line/release/changelog.js +18 -15
  43. package/src/command-line/release/command-object.d.ts +8 -0
  44. package/src/command-line/release/command-object.js +9 -0
  45. package/src/command-line/release/config/config.d.ts +8 -7
  46. package/src/command-line/release/config/config.js +139 -45
  47. package/src/command-line/release/config/use-legacy-versioning.d.ts +2 -0
  48. package/src/command-line/release/config/use-legacy-versioning.js +9 -0
  49. package/src/command-line/release/index.d.ts +4 -0
  50. package/src/command-line/release/index.js +6 -1
  51. package/src/command-line/release/plan-check.js +6 -3
  52. package/src/command-line/release/plan.js +7 -3
  53. package/src/command-line/release/publish.js +7 -3
  54. package/src/command-line/release/release.js +8 -3
  55. package/src/command-line/release/utils/batch-projects-by-generator-config.js +6 -3
  56. package/src/command-line/release/utils/git.d.ts +3 -2
  57. package/src/command-line/release/utils/git.js +65 -9
  58. package/src/command-line/release/utils/github.js +3 -1
  59. package/src/command-line/release/utils/resolve-semver-specifier.d.ts +2 -1
  60. package/src/command-line/release/utils/resolve-semver-specifier.js +2 -1
  61. package/src/command-line/release/utils/semver.d.ts +8 -0
  62. package/src/command-line/release/utils/semver.js +8 -0
  63. package/src/command-line/release/utils/shared-legacy.d.ts +25 -0
  64. package/src/command-line/release/utils/shared-legacy.js +2 -0
  65. package/src/command-line/release/utils/shared.d.ts +11 -17
  66. package/src/command-line/release/version/derive-specifier-from-conventional-commits.d.ts +7 -0
  67. package/src/command-line/release/version/derive-specifier-from-conventional-commits.js +47 -0
  68. package/src/command-line/release/version/deriver-specifier-from-version-plans.d.ts +8 -0
  69. package/src/command-line/release/version/deriver-specifier-from-version-plans.js +59 -0
  70. package/src/command-line/release/version/project-logger.d.ts +8 -0
  71. package/src/command-line/release/version/project-logger.js +45 -0
  72. package/src/command-line/release/version/release-group-processor.d.ts +252 -0
  73. package/src/command-line/release/version/release-group-processor.js +1057 -0
  74. package/src/command-line/release/version/resolve-current-version.d.ts +32 -0
  75. package/src/command-line/release/version/resolve-current-version.js +241 -0
  76. package/src/command-line/release/version/test-utils.d.ts +93 -0
  77. package/src/command-line/release/version/test-utils.js +415 -0
  78. package/src/command-line/release/version/topological-sort.d.ts +9 -0
  79. package/src/command-line/release/version/topological-sort.js +41 -0
  80. package/src/command-line/release/version/version-actions.d.ts +171 -0
  81. package/src/command-line/release/version/version-actions.js +195 -0
  82. package/src/command-line/release/version-legacy.d.ts +46 -0
  83. package/src/command-line/release/version-legacy.js +453 -0
  84. package/src/command-line/release/version.d.ts +0 -40
  85. package/src/command-line/release/version.js +84 -262
  86. package/src/command-line/repair/repair.js +0 -1
  87. package/src/command-line/report/report.d.ts +7 -3
  88. package/src/command-line/report/report.js +52 -18
  89. package/src/command-line/run/command-object.js +2 -2
  90. package/src/command-line/run/executor-utils.d.ts +6 -1
  91. package/src/command-line/run/executor-utils.js +10 -1
  92. package/src/command-line/run/run.js +2 -2
  93. package/src/command-line/run-many/command-object.js +2 -2
  94. package/src/command-line/yargs-utils/shared-options.d.ts +4 -0
  95. package/src/command-line/yargs-utils/shared-options.js +20 -0
  96. package/src/config/misc-interfaces.d.ts +11 -1
  97. package/src/config/nx-json.d.ts +160 -16
  98. package/src/config/project-graph.d.ts +4 -2
  99. package/src/config/project-graph.js +8 -0
  100. package/src/config/workspace-json-project-json.d.ts +2 -2
  101. package/src/core/graph/main.js +1 -1
  102. package/src/core/graph/runtime.js +1 -1
  103. package/src/core/graph/styles.css +2 -2
  104. package/src/core/graph/styles.js +1 -1
  105. package/src/daemon/client/client.d.ts +2 -0
  106. package/src/daemon/client/client.js +15 -0
  107. package/src/daemon/message-types/glob.d.ts +7 -0
  108. package/src/daemon/message-types/glob.js +9 -1
  109. package/src/daemon/message-types/hash-glob.d.ts +6 -0
  110. package/src/daemon/message-types/hash-glob.js +9 -1
  111. package/src/daemon/server/handle-glob.d.ts +1 -0
  112. package/src/daemon/server/handle-glob.js +8 -0
  113. package/src/daemon/server/handle-hash-glob.d.ts +1 -0
  114. package/src/daemon/server/handle-hash-glob.js +8 -0
  115. package/src/daemon/server/logger.js +2 -1
  116. package/src/daemon/server/server.js +7 -0
  117. package/src/devkit-internals.d.ts +3 -2
  118. package/src/devkit-internals.js +5 -1
  119. package/src/executors/run-commands/run-commands.impl.d.ts +2 -5
  120. package/src/executors/run-commands/run-commands.impl.js +14 -42
  121. package/src/executors/run-commands/running-tasks.d.ts +9 -4
  122. package/src/executors/run-commands/running-tasks.js +103 -30
  123. package/src/executors/run-script/run-script.impl.js +4 -3
  124. package/src/generators/internal-utils/format-changed-files-with-prettier-if-available.js +8 -0
  125. package/src/generators/testing-utils/create-tree.js +5 -1
  126. package/src/migrations/{update-17-0-0/rm-default-collection-npm-scope.d.ts → update-21-0-0/release-version-config-changes.d.ts} +1 -1
  127. package/src/migrations/update-21-0-0/release-version-config-changes.js +111 -0
  128. package/src/native/index.d.ts +98 -19
  129. package/src/native/index.js +16 -2
  130. package/src/native/native-bindings.js +7 -0
  131. package/src/native/nx.wasi-browser.js +20 -19
  132. package/src/native/nx.wasi.cjs +20 -19
  133. package/src/native/nx.wasm32-wasi.wasm +0 -0
  134. package/src/nx-cloud/nx-cloud-tasks-runner-shell.js +3 -3
  135. package/src/plugins/js/lock-file/lock-file.js +28 -13
  136. package/src/plugins/js/lock-file/utils/package-json.d.ts +1 -1
  137. package/src/plugins/js/lock-file/utils/package-json.js +8 -6
  138. package/src/plugins/js/lock-file/utils/pnpm-normalizer.js +3 -3
  139. package/src/plugins/js/lock-file/yarn-parser.js +85 -39
  140. package/src/plugins/js/project-graph/affected/lock-file-changes.js +1 -0
  141. package/src/plugins/js/project-graph/build-dependencies/explicit-project-dependencies.js +1 -1
  142. package/src/plugins/js/project-graph/build-dependencies/target-project-locator.d.ts +10 -1
  143. package/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +59 -6
  144. package/src/plugins/js/utils/packages.js +22 -3
  145. package/src/plugins/js/utils/register.js +1 -0
  146. package/src/plugins/js/utils/typescript.js +3 -3
  147. package/src/plugins/package-json/create-nodes.d.ts +1 -1
  148. package/src/plugins/package-json/create-nodes.js +4 -2
  149. package/src/project-graph/affected/locators/project-glob-changes.js +2 -2
  150. package/src/project-graph/error-types.js +32 -2
  151. package/src/project-graph/file-utils.d.ts +1 -10
  152. package/src/project-graph/file-utils.js +2 -77
  153. package/src/project-graph/nx-deps-cache.js +7 -2
  154. package/src/project-graph/plugins/get-plugins.js +2 -1
  155. package/src/project-graph/plugins/in-process-loader.js +1 -1
  156. package/src/project-graph/plugins/isolation/plugin-worker.js +12 -6
  157. package/src/project-graph/plugins/loaded-nx-plugin.d.ts +2 -1
  158. package/src/project-graph/plugins/loaded-nx-plugin.js +3 -7
  159. package/src/project-graph/plugins/public-api.d.ts +1 -1
  160. package/src/project-graph/plugins/utils.d.ts +2 -2
  161. package/src/project-graph/plugins/utils.js +2 -2
  162. package/src/project-graph/project-graph.js +5 -2
  163. package/src/project-graph/utils/project-configuration-utils.d.ts +3 -3
  164. package/src/project-graph/utils/project-configuration-utils.js +54 -21
  165. package/src/project-graph/utils/retrieve-workspace-files.d.ts +1 -1
  166. package/src/project-graph/utils/retrieve-workspace-files.js +14 -18
  167. package/src/tasks-runner/batch/batch-messages.d.ts +2 -0
  168. package/src/tasks-runner/batch/run-batch.js +3 -4
  169. package/src/tasks-runner/cache.d.ts +20 -6
  170. package/src/tasks-runner/cache.js +104 -20
  171. package/src/tasks-runner/create-task-graph.d.ts +0 -1
  172. package/src/tasks-runner/create-task-graph.js +11 -11
  173. package/src/tasks-runner/default-tasks-runner.js +5 -14
  174. package/src/tasks-runner/forked-process-task-runner.d.ts +8 -3
  175. package/src/tasks-runner/forked-process-task-runner.js +59 -46
  176. package/src/tasks-runner/init-tasks-runner.d.ts +15 -1
  177. package/src/tasks-runner/init-tasks-runner.js +62 -2
  178. package/src/tasks-runner/is-tui-enabled.d.ts +2 -0
  179. package/src/tasks-runner/is-tui-enabled.js +64 -0
  180. package/src/tasks-runner/life-cycle.d.ts +14 -3
  181. package/src/tasks-runner/life-cycle.js +37 -2
  182. package/src/tasks-runner/life-cycles/task-history-life-cycle-old.d.ts +2 -0
  183. package/src/tasks-runner/life-cycles/task-history-life-cycle-old.js +15 -7
  184. package/src/tasks-runner/life-cycles/task-history-life-cycle.d.ts +5 -0
  185. package/src/tasks-runner/life-cycles/task-history-life-cycle.js +35 -5
  186. package/src/tasks-runner/life-cycles/tui-summary-life-cycle.d.ts +18 -0
  187. package/src/tasks-runner/life-cycles/tui-summary-life-cycle.js +229 -0
  188. package/src/tasks-runner/pseudo-terminal.d.ts +10 -7
  189. package/src/tasks-runner/pseudo-terminal.js +37 -35
  190. package/src/tasks-runner/run-command.d.ts +4 -1
  191. package/src/tasks-runner/run-command.js +220 -42
  192. package/src/tasks-runner/running-tasks/node-child-process.js +4 -11
  193. package/src/tasks-runner/running-tasks/running-task.d.ts +3 -0
  194. package/src/tasks-runner/running-tasks/shared-running-task.d.ts +14 -0
  195. package/src/tasks-runner/running-tasks/shared-running-task.js +30 -0
  196. package/src/tasks-runner/task-env.d.ts +1 -4
  197. package/src/tasks-runner/task-env.js +2 -0
  198. package/src/tasks-runner/task-orchestrator.d.ts +26 -10
  199. package/src/tasks-runner/task-orchestrator.js +212 -57
  200. package/src/tasks-runner/tasks-runner.d.ts +1 -0
  201. package/src/tasks-runner/tasks-schedule.d.ts +1 -0
  202. package/src/tasks-runner/tasks-schedule.js +9 -0
  203. package/src/tasks-runner/utils.d.ts +2 -2
  204. package/src/tasks-runner/utils.js +18 -12
  205. package/src/utils/child-process.d.ts +4 -0
  206. package/src/utils/child-process.js +23 -30
  207. package/src/utils/command-line-utils.d.ts +1 -1
  208. package/src/utils/find-matching-projects.js +2 -2
  209. package/src/utils/git-utils.d.ts +1 -1
  210. package/src/utils/git-utils.js +8 -3
  211. package/src/utils/handle-errors.js +15 -0
  212. package/src/utils/is-ci.js +4 -1
  213. package/src/utils/is-using-prettier.d.ts +3 -0
  214. package/src/utils/is-using-prettier.js +62 -0
  215. package/src/utils/nx-key.d.ts +7 -0
  216. package/src/utils/nx-key.js +52 -0
  217. package/src/utils/package-json.d.ts +1 -1
  218. package/src/utils/package-json.js +16 -2
  219. package/src/utils/package-manager.js +2 -2
  220. package/src/utils/path.js +1 -1
  221. package/src/utils/require-nx-key.d.ts +1 -0
  222. package/src/utils/require-nx-key.js +22 -0
  223. package/src/utils/workspace-context.d.ts +2 -0
  224. package/src/utils/workspace-context.js +16 -0
  225. package/src/command-line/activate-powerpack/activate-powerpack.d.ts +0 -2
  226. package/src/command-line/activate-powerpack/activate-powerpack.js +0 -34
  227. package/src/command-line/activate-powerpack/command-object.d.ts +0 -6
  228. package/src/command-line/init/implementation/react/write-craco-config.d.ts +0 -1
  229. package/src/command-line/init/implementation/react/write-craco-config.js +0 -61
  230. package/src/migrations/update-17-0-0/move-cache-directory.d.ts +0 -2
  231. package/src/migrations/update-17-0-0/move-cache-directory.js +0 -35
  232. package/src/migrations/update-17-0-0/rm-default-collection-npm-scope.js +0 -72
  233. package/src/migrations/update-17-0-0/use-minimal-config-for-tasks-runner-options.d.ts +0 -2
  234. package/src/migrations/update-17-0-0/use-minimal-config-for-tasks-runner-options.js +0 -122
  235. package/src/migrations/update-17-2-0/move-default-base.d.ts +0 -5
  236. package/src/migrations/update-17-2-0/move-default-base.js +0 -21
  237. package/src/migrations/update-17-3-0/nx-release-path.d.ts +0 -3
  238. package/src/migrations/update-17-3-0/nx-release-path.js +0 -47
  239. package/src/migrations/update-18-0-0/disable-crystal-for-existing-workspaces.d.ts +0 -2
  240. package/src/migrations/update-18-0-0/disable-crystal-for-existing-workspaces.js +0 -11
  241. package/src/utils/powerpack.d.ts +0 -5
  242. package/src/utils/powerpack.js +0 -33
@@ -1,14 +1,17 @@
1
- import { TaskHasher } from '../hasher/task-hasher';
2
- import { DefaultTasksRunnerOptions } from './default-tasks-runner';
3
- import { TaskStatus } from './tasks-runner';
1
+ import { NxJsonConfiguration } from '../config/nx-json';
4
2
  import { ProjectGraph } from '../config/project-graph';
5
- import { TaskGraph } from '../config/task-graph';
3
+ import { Task, TaskGraph } from '../config/task-graph';
6
4
  import { DaemonClient } from '../daemon/client/client';
7
- import { NxJsonConfiguration } from '../config/nx-json';
5
+ import { TaskHasher } from '../hasher/task-hasher';
8
6
  import { NxArgs } from '../utils/command-line-utils';
7
+ import { DefaultTasksRunnerOptions } from './default-tasks-runner';
8
+ import { RunningTask } from './running-tasks/running-task';
9
+ import { TaskStatus } from './tasks-runner';
10
+ import { SharedRunningTask } from './running-tasks/shared-running-task';
9
11
  export declare class TaskOrchestrator {
10
12
  private readonly hasher;
11
13
  private readonly initiatingProject;
14
+ private readonly initiatingTasks;
12
15
  private readonly projectGraph;
13
16
  private readonly taskGraph;
14
17
  private readonly nxJson;
@@ -16,12 +19,16 @@ export declare class TaskOrchestrator {
16
19
  private readonly bail;
17
20
  private readonly daemon;
18
21
  private readonly outputStyle;
22
+ private readonly taskGraphForHashing;
19
23
  private taskDetails;
20
24
  private cache;
25
+ private readonly tuiEnabled;
21
26
  private forkedProcessTaskRunner;
27
+ private runningTasksService;
22
28
  private tasksSchedule;
23
29
  private batchEnv;
24
30
  private reverseTaskDeps;
31
+ private initializingTaskIds;
25
32
  private processedTasks;
26
33
  private processedBatches;
27
34
  private completedTasks;
@@ -29,25 +36,32 @@ export declare class TaskOrchestrator {
29
36
  private groups;
30
37
  private bailed;
31
38
  private runningContinuousTasks;
32
- private cleaningUp;
33
- constructor(hasher: TaskHasher, initiatingProject: string | undefined, projectGraph: ProjectGraph, taskGraph: TaskGraph, nxJson: NxJsonConfiguration, options: NxArgs & DefaultTasksRunnerOptions, bail: boolean, daemon: DaemonClient, outputStyle: string);
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);
40
+ init(): Promise<void>;
34
41
  run(): Promise<{
35
42
  [id: string]: TaskStatus;
36
43
  }>;
37
44
  private executeNextBatchOfTasksUsingTaskSchedule;
38
- private processScheduledTask;
45
+ processTasks(taskIds: string[]): void;
46
+ private processTask;
39
47
  private processScheduledBatch;
40
48
  private processAllScheduledTasks;
41
49
  private applyCachedResults;
42
50
  private applyCachedResult;
43
51
  private applyFromCacheOrRunBatch;
44
52
  private runBatch;
45
- private applyFromCacheOrRunTask;
53
+ applyFromCacheOrRunTask(doNotSkipCache: boolean, task: Task, groupId: number): Promise<{
54
+ task: Task;
55
+ code: number;
56
+ status: TaskStatus;
57
+ terminalOutput?: string;
58
+ }>;
46
59
  private runTask;
47
60
  private runTaskInForkedProcess;
48
- private startContinuousTask;
61
+ startContinuousTask(task: Task, groupId: number): Promise<RunningTask | SharedRunningTask>;
49
62
  private preRunSteps;
50
63
  private postRunSteps;
64
+ private scheduleNextTasksAndReleaseThreads;
51
65
  private complete;
52
66
  private pipeOutputCapture;
53
67
  private shouldCacheTaskResult;
@@ -56,4 +70,6 @@ export declare class TaskOrchestrator {
56
70
  private shouldCopyOutputsFromCache;
57
71
  private recordOutputsHash;
58
72
  private cleanup;
73
+ private cleanUpUnneededContinuousTasks;
59
74
  }
75
+ export declare function getThreadCount(options: NxArgs & DefaultTasksRunnerOptions, taskGraph: TaskGraph): number;
@@ -1,26 +1,33 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TaskOrchestrator = void 0;
4
+ exports.getThreadCount = getThreadCount;
4
5
  const events_1 = require("events");
5
- const perf_hooks_1 = require("perf_hooks");
6
- const path_1 = require("path");
7
6
  const fs_1 = require("fs");
7
+ const path_1 = require("path");
8
+ const perf_hooks_1 = require("perf_hooks");
8
9
  const run_commands_impl_1 = require("../executors/run-commands/run-commands.impl");
9
- const forked_process_task_runner_1 = require("./forked-process-task-runner");
10
- const cache_1 = require("./cache");
11
- const utils_1 = require("./utils");
12
- const tasks_schedule_1 = require("./tasks-schedule");
13
10
  const hash_task_1 = require("../hasher/hash-task");
14
- const task_env_1 = require("./task-env");
15
- const workspace_root_1 = require("../utils/workspace-root");
11
+ const native_1 = require("../native");
12
+ const db_connection_1 = require("../utils/db-connection");
16
13
  const output_1 = require("../utils/output");
17
14
  const params_1 = require("../utils/params");
15
+ const workspace_root_1 = require("../utils/workspace-root");
16
+ const cache_1 = require("./cache");
17
+ const forked_process_task_runner_1 = require("./forked-process-task-runner");
18
+ const is_tui_enabled_1 = require("./is-tui-enabled");
19
+ const pseudo_terminal_1 = require("./pseudo-terminal");
18
20
  const noop_child_process_1 = require("./running-tasks/noop-child-process");
21
+ const task_env_1 = require("./task-env");
22
+ const tasks_schedule_1 = require("./tasks-schedule");
23
+ const utils_1 = require("./utils");
24
+ const shared_running_task_1 = require("./running-tasks/shared-running-task");
19
25
  class TaskOrchestrator {
20
26
  // endregion internal state
21
- constructor(hasher, initiatingProject, projectGraph, taskGraph, nxJson, options, bail, daemon, outputStyle) {
27
+ constructor(hasher, initiatingProject, initiatingTasks, projectGraph, taskGraph, nxJson, options, bail, daemon, outputStyle, taskGraphForHashing = taskGraph) {
22
28
  this.hasher = hasher;
23
29
  this.initiatingProject = initiatingProject;
30
+ this.initiatingTasks = initiatingTasks;
24
31
  this.projectGraph = projectGraph;
25
32
  this.taskGraph = taskGraph;
26
33
  this.nxJson = nxJson;
@@ -28,13 +35,17 @@ class TaskOrchestrator {
28
35
  this.bail = bail;
29
36
  this.daemon = daemon;
30
37
  this.outputStyle = outputStyle;
38
+ this.taskGraphForHashing = taskGraphForHashing;
31
39
  this.taskDetails = (0, hash_task_1.getTaskDetails)();
32
40
  this.cache = (0, cache_1.getCache)(this.options);
33
- this.forkedProcessTaskRunner = new forked_process_task_runner_1.ForkedProcessTaskRunner(this.options);
41
+ this.tuiEnabled = (0, is_tui_enabled_1.isTuiEnabled)(this.nxJson);
42
+ this.forkedProcessTaskRunner = new forked_process_task_runner_1.ForkedProcessTaskRunner(this.options, this.tuiEnabled);
43
+ this.runningTasksService = new native_1.RunningTasksService((0, db_connection_1.getDbConnection)());
34
44
  this.tasksSchedule = new tasks_schedule_1.TasksSchedule(this.projectGraph, this.taskGraph, this.options);
35
45
  // region internal state
36
46
  this.batchEnv = (0, task_env_1.getEnvVariablesForBatchProcess)(this.options.skipNxCache, this.options.captureStderr);
37
47
  this.reverseTaskDeps = (0, utils_1.calculateReverseDeps)(this.taskGraph);
48
+ this.initializingTaskIds = new Set(this.initiatingTasks.map((t) => t.id));
38
49
  this.processedTasks = new Map();
39
50
  this.processedBatches = new Map();
40
51
  this.completedTasks = {};
@@ -42,20 +53,21 @@ class TaskOrchestrator {
42
53
  this.groups = [];
43
54
  this.bailed = false;
44
55
  this.runningContinuousTasks = new Map();
45
- this.cleaningUp = false;
46
56
  }
47
- async run() {
57
+ async init() {
48
58
  // Init the ForkedProcessTaskRunner, TasksSchedule, and Cache
49
59
  await Promise.all([
50
60
  this.forkedProcessTaskRunner.init(),
51
61
  this.tasksSchedule.init(),
52
62
  'init' in this.cache ? this.cache.init() : null,
53
63
  ]);
64
+ }
65
+ async run() {
66
+ await this.init();
54
67
  // initial scheduling
55
68
  await this.tasksSchedule.scheduleNextTasks();
56
69
  perf_hooks_1.performance.mark('task-execution:start');
57
- const threadCount = this.options.parallel +
58
- Object.values(this.taskGraph.tasks).filter((t) => t.continuous).length;
70
+ const threadCount = getThreadCount(this.options, this.taskGraph);
59
71
  const threads = [];
60
72
  process.stdout.setMaxListeners(threadCount + events_1.defaultMaxListeners);
61
73
  process.stderr.setMaxListeners(threadCount + events_1.defaultMaxListeners);
@@ -63,7 +75,19 @@ class TaskOrchestrator {
63
75
  for (let i = 0; i < threadCount; ++i) {
64
76
  threads.push(this.executeNextBatchOfTasksUsingTaskSchedule());
65
77
  }
66
- await Promise.all(threads);
78
+ await Promise.race([
79
+ Promise.all(threads),
80
+ ...(this.tuiEnabled
81
+ ? [
82
+ new Promise((resolve) => {
83
+ this.options.lifeCycle.registerForcedShutdownCallback(() => {
84
+ // The user force quit the TUI with ctrl+c, so proceed onto cleanup
85
+ resolve(undefined);
86
+ });
87
+ }),
88
+ ]
89
+ : []),
90
+ ]);
67
91
  perf_hooks_1.performance.mark('task-execution:end');
68
92
  perf_hooks_1.performance.measure('task-execution', 'task-execution:start', 'task-execution:end');
69
93
  this.cache.removeOldCacheRecords();
@@ -100,12 +124,20 @@ class TaskOrchestrator {
100
124
  // block until some other task completes, then try again
101
125
  return new Promise((res) => this.waitingForTasks.push(res)).then(() => this.executeNextBatchOfTasksUsingTaskSchedule());
102
126
  }
127
+ processTasks(taskIds) {
128
+ for (const taskId of taskIds) {
129
+ // Task is already handled or being handled
130
+ if (!this.processedTasks.has(taskId)) {
131
+ this.processedTasks.set(taskId, this.processTask(taskId));
132
+ }
133
+ }
134
+ }
103
135
  // region Processing Scheduled Tasks
104
- async processScheduledTask(taskId) {
136
+ async processTask(taskId) {
105
137
  const task = this.taskGraph.tasks[taskId];
106
138
  const taskSpecificEnv = (0, task_env_1.getTaskSpecificEnv)(task);
107
139
  if (!task.hash) {
108
- await (0, hash_task_1.hashTask)(this.hasher, this.projectGraph, this.taskGraph, task, taskSpecificEnv, this.taskDetails);
140
+ await (0, hash_task_1.hashTask)(this.hasher, this.projectGraph, this.taskGraphForHashing, task, taskSpecificEnv, this.taskDetails);
109
141
  }
110
142
  await this.options.lifeCycle.scheduleTask(task);
111
143
  return taskSpecificEnv;
@@ -113,7 +145,7 @@ class TaskOrchestrator {
113
145
  async processScheduledBatch(batch) {
114
146
  await Promise.all(Object.values(batch.taskGraph.tasks).map(async (task) => {
115
147
  if (!task.hash) {
116
- await (0, hash_task_1.hashTask)(this.hasher, this.projectGraph, this.taskGraph, task, this.batchEnv, this.taskDetails);
148
+ await (0, hash_task_1.hashTask)(this.hasher, this.projectGraph, this.taskGraphForHashing, task, this.batchEnv, this.taskDetails);
117
149
  }
118
150
  await this.options.lifeCycle.scheduleTask(task);
119
151
  }));
@@ -123,12 +155,7 @@ class TaskOrchestrator {
123
155
  for (const batch of scheduledBatches) {
124
156
  this.processedBatches.set(batch, this.processScheduledBatch(batch));
125
157
  }
126
- for (const taskId of scheduledTasks) {
127
- // Task is already handled or being handled
128
- if (!this.processedTasks.has(taskId)) {
129
- this.processedTasks.set(taskId, this.processScheduledTask(taskId));
130
- }
131
- }
158
+ this.processTasks(scheduledTasks);
132
159
  }
133
160
  // endregion Processing Scheduled Tasks
134
161
  // region Applying Cache
@@ -142,7 +169,12 @@ class TaskOrchestrator {
142
169
  if (!cachedResult || cachedResult.code !== 0)
143
170
  return null;
144
171
  const outputs = task.outputs;
145
- const shouldCopyOutputsFromCache = !!outputs.length &&
172
+ const shouldCopyOutputsFromCache =
173
+ // No output files to restore
174
+ !!outputs.length &&
175
+ // Remote caches are restored to output dirs when applied and using db cache
176
+ (!cachedResult.remote || !(0, cache_1.dbCacheEnabled)(this.nxJson)) &&
177
+ // Output files have not been touched since last run
146
178
  (await this.shouldCopyOutputsFromCache(outputs, task.hash));
147
179
  if (shouldCopyOutputsFromCache) {
148
180
  await this.cache.copyFilesFromCache(task.hash, cachedResult, outputs);
@@ -154,6 +186,7 @@ class TaskOrchestrator {
154
186
  : 'local-cache-kept-existing';
155
187
  this.options.lifeCycle.printTaskTerminalOutput(task, status, cachedResult.terminalOutput);
156
188
  return {
189
+ code: cachedResult.code,
157
190
  task,
158
191
  status,
159
192
  };
@@ -177,6 +210,7 @@ class TaskOrchestrator {
177
210
  results.push(...batchResults);
178
211
  }
179
212
  await this.postRunSteps(tasks, results, doNotSkipCache, { groupId });
213
+ this.forkedProcessTaskRunner.cleanUpBatchProcesses();
180
214
  const tasksCompleted = taskEntries.filter(([taskId]) => this.completedTasks[taskId]);
181
215
  // Batch is still not done, run it again
182
216
  if (tasksCompleted.length !== taskEntries.length) {
@@ -188,7 +222,7 @@ class TaskOrchestrator {
188
222
  }
189
223
  async runBatch(batch, env) {
190
224
  try {
191
- const batchProcess = await this.forkedProcessTaskRunner.forkProcessForBatch(batch, this.taskGraph, env);
225
+ const batchProcess = await this.forkedProcessTaskRunner.forkProcessForBatch(batch, this.projectGraph, this.taskGraph, env);
192
226
  const results = await batchProcess.getResults();
193
227
  const batchResultEntries = Object.entries(results);
194
228
  return batchResultEntries.map(([taskId, result]) => ({
@@ -233,11 +267,13 @@ class TaskOrchestrator {
233
267
  const { code, terminalOutput } = await childProcess.getResults();
234
268
  results.push({
235
269
  task,
270
+ code,
236
271
  status: code === 0 ? 'success' : 'failure',
237
272
  terminalOutput,
238
273
  });
239
274
  }
240
275
  await this.postRunSteps([task], results, doNotSkipCache, { groupId });
276
+ return results[0];
241
277
  }
242
278
  async runTask(task, streamOutput, env, temporaryOutputPath, pipeOutput) {
243
279
  const shouldPrefix = streamOutput && process.env.NX_PREFIX_OUTPUT === 'true';
@@ -247,7 +283,6 @@ class TaskOrchestrator {
247
283
  !shouldPrefix) {
248
284
  try {
249
285
  const { schema } = (0, utils_1.getExecutorForTask)(task, this.projectGraph);
250
- const isRunOne = this.initiatingProject != null;
251
286
  const combinedOptions = (0, params_1.combineOptionsForExecutor)(task.overrides, task.target.configuration ?? targetConfiguration.defaultConfiguration, targetConfiguration, schema, task.target.project, (0, path_1.relative)(task.projectRoot ?? workspace_root_1.workspaceRoot, process.cwd()), process.env.NX_VERBOSE_LOGGING === 'true');
252
287
  if (combinedOptions.env) {
253
288
  env = {
@@ -259,22 +294,48 @@ class TaskOrchestrator {
259
294
  const args = (0, utils_1.getPrintableCommandArgsForTask)(task);
260
295
  output_1.output.logCommand(args.join(' '));
261
296
  }
262
- const runningTask = await (0, run_commands_impl_1.runCommands)({
297
+ const runCommandsOptions = {
263
298
  ...combinedOptions,
264
299
  env,
265
- usePty: isRunOne &&
266
- !this.tasksSchedule.hasTasks() &&
267
- this.runningContinuousTasks.size === 0,
300
+ usePty: this.tuiEnabled ||
301
+ (!this.tasksSchedule.hasTasks() &&
302
+ this.runningContinuousTasks.size === 0),
268
303
  streamOutput,
269
- }, {
304
+ };
305
+ const runningTask = await (0, run_commands_impl_1.runCommands)(runCommandsOptions, {
270
306
  root: workspace_root_1.workspaceRoot, // only root is needed in runCommands
271
307
  });
272
- runningTask.onExit((code, terminalOutput) => {
273
- if (!streamOutput) {
274
- this.options.lifeCycle.printTaskTerminalOutput(task, code === 0 ? 'success' : 'failure', terminalOutput);
275
- (0, fs_1.writeFileSync)(temporaryOutputPath, terminalOutput);
308
+ if (this.tuiEnabled) {
309
+ if (runningTask instanceof pseudo_terminal_1.PseudoTtyProcess) {
310
+ // This is an external of a the pseudo terminal where a task is running and can be passed to the TUI
311
+ this.options.lifeCycle.registerRunningTask(task.id, runningTask.getParserAndWriter());
276
312
  }
277
- });
313
+ else {
314
+ this.options.lifeCycle.registerRunningTaskWithEmptyParser(task.id);
315
+ runningTask.onOutput((output) => {
316
+ this.options.lifeCycle.appendTaskOutput(task.id, output);
317
+ });
318
+ }
319
+ }
320
+ if (!streamOutput) {
321
+ if (runningTask instanceof pseudo_terminal_1.PseudoTtyProcess) {
322
+ // TODO: shouldn't this be checking if the task is continuous before writing anything to disk or calling printTaskTerminalOutput?
323
+ let terminalOutput = '';
324
+ runningTask.onOutput((data) => {
325
+ terminalOutput += data;
326
+ });
327
+ runningTask.onExit((code) => {
328
+ this.options.lifeCycle.printTaskTerminalOutput(task, code === 0 ? 'success' : 'failure', terminalOutput);
329
+ (0, fs_1.writeFileSync)(temporaryOutputPath, terminalOutput);
330
+ });
331
+ }
332
+ else {
333
+ runningTask.onExit((code, terminalOutput) => {
334
+ this.options.lifeCycle.printTaskTerminalOutput(task, code === 0 ? 'success' : 'failure', terminalOutput);
335
+ (0, fs_1.writeFileSync)(temporaryOutputPath, terminalOutput);
336
+ });
337
+ }
338
+ }
278
339
  return runningTask;
279
340
  }
280
341
  catch (e) {
@@ -286,6 +347,10 @@ class TaskOrchestrator {
286
347
  }
287
348
  const terminalOutput = e.stack ?? e.message ?? '';
288
349
  (0, fs_1.writeFileSync)(temporaryOutputPath, terminalOutput);
350
+ return new noop_child_process_1.NoopChildProcess({
351
+ code: 1,
352
+ terminalOutput,
353
+ });
289
354
  }
290
355
  }
291
356
  else if (targetConfiguration.executor === 'nx:noop') {
@@ -297,14 +362,27 @@ class TaskOrchestrator {
297
362
  }
298
363
  else {
299
364
  // cache prep
300
- return await this.runTaskInForkedProcess(task, env, pipeOutput, temporaryOutputPath, streamOutput);
365
+ const runningTask = await this.runTaskInForkedProcess(task, env, pipeOutput, temporaryOutputPath, streamOutput);
366
+ if (this.tuiEnabled) {
367
+ if (runningTask instanceof pseudo_terminal_1.PseudoTtyProcess) {
368
+ // This is an external of a the pseudo terminal where a task is running and can be passed to the TUI
369
+ this.options.lifeCycle.registerRunningTask(task.id, runningTask.getParserAndWriter());
370
+ }
371
+ else if ('onOutput' in runningTask) {
372
+ this.options.lifeCycle.registerRunningTaskWithEmptyParser(task.id);
373
+ runningTask.onOutput((output) => {
374
+ this.options.lifeCycle.appendTaskOutput(task.id, output);
375
+ });
376
+ }
377
+ }
378
+ return runningTask;
301
379
  }
302
380
  }
303
381
  async runTaskInForkedProcess(task, env, pipeOutput, temporaryOutputPath, streamOutput) {
304
382
  try {
305
383
  const usePtyFork = process.env.NX_NATIVE_COMMAND_RUNNER !== 'false';
306
384
  // Disable the pseudo terminal if this is a run-many or when running a continuous task as part of a run-one
307
- const disablePseudoTerminal = !this.initiatingProject || task.continuous;
385
+ const disablePseudoTerminal = !this.tuiEnabled && (!this.initiatingProject || task.continuous);
308
386
  // execution
309
387
  const childProcess = usePtyFork
310
388
  ? await this.forkedProcessTaskRunner.forkProcess(task, {
@@ -335,6 +413,36 @@ class TaskOrchestrator {
335
413
  }
336
414
  }
337
415
  async startContinuousTask(task, groupId) {
416
+ if (this.runningTasksService.getRunningTasks([task.id]).length) {
417
+ await this.preRunSteps([task], { groupId });
418
+ if (this.tuiEnabled) {
419
+ this.options.lifeCycle.setTaskStatus(task.id, 8 /* NativeTaskStatus.Shared */);
420
+ }
421
+ const runningTask = new shared_running_task_1.SharedRunningTask(this.runningTasksService, task.id);
422
+ this.runningContinuousTasks.set(task.id, runningTask);
423
+ runningTask.onExit(() => {
424
+ if (this.tuiEnabled) {
425
+ this.options.lifeCycle.setTaskStatus(task.id, 9 /* NativeTaskStatus.Stopped */);
426
+ }
427
+ this.runningContinuousTasks.delete(task.id);
428
+ });
429
+ // task is already running by another process, we schedule the next tasks
430
+ // and release the threads
431
+ await this.scheduleNextTasksAndReleaseThreads();
432
+ if (this.initializingTaskIds.has(task.id)) {
433
+ await new Promise((res) => {
434
+ runningTask.onExit((code) => {
435
+ if (!this.tuiEnabled) {
436
+ if (code > 128) {
437
+ process.exit(code);
438
+ }
439
+ }
440
+ res();
441
+ });
442
+ });
443
+ }
444
+ return runningTask;
445
+ }
338
446
  const taskSpecificEnv = await this.processedTasks.get(task.id);
339
447
  await this.preRunSteps([task], { groupId });
340
448
  const pipeOutput = await this.pipeOutputCapture(task);
@@ -349,25 +457,27 @@ class TaskOrchestrator {
349
457
  : process.env.FORCE_COLOR, this.options.skipNxCache, this.options.captureStderr, null, null)
350
458
  : (0, task_env_1.getEnvVariablesForTask)(task, taskSpecificEnv, undefined, this.options.skipNxCache, this.options.captureStderr, temporaryOutputPath, streamOutput);
351
459
  const childProcess = await this.runTask(task, streamOutput, env, temporaryOutputPath, pipeOutput);
460
+ this.runningTasksService.addRunningTask(task.id);
352
461
  this.runningContinuousTasks.set(task.id, childProcess);
353
- childProcess.onExit((code) => {
354
- if (!this.cleaningUp) {
355
- console.error(`Task "${task.id}" is continuous but exited with code ${code}`);
356
- this.cleanup().then(() => {
357
- process.exit(1);
358
- });
462
+ childProcess.onExit(() => {
463
+ if (this.tuiEnabled) {
464
+ this.options.lifeCycle.setTaskStatus(task.id, 9 /* NativeTaskStatus.Stopped */);
359
465
  }
466
+ this.runningTasksService.removeRunningTask(task.id);
467
+ this.runningContinuousTasks.delete(task.id);
360
468
  });
361
- if (this.initiatingProject === task.target.project &&
362
- this.options.targets.length === 1 &&
363
- this.options.targets[0] === task.target.target) {
364
- await childProcess.getResults();
365
- }
366
- else {
367
- await this.tasksSchedule.scheduleNextTasks();
368
- // release blocked threads
369
- this.waitingForTasks.forEach((f) => f(null));
370
- this.waitingForTasks.length = 0;
469
+ await this.scheduleNextTasksAndReleaseThreads();
470
+ if (this.initializingTaskIds.has(task.id)) {
471
+ await new Promise((res) => {
472
+ childProcess.onExit((code) => {
473
+ if (!this.tuiEnabled) {
474
+ if (code > 128) {
475
+ process.exit(code);
476
+ }
477
+ }
478
+ res();
479
+ });
480
+ });
371
481
  }
372
482
  return childProcess;
373
483
  }
@@ -430,6 +540,9 @@ class TaskOrchestrator {
430
540
  status,
431
541
  };
432
542
  }));
543
+ await this.scheduleNextTasksAndReleaseThreads();
544
+ }
545
+ async scheduleNextTasksAndReleaseThreads() {
433
546
  await this.tasksSchedule.scheduleNextTasks();
434
547
  // release blocked threads
435
548
  this.waitingForTasks.forEach((f) => f(null));
@@ -437,9 +550,13 @@ class TaskOrchestrator {
437
550
  }
438
551
  complete(taskResults) {
439
552
  this.tasksSchedule.complete(taskResults.map(({ taskId }) => taskId));
553
+ this.cleanUpUnneededContinuousTasks();
440
554
  for (const { taskId, status } of taskResults) {
441
555
  if (this.completedTasks[taskId] === undefined) {
442
556
  this.completedTasks[taskId] = status;
557
+ if (this.tuiEnabled) {
558
+ this.options.lifeCycle.setTaskStatus(taskId, (0, native_1.parseTaskStatus)(status));
559
+ }
443
560
  if (status === 'failure' || status === 'skipped') {
444
561
  if (this.bail) {
445
562
  // mark the execution as bailed which will stop all further execution
@@ -503,15 +620,53 @@ class TaskOrchestrator {
503
620
  }
504
621
  // endregion utils
505
622
  async cleanup() {
506
- this.cleaningUp = true;
507
623
  await Promise.all(Array.from(this.runningContinuousTasks).map(async ([taskId, t]) => {
508
624
  try {
509
- return t.kill();
625
+ await t.kill();
626
+ this.options.lifeCycle.setTaskStatus(taskId, 9 /* NativeTaskStatus.Stopped */);
510
627
  }
511
628
  catch (e) {
512
629
  console.error(`Unable to terminate ${taskId}\nError:`, e);
513
630
  }
631
+ finally {
632
+ this.runningTasksService.removeRunningTask(taskId);
633
+ }
514
634
  }));
515
635
  }
636
+ cleanUpUnneededContinuousTasks() {
637
+ const incompleteTasks = this.tasksSchedule.getIncompleteTasks();
638
+ const neededContinuousTasks = new Set(this.initializingTaskIds);
639
+ for (const task of incompleteTasks) {
640
+ const continuousDependencies = this.taskGraph.continuousDependencies[task.id];
641
+ for (const continuousDependency of continuousDependencies) {
642
+ neededContinuousTasks.add(continuousDependency);
643
+ }
644
+ }
645
+ for (const taskId of this.runningContinuousTasks.keys()) {
646
+ if (!neededContinuousTasks.has(taskId)) {
647
+ const runningTask = this.runningContinuousTasks.get(taskId);
648
+ if (runningTask) {
649
+ runningTask.kill();
650
+ this.options.lifeCycle.setTaskStatus(taskId, 9 /* NativeTaskStatus.Stopped */);
651
+ }
652
+ }
653
+ }
654
+ }
516
655
  }
517
656
  exports.TaskOrchestrator = TaskOrchestrator;
657
+ function getThreadCount(options, taskGraph) {
658
+ if (options['parallel'] === 'false' ||
659
+ options['parallel'] === false) {
660
+ options['parallel'] = 1;
661
+ }
662
+ else if (options['parallel'] === 'true' ||
663
+ options['parallel'] === true ||
664
+ options['parallel'] === undefined ||
665
+ options['parallel'] === '') {
666
+ options['parallel'] = Number(options['maxParallel'] || 3);
667
+ }
668
+ const maxParallel = options['parallel'] +
669
+ Object.values(taskGraph.tasks).filter((t) => t.continuous).length;
670
+ const totalTasks = Object.keys(taskGraph.tasks).length;
671
+ return Math.min(maxParallel, totalTasks);
672
+ }
@@ -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;
@@ -31,6 +31,7 @@ export declare class TasksSchedule {
31
31
  };
32
32
  nextTask(): Task;
33
33
  nextBatch(): Batch;
34
+ getIncompleteTasks(): Task[];
34
35
  private scheduleTasks;
35
36
  private scheduleTask;
36
37
  private scheduleBatches;
@@ -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();
@@ -1,7 +1,7 @@
1
- import { Task, TaskGraph } from '../config/task-graph';
1
+ import { CustomHasher, ExecutorConfig } from '../config/misc-interfaces';
2
2
  import { ProjectGraph, ProjectGraphProjectNode } from '../config/project-graph';
3
+ import { Task, TaskGraph } from '../config/task-graph';
3
4
  import { TargetConfiguration, TargetDependencyConfig } from '../config/workspace-json-project-json';
4
- import { CustomHasher, ExecutorConfig } from '../config/misc-interfaces';
5
5
  export type NormalizedTargetDependencyConfig = TargetDependencyConfig & {
6
6
  projects: string[];
7
7
  };