nx 21.0.0-beta.10 → 21.0.0-beta.11

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/migrations.json +10 -0
  2. package/package.json +11 -11
  3. package/schemas/nx-schema.json +5 -0
  4. package/src/adapter/angular-json.js +11 -0
  5. package/src/command-line/migrate/migrate-ui-api.js +1 -1
  6. package/src/command-line/migrate/migrate.d.ts +12 -6
  7. package/src/command-line/migrate/migrate.js +31 -9
  8. package/src/command-line/repair/repair.js +8 -2
  9. package/src/command-line/report/report.js +1 -1
  10. package/src/config/misc-interfaces.d.ts +9 -1
  11. package/src/config/nx-json.d.ts +0 -4
  12. package/src/core/graph/main.js +1 -1
  13. package/src/devkit-exports.d.ts +1 -1
  14. package/src/migrations/update-21-0-0/remove-custom-tasks-runner.d.ts +2 -0
  15. package/src/migrations/update-21-0-0/remove-custom-tasks-runner.js +38 -0
  16. package/src/migrations/update-21-0-0/remove-legacy-cache.d.ts +2 -0
  17. package/src/migrations/update-21-0-0/remove-legacy-cache.js +17 -0
  18. package/src/native/nx.wasm32-wasi.wasm +0 -0
  19. package/src/plugins/js/index.d.ts +2 -1
  20. package/src/plugins/js/index.js +8 -1
  21. package/src/project-graph/plugins/loaded-nx-plugin.js +1 -5
  22. package/src/tasks-runner/batch/run-batch.js +1 -1
  23. package/src/tasks-runner/cache.d.ts +1 -2
  24. package/src/tasks-runner/cache.js +2 -18
  25. package/src/tasks-runner/life-cycles/tui-summary-life-cycle.js +8 -7
  26. package/src/tasks-runner/pseudo-terminal.d.ts +1 -0
  27. package/src/tasks-runner/pseudo-terminal.js +11 -1
  28. package/src/tasks-runner/run-command.js +2 -24
  29. package/src/tasks-runner/task-graph-utils.d.ts +3 -0
  30. package/src/tasks-runner/task-graph-utils.js +31 -2
  31. package/src/tasks-runner/task-orchestrator.js +10 -1
@@ -13,7 +13,7 @@ export type { WorkspaceJsonConfiguration, ProjectsConfigurations, TargetDependen
13
13
  /**
14
14
  * @category Workspace
15
15
  */
16
- export type { Generator, GeneratorCallback, PromiseExecutor, AsyncIteratorExecutor, Executor, ExecutorContext, TaskGraphExecutor, GeneratorsJson, ExecutorsJson, MigrationsJson, CustomHasher, HasherContext, } from './config/misc-interfaces';
16
+ export type { Generator, Migration, GeneratorCallback, PromiseExecutor, AsyncIteratorExecutor, Executor, ExecutorContext, TaskGraphExecutor, GeneratorsJson, ExecutorsJson, MigrationsJson, CustomHasher, HasherContext, } from './config/misc-interfaces';
17
17
  export { workspaceLayout } from './config/configuration';
18
18
  export type { NxPlugin, NxPluginV2, CreateNodes, CreateNodesFunction, CreateNodesResult, CreateNodesContext, CreateNodesContextV2, CreateNodesFunctionV2, CreateNodesResultV2, CreateNodesV2, CreateDependencies, CreateDependenciesContext, CreateMetadata, CreateMetadataContext, ProjectsMetadata, PreTasksExecution, PreTasksExecutionContext, PostTasksExecution, PostTasksExecutionContext, } from './project-graph/plugins';
19
19
  export { AggregateCreateNodesError, StaleProjectGraphCacheError, } from './project-graph/error-types';
@@ -0,0 +1,2 @@
1
+ import { Tree } from '../../generators/tree';
2
+ export default function update(tree: Tree): Promise<string[]>;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = update;
4
+ const format_changed_files_with_prettier_if_available_1 = require("../../generators/internal-utils/format-changed-files-with-prettier-if-available");
5
+ const nx_json_1 = require("../../generators/utils/nx-json");
6
+ function isCustomRunnerPath(modulePath) {
7
+ return !['nx-cloud', '@nrwl/nx-cloud', 'nx/tasks-runners/default'].includes(modulePath);
8
+ }
9
+ async function update(tree) {
10
+ const nxJson = (0, nx_json_1.readNxJson)(tree);
11
+ if (!nxJson?.tasksRunnerOptions) {
12
+ return;
13
+ }
14
+ const nextSteps = [];
15
+ for (const key in nxJson.tasksRunnerOptions) {
16
+ const runner = nxJson.tasksRunnerOptions[key].runner;
17
+ if (runner && isCustomRunnerPath(runner)) {
18
+ let nextStepText = 'Nx 21 removed support for custom task runners. For more information, please check: ';
19
+ if (runner === '@nx-aws-cache/nx-aws-cache') {
20
+ nextStepText +=
21
+ 'https://nx.dev/deprecated/custom-tasks-runner#migrating-from-nxawsplugin';
22
+ }
23
+ else {
24
+ nextStepText += 'https://nx.dev/deprecated/custom-tasks-runner';
25
+ }
26
+ if (nextSteps.length === 0) {
27
+ nextSteps.push(nextStepText);
28
+ }
29
+ delete nxJson.tasksRunnerOptions[key];
30
+ }
31
+ }
32
+ if (Object.keys(nxJson.tasksRunnerOptions).length === 0) {
33
+ delete nxJson.tasksRunnerOptions;
34
+ }
35
+ (0, nx_json_1.updateNxJson)(tree, nxJson);
36
+ await (0, format_changed_files_with_prettier_if_available_1.formatChangedFilesWithPrettierIfAvailable)(tree);
37
+ return nextSteps;
38
+ }
@@ -0,0 +1,2 @@
1
+ import { Tree } from '../../generators/tree';
2
+ export default function update(tree: Tree): Promise<void>;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = update;
4
+ const format_changed_files_with_prettier_if_available_1 = require("../../generators/internal-utils/format-changed-files-with-prettier-if-available");
5
+ const nx_json_1 = require("../../generators/utils/nx-json");
6
+ async function update(tree) {
7
+ const nxJson = (0, nx_json_1.readNxJson)(tree);
8
+ if (!nxJson) {
9
+ return;
10
+ }
11
+ // If workspaces had `useLegacyCache` we can just delete the property as the property is not functional in nx v21
12
+ if (nxJson.useLegacyCache) {
13
+ delete nxJson.useLegacyCache;
14
+ }
15
+ (0, nx_json_1.updateNxJson)(tree, nxJson);
16
+ await (0, format_changed_files_with_prettier_if_available_1.formatChangedFilesWithPrettierIfAvailable)(tree);
17
+ }
Binary file
@@ -1,4 +1,5 @@
1
- import { CreateDependencies, CreateNodes } from '../../project-graph/plugins';
1
+ import { CreateDependencies, CreateNodes, CreateNodesV2 } from '../../project-graph/plugins';
2
2
  export declare const name = "nx/js/dependencies-and-lockfile";
3
+ export declare const createNodesV2: CreateNodesV2;
3
4
  export declare const createNodes: CreateNodes;
4
5
  export declare const createDependencies: CreateDependencies;
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createDependencies = exports.createNodes = exports.name = void 0;
3
+ exports.createDependencies = exports.createNodes = exports.createNodesV2 = exports.name = void 0;
4
4
  const fs_1 = require("fs");
5
5
  const path_1 = require("path");
6
6
  const perf_hooks_1 = require("perf_hooks");
7
7
  const cache_directory_1 = require("../../utils/cache-directory");
8
8
  const globs_1 = require("../../utils/globs");
9
+ const plugins_1 = require("../../project-graph/plugins");
9
10
  const lock_file_1 = require("./lock-file/lock-file");
10
11
  const build_dependencies_1 = require("./project-graph/build-dependencies/build-dependencies");
11
12
  const config_1 = require("./utils/config");
@@ -16,6 +17,12 @@ const versions_1 = require("../../utils/versions");
16
17
  const child_process_1 = require("child_process");
17
18
  exports.name = 'nx/js/dependencies-and-lockfile';
18
19
  let parsedLockFile = {};
20
+ exports.createNodesV2 = [
21
+ (0, globs_1.combineGlobPatterns)(lock_file_1.LOCKFILES),
22
+ (files, _, context) => {
23
+ return (0, plugins_1.createNodesFromFiles)(exports.createNodes[1], files, _, context);
24
+ },
25
+ ];
19
26
  exports.createNodes = [
20
27
  // Look for all lockfiles
21
28
  (0, globs_1.combineGlobPatterns)(lock_file_1.LOCKFILES),
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LoadedNxPlugin = void 0;
4
4
  const error_types_1 = require("../error-types");
5
- const utils_1 = require("./utils");
6
5
  const enabled_1 = require("./isolation/enabled");
7
6
  const client_1 = require("../../daemon/client/client");
8
7
  class LoadedNxPlugin {
@@ -14,10 +13,7 @@ class LoadedNxPlugin {
14
13
  this.exclude = pluginDefinition.exclude;
15
14
  }
16
15
  if (plugin.createNodes && !plugin.createNodesV2) {
17
- this.createNodes = [
18
- plugin.createNodes[0],
19
- (configFiles, context) => (0, utils_1.createNodesFromFiles)(plugin.createNodes[1], configFiles, this.options, context).then((results) => results.map((r) => [this.name, r[0], r[1]])),
20
- ];
16
+ throw new Error(`Plugin ${plugin.name} only provides \`createNodes\` which was removed in Nx 21, it should provide a \`createNodesV2\` implementation.`);
21
17
  }
22
18
  if (plugin.createNodesV2) {
23
19
  this.createNodes = [
@@ -32,7 +32,7 @@ async function runTasks(executorName, projectGraph, batchTaskGraph, fullTaskGrap
32
32
  input[task.id] = (0, params_1.combineOptionsForExecutor)(task.overrides, task.target.configuration, targetConfiguration, batchExecutor.schema, null, process.cwd());
33
33
  }
34
34
  try {
35
- const results = await batchExecutor.batchImplementationFactory()(batchTaskGraph, input, tasks[0].overrides, context);
35
+ const results = await batchExecutor.batchImplementationFactory()(batchTaskGraph, input, tasks[tasks.length - 1].overrides, context);
36
36
  if (typeof results !== 'object') {
37
37
  throw new Error(`"${executorName} returned invalid results: ${results}`);
38
38
  }
@@ -1,6 +1,5 @@
1
1
  import { DefaultTasksRunnerOptions, RemoteCache } from './default-tasks-runner';
2
2
  import { Task } from '../config/task-graph';
3
- import { NxJsonConfiguration } from '../config/nx-json';
4
3
  export type CachedResult = {
5
4
  terminalOutput: string;
6
5
  outputsPath: string;
@@ -11,7 +10,7 @@ export type TaskWithCachedResult = {
11
10
  task: Task;
12
11
  cachedResult: CachedResult;
13
12
  };
14
- export declare function dbCacheEnabled(nxJson?: NxJsonConfiguration): boolean;
13
+ export declare function dbCacheEnabled(): boolean;
15
14
  export declare function getCache(options: DefaultTasksRunnerOptions): DbCache | Cache;
16
15
  export declare class DbCache {
17
16
  private readonly options;
@@ -24,23 +24,7 @@ const is_ci_1 = require("../utils/is-ci");
24
24
  const output_1 = require("../utils/output");
25
25
  const logger_1 = require("../utils/logger");
26
26
  // This function is called once during tasks runner initialization. It checks if the db cache is enabled and logs a warning if it is not.
27
- function dbCacheEnabled(nxJson = (0, nx_json_1.readNxJson)()) {
28
- // If the user has explicitly disabled the db cache, we can warn...
29
- if (nxJson.useLegacyCache ||
30
- process.env.NX_DISABLE_DB === 'true' ||
31
- process.env.NX_DB_CACHE === 'false') {
32
- let readMoreLink = 'https://nx.dev/deprecated/legacy-cache';
33
- if (nxJson.tasksRunnerOptions?.default?.runner &&
34
- !['nx-cloud', 'nx/tasks-runners/default', '@nrwl/nx-cloud'].includes(nxJson.tasksRunnerOptions.default.runner)) {
35
- readMoreLink += '#tasksrunneroptions';
36
- }
37
- else if (process.env.NX_REJECT_UNKNOWN_LOCAL_CACHE === '0' ||
38
- process.env.NX_REJECT_UNKNOWN_LOCAL_CACHE === 'false') {
39
- readMoreLink += '#nxrejectunknownlocalcache';
40
- }
41
- logger_1.logger.warn(`Nx is configured to use the legacy cache. This cache will be removed in Nx 21. Read more at ${readMoreLink}.`);
42
- return false;
43
- }
27
+ function dbCacheEnabled() {
44
28
  // ...but if on wasm and the the db cache isnt supported we shouldn't warn
45
29
  if (native_1.IS_WASM) {
46
30
  return false;
@@ -59,7 +43,7 @@ function dbCacheEnabled(nxJson = (0, nx_json_1.readNxJson)()) {
59
43
  // Do not change the order of these arguments as this function is used by nx cloud
60
44
  function getCache(options) {
61
45
  const nxJson = (0, nx_json_1.readNxJson)();
62
- return dbCacheEnabled(nxJson)
46
+ return dbCacheEnabled()
63
47
  ? new DbCache({
64
48
  // Remove this in Nx 21
65
49
  nxCloudRemoteCache: (0, nx_cloud_utils_1.isNxCloudUsed)(nxJson) ? options.remoteCache : null,
@@ -20,10 +20,10 @@ function getTuiTerminalSummaryLifeCycle({ projectNames, tasks, args, overrides,
20
20
  let totalSuccessfulTasks = 0;
21
21
  let totalFailedTasks = 0;
22
22
  let totalCompletedTasks = 0;
23
- let totalStoppedTasks = 0;
24
23
  let timeTakenText;
25
24
  const failedTasks = new Set();
26
25
  const inProgressTasks = new Set();
26
+ const stoppedTasks = new Set();
27
27
  const tasksToTerminalOutputs = {};
28
28
  const taskIdsInOrderOfCompletion = [];
29
29
  lifeCycle.startTasks = (tasks) => {
@@ -37,7 +37,8 @@ function getTuiTerminalSummaryLifeCycle({ projectNames, tasks, args, overrides,
37
37
  };
38
38
  lifeCycle.setTaskStatus = (taskId, taskStatus) => {
39
39
  if (taskStatus === 9 /* NativeTaskStatus.Stopped */) {
40
- totalStoppedTasks++;
40
+ stoppedTasks.add(taskId);
41
+ inProgressTasks.delete(taskId);
41
42
  }
42
43
  };
43
44
  lifeCycle.endTasks = (taskResults) => {
@@ -83,7 +84,7 @@ function getTuiTerminalSummaryLifeCycle({ projectNames, tasks, args, overrides,
83
84
  };
84
85
  const printRunOneSummary = () => {
85
86
  let lines = [];
86
- const failure = totalSuccessfulTasks + totalStoppedTasks !== totalTasks;
87
+ const failure = totalSuccessfulTasks + stoppedTasks.size !== totalTasks;
87
88
  // Prints task outputs in the order they were completed
88
89
  // above the summary, since run-one should print all task results.
89
90
  for (const taskId of taskIdsInOrderOfCompletion) {
@@ -107,7 +108,7 @@ function getTuiTerminalSummaryLifeCycle({ projectNames, tasks, args, overrides,
107
108
  }
108
109
  lines = [output_1.output.colors.green(lines.join(node_os_1.EOL))];
109
110
  }
110
- else if (totalCompletedTasks + totalStoppedTasks === totalTasks) {
111
+ else if (totalCompletedTasks + stoppedTasks.size === totalTasks) {
111
112
  let text = `Ran target ${output_1.output.bold(targets[0])} for project ${output_1.output.bold(initiatingProject)}`;
112
113
  if (tasks.length > 1) {
113
114
  text += ` and ${output_1.output.bold(tasks.length - 1)} task(s) they depend on`;
@@ -129,7 +130,7 @@ function getTuiTerminalSummaryLifeCycle({ projectNames, tasks, args, overrides,
129
130
  `${LEFT_PAD}${output_1.output.colors.red(figures.cross)}${SPACER}${totalFailedTasks}${`/${totalCompletedTasks}`} failed`,
130
131
  `${LEFT_PAD}${output_1.output.dim(figures.tick)}${SPACER}${totalSuccessfulTasks}${`/${totalCompletedTasks}`} succeeded ${output_1.output.dim(`[${totalCachedTasks} read from cache]`)}`,
131
132
  ...viewLogs,
132
- ]),
133
+ ].join(node_os_1.EOL)),
133
134
  ];
134
135
  }
135
136
  else {
@@ -145,7 +146,7 @@ function getTuiTerminalSummaryLifeCycle({ projectNames, tasks, args, overrides,
145
146
  const printRunManySummary = () => {
146
147
  console.log('');
147
148
  const lines = [];
148
- const failure = totalSuccessfulTasks + totalStoppedTasks !== totalTasks;
149
+ const failure = totalSuccessfulTasks + stoppedTasks.size !== totalTasks;
149
150
  for (const taskId of taskIdsInOrderOfCompletion) {
150
151
  const { terminalOutput, taskStatus } = tasksToTerminalOutputs[taskId];
151
152
  if (taskStatus === 'failure') {
@@ -157,7 +158,7 @@ function getTuiTerminalSummaryLifeCycle({ projectNames, tasks, args, overrides,
157
158
  }
158
159
  }
159
160
  lines.push(...output_1.output.getVerticalSeparatorLines(failure ? 'red' : 'green'));
160
- if (totalSuccessfulTasks + totalStoppedTasks === totalTasks) {
161
+ if (totalSuccessfulTasks + stoppedTasks.size === totalTasks) {
161
162
  const successSummaryRows = [];
162
163
  const text = `Successfully ran ${(0, formatting_utils_1.formatTargetsAndProjects)(projectNames, targets, tasks)}`;
163
164
  const taskOverridesRows = [];
@@ -8,6 +8,7 @@ export declare class PseudoTerminal {
8
8
  private pseudoIPCPath;
9
9
  private pseudoIPC;
10
10
  private initialized;
11
+ private childProcesses;
11
12
  static isSupported(): boolean;
12
13
  constructor(rustPseudoTerminal: RustPseudoTerminal);
13
14
  init(): Promise<void>;
@@ -38,6 +38,7 @@ class PseudoTerminal {
38
38
  this.pseudoIPCPath = (0, socket_utils_1.getForkedProcessOsSocketPath)(process.pid.toString() + '-' + id++);
39
39
  this.pseudoIPC = new pseudo_ipc_1.PseudoIPCServer(this.pseudoIPCPath);
40
40
  this.initialized = false;
41
+ this.childProcesses = new Set();
41
42
  }
42
43
  async init() {
43
44
  if (this.initialized) {
@@ -47,18 +48,27 @@ class PseudoTerminal {
47
48
  this.initialized = true;
48
49
  }
49
50
  shutdown() {
51
+ for (const cp of this.childProcesses) {
52
+ try {
53
+ cp.kill();
54
+ }
55
+ catch { }
56
+ }
50
57
  if (this.initialized) {
51
58
  this.pseudoIPC.close();
52
59
  }
53
60
  }
54
61
  runCommand(command, { cwd, execArgv, jsEnv, quiet, tty, } = {}) {
55
- return new PseudoTtyProcess(this.rustPseudoTerminal, this.rustPseudoTerminal.runCommand(command, cwd, jsEnv, execArgv, quiet, tty));
62
+ const cp = new PseudoTtyProcess(this.rustPseudoTerminal, this.rustPseudoTerminal.runCommand(command, cwd, jsEnv, execArgv, quiet, tty));
63
+ this.childProcesses.add(cp);
64
+ return cp;
56
65
  }
57
66
  async fork(id, script, { cwd, execArgv, jsEnv, quiet, }) {
58
67
  if (!this.initialized) {
59
68
  throw new Error('Call init() before forking processes');
60
69
  }
61
70
  const cp = new PseudoTtyProcessWithSend(this.rustPseudoTerminal, this.rustPseudoTerminal.fork(id, script, this.pseudoIPCPath, cwd, jsEnv, execArgv, quiet), id, this.pseudoIPC);
71
+ this.childProcesses.add(cp);
62
72
  await this.pseudoIPC.waitForChildReady(id);
63
73
  return cp;
64
74
  }
@@ -17,7 +17,6 @@ const create_task_hasher_1 = require("../hasher/create-task-hasher");
17
17
  const hash_task_1 = require("../hasher/hash-task");
18
18
  const tasks_execution_hooks_1 = require("../project-graph/plugins/tasks-execution-hooks");
19
19
  const project_graph_1 = require("../project-graph/project-graph");
20
- const fileutils_1 = require("../utils/fileutils");
21
20
  const handle_errors_1 = require("../utils/handle-errors");
22
21
  const is_ci_1 = require("../utils/is-ci");
23
22
  const nx_cloud_utils_1 = require("../utils/nx-cloud-utils");
@@ -241,6 +240,7 @@ async function getTerminalOutputLifeCycle(initiatingProject, initiatingTasks, pr
241
240
  }
242
241
  function createTaskGraphAndRunValidations(projectGraph, extraTargetDependencies, projectNames, nxArgs, overrides, extraOptions) {
243
242
  const taskGraph = (0, create_task_graph_1.createTaskGraph)(projectGraph, extraTargetDependencies, projectNames, nxArgs.targets, nxArgs.configuration, overrides, extraOptions.excludeTaskDependencies);
243
+ (0, task_graph_utils_1.assertTaskGraphDoesNotContainInvalidTargets)(taskGraph);
244
244
  const cycle = (0, task_graph_utils_1.findCycle)(taskGraph);
245
245
  if (cycle) {
246
246
  if (process.env.NX_IGNORE_CYCLES === 'true' || nxArgs.nxIgnoreCycles) {
@@ -712,14 +712,6 @@ function getRunner(nxArgs, nxJson) {
712
712
  }
713
713
  const modulePath = getTasksRunnerPath(runner, nxJson);
714
714
  try {
715
- if (isCustomRunnerPath(modulePath)) {
716
- output_1.output.warn({
717
- title: `Custom task runners will be replaced by a new API starting with Nx 21.`,
718
- bodyLines: [
719
- `For more information, see https://nx.dev/deprecated/custom-tasks-runner`,
720
- ],
721
- });
722
- }
723
715
  const tasksRunner = loadTasksRunner(modulePath);
724
716
  return {
725
717
  tasksRunner,
@@ -732,18 +724,12 @@ function getRunner(nxArgs, nxJson) {
732
724
  }
733
725
  const defaultTasksRunnerPath = require.resolve('./default-tasks-runner');
734
726
  function getTasksRunnerPath(runner, nxJson) {
735
- let modulePath = nxJson.tasksRunnerOptions?.[runner]?.runner;
736
- if (modulePath) {
737
- if ((0, fileutils_1.isRelativePath)(modulePath)) {
738
- return (0, node_path_1.join)(workspace_root_1.workspaceRoot, modulePath);
739
- }
740
- return modulePath;
741
- }
742
727
  const isCloudRunner =
743
728
  // No tasksRunnerOptions for given --runner
744
729
  nxJson.nxCloudAccessToken ||
745
730
  // No runner prop in tasks runner options, check if access token is set.
746
731
  nxJson.tasksRunnerOptions?.[runner]?.options?.accessToken ||
732
+ ['nx-cloud', '@nrwl/nx-cloud'].includes(nxJson.tasksRunnerOptions?.[runner]?.runner) ||
747
733
  // Cloud access token specified in env var.
748
734
  process.env.NX_CLOUD_ACCESS_TOKEN ||
749
735
  // Nx Cloud ID specified in nxJson
@@ -792,11 +778,3 @@ function getRunnerOptions(runner, nxJson, nxArgs, isCloudDefault) {
792
778
  }
793
779
  return result;
794
780
  }
795
- function isCustomRunnerPath(modulePath) {
796
- return ![
797
- 'nx-cloud',
798
- '@nrwl/nx-cloud',
799
- 'nx/tasks-runners/default',
800
- defaultTasksRunnerPath,
801
- ].includes(modulePath);
802
- }
@@ -6,6 +6,7 @@ import { TaskGraph } from '../config/task-graph';
6
6
  */
7
7
  export declare function findCycle(graph: {
8
8
  dependencies: Record<string, string[]>;
9
+ continuousDependencies?: Record<string, string[]>;
9
10
  }): string[] | null;
10
11
  /**
11
12
  * This function finds all cycles in the graph.
@@ -13,9 +14,11 @@ export declare function findCycle(graph: {
13
14
  */
14
15
  export declare function findCycles(graph: {
15
16
  dependencies: Record<string, string[]>;
17
+ continuousDependencies?: Record<string, string[]>;
16
18
  }): Set<string> | null;
17
19
  export declare function makeAcyclic(graph: {
18
20
  roots: string[];
19
21
  dependencies: Record<string, string[]>;
20
22
  }): void;
21
23
  export declare function validateNoAtomizedTasks(taskGraph: TaskGraph, projectGraph: ProjectGraph): void;
24
+ export declare function assertTaskGraphDoesNotContainInvalidTargets(taskGraph: TaskGraph): void;
@@ -4,12 +4,16 @@ exports.findCycle = findCycle;
4
4
  exports.findCycles = findCycles;
5
5
  exports.makeAcyclic = makeAcyclic;
6
6
  exports.validateNoAtomizedTasks = validateNoAtomizedTasks;
7
+ exports.assertTaskGraphDoesNotContainInvalidTargets = assertTaskGraphDoesNotContainInvalidTargets;
7
8
  const output_1 = require("../utils/output");
8
9
  function _findCycle(graph, id, visited, path) {
9
10
  if (visited[id])
10
11
  return null;
11
12
  visited[id] = true;
12
- for (const d of graph.dependencies[id]) {
13
+ for (const d of [
14
+ ...graph.dependencies[id],
15
+ ...(graph.continuousDependencies?.[id] ?? []),
16
+ ]) {
13
17
  if (path.includes(d))
14
18
  return [...path, d];
15
19
  const cycle = _findCycle(graph, d, visited, [...path, d]);
@@ -57,9 +61,11 @@ function _makeAcyclic(graph, id, visited, path) {
57
61
  return;
58
62
  visited[id] = true;
59
63
  const deps = graph.dependencies[id];
60
- for (const d of [...deps]) {
64
+ const continuousDeps = graph.continuousDependencies?.[id] ?? [];
65
+ for (const d of [...deps, ...continuousDeps]) {
61
66
  if (path.includes(d)) {
62
67
  deps.splice(deps.indexOf(d), 1);
68
+ continuousDeps.splice(continuousDeps.indexOf(d), 1);
63
69
  }
64
70
  else {
65
71
  _makeAcyclic(graph, d, visited, [...path, d]);
@@ -109,3 +115,26 @@ function validateNoAtomizedTasks(taskGraph, projectGraph) {
109
115
  }
110
116
  process.exit(1);
111
117
  }
118
+ function assertTaskGraphDoesNotContainInvalidTargets(taskGraph) {
119
+ const invalidTasks = [];
120
+ for (const task of Object.values(taskGraph.tasks)) {
121
+ if (task.parallelism === false &&
122
+ taskGraph.continuousDependencies[task.id].length > 0) {
123
+ invalidTasks.push(task);
124
+ }
125
+ }
126
+ if (invalidTasks.length > 0) {
127
+ throw new NonParallelTaskDependsOnContinuousTasksError(invalidTasks, taskGraph);
128
+ }
129
+ }
130
+ class NonParallelTaskDependsOnContinuousTasksError extends Error {
131
+ constructor(invalidTasks, taskGraph) {
132
+ let message = 'The following tasks do not support parallelism but depend on continuous tasks:';
133
+ for (const task of invalidTasks) {
134
+ message += `\n - ${task.id} -> ${taskGraph.continuousDependencies[task.id].join(', ')}`;
135
+ }
136
+ super(message);
137
+ this.invalidTasks = invalidTasks;
138
+ this.name = 'NonParallelTaskDependsOnContinuousTasksError';
139
+ }
140
+ }
@@ -173,7 +173,7 @@ class TaskOrchestrator {
173
173
  // No output files to restore
174
174
  !!outputs.length &&
175
175
  // Remote caches are restored to output dirs when applied and using db cache
176
- (!cachedResult.remote || !(0, cache_1.dbCacheEnabled)(this.nxJson)) &&
176
+ (!cachedResult.remote || !(0, cache_1.dbCacheEnabled)()) &&
177
177
  // Output files have not been touched since last run
178
178
  (await this.shouldCopyOutputsFromCache(outputs, task.hash));
179
179
  if (shouldCopyOutputsFromCache) {
@@ -194,6 +194,7 @@ class TaskOrchestrator {
194
194
  // endregion Applying Cache
195
195
  // region Batch
196
196
  async applyFromCacheOrRunBatch(doNotSkipCache, batch, groupId) {
197
+ const applyFromCacheOrRunBatchStart = perf_hooks_1.performance.mark('TaskOrchestrator-apply-from-cache-or-run-batch:start');
197
198
  const taskEntries = Object.entries(batch.taskGraph.tasks);
198
199
  const tasks = taskEntries.map(([, task]) => task);
199
200
  // Wait for batch to be processed
@@ -219,8 +220,12 @@ class TaskOrchestrator {
219
220
  taskGraph: (0, utils_1.removeTasksFromTaskGraph)(batch.taskGraph, tasksCompleted.map(([taskId]) => taskId)),
220
221
  }, groupId);
221
222
  }
223
+ // Batch is done, mark it as completed
224
+ const applyFromCacheOrRunBatchEnd = perf_hooks_1.performance.mark('TaskOrchestrator-apply-from-cache-or-run-batch:end');
225
+ perf_hooks_1.performance.measure('TaskOrchestrator-apply-from-cache-or-run-batch', applyFromCacheOrRunBatchStart.name, applyFromCacheOrRunBatchEnd.name);
222
226
  }
223
227
  async runBatch(batch, env) {
228
+ const runBatchStart = perf_hooks_1.performance.mark('TaskOrchestrator-run-batch:start');
224
229
  try {
225
230
  const batchProcess = await this.forkedProcessTaskRunner.forkProcessForBatch(batch, this.projectGraph, this.taskGraph, env);
226
231
  const results = await batchProcess.getResults();
@@ -242,6 +247,10 @@ class TaskOrchestrator {
242
247
  status: 'failure',
243
248
  }));
244
249
  }
250
+ finally {
251
+ const runBatchEnd = perf_hooks_1.performance.mark('TaskOrchestrator-run-batch:end');
252
+ perf_hooks_1.performance.measure('TaskOrchestrator-run-batch', runBatchStart.name, runBatchEnd.name);
253
+ }
245
254
  }
246
255
  // endregion Batch
247
256
  // region Single Task