nx 21.0.0-canary.20250429-cf4a1f3 → 21.0.0-canary.20250501-8f50358

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 (63) hide show
  1. package/migrations.json +16 -1
  2. package/package.json +11 -11
  3. package/release/changelog-renderer/index.d.ts +7 -7
  4. package/release/changelog-renderer/index.js +12 -31
  5. package/schemas/nx-schema.json +8 -3
  6. package/src/command-line/migrate/migrate-ui-api.d.ts +2 -1
  7. package/src/command-line/migrate/migrate-ui-api.js +4 -3
  8. package/src/command-line/migrate/migrate.d.ts +12 -6
  9. package/src/command-line/migrate/migrate.js +31 -9
  10. package/src/command-line/release/changelog.d.ts +3 -2
  11. package/src/command-line/release/changelog.js +57 -70
  12. package/src/command-line/release/command-object.d.ts +1 -1
  13. package/src/command-line/release/config/config.d.ts +8 -1
  14. package/src/command-line/release/config/config.js +18 -11
  15. package/src/command-line/release/release.js +30 -18
  16. package/src/command-line/release/utils/git.d.ts +1 -0
  17. package/src/command-line/release/utils/git.js +27 -8
  18. package/src/command-line/release/utils/remote-release-clients/github.d.ts +57 -0
  19. package/src/command-line/release/utils/remote-release-clients/github.js +309 -0
  20. package/src/command-line/release/utils/remote-release-clients/gitlab.d.ts +62 -0
  21. package/src/command-line/release/utils/remote-release-clients/gitlab.js +271 -0
  22. package/src/command-line/release/utils/remote-release-clients/remote-release-client.d.ts +111 -0
  23. package/src/command-line/release/utils/remote-release-clients/remote-release-client.js +136 -0
  24. package/src/command-line/repair/repair.js +8 -2
  25. package/src/command-line/report/report.js +1 -1
  26. package/src/command-line/yargs-utils/shared-options.d.ts +1 -1
  27. package/src/command-line/yargs-utils/shared-options.js +22 -3
  28. package/src/config/misc-interfaces.d.ts +9 -1
  29. package/src/config/nx-json.d.ts +8 -5
  30. package/src/core/graph/main.js +1 -1
  31. package/src/core/graph/styles.css +1 -1
  32. package/src/devkit-exports.d.ts +1 -1
  33. package/src/migrations/update-21-0-0/release-changelog-config-changes.d.ts +2 -0
  34. package/src/migrations/update-21-0-0/release-changelog-config-changes.js +38 -0
  35. package/src/migrations/update-21-0-0/remove-custom-tasks-runner.d.ts +2 -0
  36. package/src/migrations/update-21-0-0/remove-custom-tasks-runner.js +38 -0
  37. package/src/migrations/update-21-0-0/remove-legacy-cache.d.ts +2 -0
  38. package/src/migrations/update-21-0-0/remove-legacy-cache.js +17 -0
  39. package/src/native/index.d.ts +6 -1
  40. package/src/native/native-bindings.js +1 -0
  41. package/src/native/native-file-cache-location.js +2 -1
  42. package/src/native/nx.wasm32-wasi.wasm +0 -0
  43. package/src/project-graph/plugins/get-plugins.js +19 -14
  44. package/src/tasks-runner/batch/run-batch.js +1 -1
  45. package/src/tasks-runner/cache.d.ts +1 -2
  46. package/src/tasks-runner/cache.js +2 -18
  47. package/src/tasks-runner/is-tui-enabled.d.ts +16 -1
  48. package/src/tasks-runner/is-tui-enabled.js +40 -28
  49. package/src/tasks-runner/life-cycles/tui-summary-life-cycle.js +8 -7
  50. package/src/tasks-runner/pseudo-terminal.d.ts +1 -0
  51. package/src/tasks-runner/pseudo-terminal.js +11 -1
  52. package/src/tasks-runner/run-command.js +5 -27
  53. package/src/tasks-runner/running-tasks/node-child-process.d.ts +1 -0
  54. package/src/tasks-runner/running-tasks/node-child-process.js +7 -0
  55. package/src/tasks-runner/task-graph-utils.d.ts +3 -0
  56. package/src/tasks-runner/task-graph-utils.js +31 -2
  57. package/src/tasks-runner/task-orchestrator.js +16 -4
  58. package/src/utils/is-ci.d.ts +1 -1
  59. package/src/utils/is-ci.js +4 -1
  60. package/src/utils/package-manager.d.ts +1 -0
  61. package/src/utils/package-manager.js +29 -16
  62. package/src/command-line/release/utils/github.d.ts +0 -32
  63. package/src/command-line/release/utils/github.js +0 -326
@@ -1,48 +1,60 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isTuiEnabled = isTuiEnabled;
4
- const devkit_internals_1 = require("../devkit-internals");
4
+ exports.shouldUseTui = shouldUseTui;
5
+ const native_1 = require("../native");
5
6
  const is_ci_1 = require("../utils/is-ci");
6
7
  let tuiEnabled = undefined;
7
- function isTuiEnabled(nxJson, skipCapableCheck = false) {
8
- if (tuiEnabled !== undefined) {
9
- return tuiEnabled;
10
- }
8
+ /**
9
+ * @returns If tui is enabled
10
+ */
11
+ function isTuiEnabled() {
12
+ return process.env.NX_TUI === 'true';
13
+ }
14
+ /**
15
+ * Determines if the TUI should be enabled for the current environment.
16
+ *
17
+ * **Note:** This function should almost never be called directly. Instead, use the `isTuiEnabled` function.
18
+ *
19
+ * @param nxJson `nx.json`
20
+ * @param nxArgs CLI Flags passed into Nx
21
+ * @param skipCapabilityCheck Mainly used for unit tests.
22
+ * @returns `true` if the TUI should be enabled, `false` otherwise.
23
+ */
24
+ function shouldUseTui(nxJson, nxArgs, skipCapabilityCheck = process.env.NX_TUI_SKIP_CAPABILITY_CHECK === 'true') {
11
25
  // If the current terminal/environment is not capable of displaying the TUI, we don't run it
12
26
  const isWindows = process.platform === 'win32';
13
- const isCapable = skipCapableCheck || (process.stderr.isTTY && isUnicodeSupported());
27
+ const isCapable = skipCapabilityCheck || (process.stderr.isTTY && isUnicodeSupported());
14
28
  if (!isCapable) {
15
- tuiEnabled = false;
16
- process.env.NX_TUI = 'false';
17
- return tuiEnabled;
29
+ return false;
18
30
  }
19
31
  // The environment variable takes precedence over the nx.json config
20
32
  if (typeof process.env.NX_TUI === 'string') {
21
- tuiEnabled = process.env.NX_TUI === 'true';
22
- return tuiEnabled;
33
+ return process.env.NX_TUI === 'true';
23
34
  }
24
- // Windows is not working well right now, temporarily disable it on Windows even if it has been specified as enabled
25
- // TODO(@JamesHenry): Remove this check once Windows issues are fixed.
26
- if ((0, is_ci_1.isCI)() || isWindows) {
27
- tuiEnabled = false;
28
- process.env.NX_TUI = 'false';
29
- return tuiEnabled;
35
+ if (['static', 'stream', 'dynamic-legacy'].includes(nxArgs.outputStyle)) {
36
+ // If the user has specified a non-TUI output style, we disable the TUI
37
+ return false;
30
38
  }
31
- // Only read from disk if nx.json config is not already provided (and we have not been able to determine tuiEnabled based on the above checks)
32
- if (!nxJson) {
33
- nxJson = (0, devkit_internals_1.readNxJsonFromDisk)();
39
+ if (
40
+ // Interactive TUI doesn't make sense on CI
41
+ (0, is_ci_1.isCI)() ||
42
+ // TODO(@JamesHenry): Remove this check once Windows issues are fixed.
43
+ // Windows is not working well right now, temporarily disable it on Windows even if it has been specified as enabled
44
+ isWindows ||
45
+ // WASM needs further testing
46
+ native_1.IS_WASM) {
47
+ return false;
48
+ }
49
+ if (nxArgs.outputStyle === 'dynamic' || nxArgs.outputStyle === 'tui') {
50
+ return true;
34
51
  }
35
52
  // Respect user config
36
53
  if (typeof nxJson.tui?.enabled === 'boolean') {
37
- tuiEnabled = Boolean(nxJson.tui?.enabled);
38
- }
39
- else {
40
- // Default to enabling the TUI if the system is capable of displaying it
41
- tuiEnabled = true;
54
+ return Boolean(nxJson.tui?.enabled);
42
55
  }
43
- // Also set the environment variable for consistency and ease of checking on the rust side, for example
44
- process.env.NX_TUI = tuiEnabled.toString();
45
- return tuiEnabled;
56
+ // Default to enabling the TUI if the system is capable of displaying it
57
+ return true;
46
58
  }
47
59
  // Credit to https://github.com/sindresorhus/is-unicode-supported/blob/e0373335038856c63034c8eef6ac43ee3827a601/index.js
48
60
  function isUnicodeSupported() {
@@ -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");
@@ -48,7 +47,8 @@ const originalConsoleError = console.error.bind(console);
48
47
  async function getTerminalOutputLifeCycle(initiatingProject, initiatingTasks, projectNames, tasks, taskGraph, nxArgs, nxJson, overrides) {
49
48
  const overridesWithoutHidden = { ...overrides };
50
49
  delete overridesWithoutHidden['__overrides_unparsed__'];
51
- if ((0, is_tui_enabled_1.isTuiEnabled)(nxJson)) {
50
+ const isRunOne = initiatingProject != null;
51
+ if ((0, is_tui_enabled_1.isTuiEnabled)()) {
52
52
  const interceptedNxCloudLogs = [];
53
53
  const createPatchedConsoleMethod = (originalMethod) => {
54
54
  return (...args) => {
@@ -125,7 +125,7 @@ async function getTerminalOutputLifeCycle(initiatingProject, initiatingTasks, pr
125
125
  const lifeCycles = [tsLifeCycle];
126
126
  // Only run the TUI if there are tasks to run
127
127
  if (tasks.length > 0) {
128
- appLifeCycle = new AppLifeCycle(tasks, pinnedTasks, nxArgs ?? {}, nxJson.tui ?? {}, titleText);
128
+ appLifeCycle = new AppLifeCycle(tasks, initiatingTasks.map((t) => t.id), isRunOne ? 0 /* RunMode.RunOne */ : 1 /* RunMode.RunMany */, pinnedTasks, nxArgs ?? {}, nxJson.tui ?? {}, titleText);
129
129
  lifeCycles.unshift(appLifeCycle);
130
130
  /**
131
131
  * Patch stdout.write and stderr.write methods to pass Nx Cloud client logs to the TUI via the lifecycle
@@ -206,7 +206,6 @@ async function getTerminalOutputLifeCycle(initiatingProject, initiatingTasks, pr
206
206
  };
207
207
  }
208
208
  const { runnerOptions } = getRunner(nxArgs, nxJson);
209
- const isRunOne = initiatingProject != null;
210
209
  const useDynamicOutput = shouldUseDynamicLifeCycle(tasks, runnerOptions, nxArgs.outputStyle);
211
210
  if (isRunOne) {
212
211
  if (useDynamicOutput) {
@@ -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
- }
@@ -4,6 +4,7 @@ export declare class NodeChildProcessWithNonDirectOutput implements RunningTask
4
4
  private childProcess;
5
5
  private terminalOutput;
6
6
  private exitCallbacks;
7
+ private exitCode;
7
8
  constructor(childProcess: ChildProcess, { streamOutput, prefix }: {
8
9
  streamOutput: boolean;
9
10
  prefix: string;
@@ -35,6 +35,7 @@ class NodeChildProcessWithNonDirectOutput {
35
35
  this.childProcess.on('exit', (code, signal) => {
36
36
  if (code === null)
37
37
  code = (0, exit_codes_1.signalToCode)(signal);
38
+ this.exitCode = code;
38
39
  for (const cb of this.exitCallbacks) {
39
40
  cb(code, this.terminalOutput);
40
41
  }
@@ -56,6 +57,12 @@ class NodeChildProcessWithNonDirectOutput {
56
57
  this.exitCallbacks.push(cb);
57
58
  }
58
59
  async getResults() {
60
+ if (typeof this.exitCode === 'number') {
61
+ return {
62
+ code: this.exitCode,
63
+ terminalOutput: this.terminalOutput,
64
+ };
65
+ }
59
66
  return new Promise((res) => {
60
67
  this.onExit((code, terminalOutput) => {
61
68
  res({ code, terminalOutput });
@@ -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
+ }
@@ -38,9 +38,11 @@ class TaskOrchestrator {
38
38
  this.taskGraphForHashing = taskGraphForHashing;
39
39
  this.taskDetails = (0, hash_task_1.getTaskDetails)();
40
40
  this.cache = (0, cache_1.getCache)(this.options);
41
- this.tuiEnabled = (0, is_tui_enabled_1.isTuiEnabled)(this.nxJson);
41
+ this.tuiEnabled = (0, is_tui_enabled_1.isTuiEnabled)();
42
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)());
43
+ this.runningTasksService = !native_1.IS_WASM
44
+ ? new native_1.RunningTasksService((0, db_connection_1.getDbConnection)())
45
+ : null;
44
46
  this.tasksSchedule = new tasks_schedule_1.TasksSchedule(this.projectGraph, this.taskGraph, this.options);
45
47
  // region internal state
46
48
  this.batchEnv = (0, task_env_1.getEnvVariablesForBatchProcess)(this.options.skipNxCache, this.options.captureStderr);
@@ -173,7 +175,7 @@ class TaskOrchestrator {
173
175
  // No output files to restore
174
176
  !!outputs.length &&
175
177
  // Remote caches are restored to output dirs when applied and using db cache
176
- (!cachedResult.remote || !(0, cache_1.dbCacheEnabled)(this.nxJson)) &&
178
+ (!cachedResult.remote || !(0, cache_1.dbCacheEnabled)()) &&
177
179
  // Output files have not been touched since last run
178
180
  (await this.shouldCopyOutputsFromCache(outputs, task.hash));
179
181
  if (shouldCopyOutputsFromCache) {
@@ -194,6 +196,7 @@ class TaskOrchestrator {
194
196
  // endregion Applying Cache
195
197
  // region Batch
196
198
  async applyFromCacheOrRunBatch(doNotSkipCache, batch, groupId) {
199
+ const applyFromCacheOrRunBatchStart = perf_hooks_1.performance.mark('TaskOrchestrator-apply-from-cache-or-run-batch:start');
197
200
  const taskEntries = Object.entries(batch.taskGraph.tasks);
198
201
  const tasks = taskEntries.map(([, task]) => task);
199
202
  // Wait for batch to be processed
@@ -219,8 +222,12 @@ class TaskOrchestrator {
219
222
  taskGraph: (0, utils_1.removeTasksFromTaskGraph)(batch.taskGraph, tasksCompleted.map(([taskId]) => taskId)),
220
223
  }, groupId);
221
224
  }
225
+ // Batch is done, mark it as completed
226
+ const applyFromCacheOrRunBatchEnd = perf_hooks_1.performance.mark('TaskOrchestrator-apply-from-cache-or-run-batch:end');
227
+ perf_hooks_1.performance.measure('TaskOrchestrator-apply-from-cache-or-run-batch', applyFromCacheOrRunBatchStart.name, applyFromCacheOrRunBatchEnd.name);
222
228
  }
223
229
  async runBatch(batch, env) {
230
+ const runBatchStart = perf_hooks_1.performance.mark('TaskOrchestrator-run-batch:start');
224
231
  try {
225
232
  const batchProcess = await this.forkedProcessTaskRunner.forkProcessForBatch(batch, this.projectGraph, this.taskGraph, env);
226
233
  const results = await batchProcess.getResults();
@@ -242,6 +249,10 @@ class TaskOrchestrator {
242
249
  status: 'failure',
243
250
  }));
244
251
  }
252
+ finally {
253
+ const runBatchEnd = perf_hooks_1.performance.mark('TaskOrchestrator-run-batch:end');
254
+ perf_hooks_1.performance.measure('TaskOrchestrator-run-batch', runBatchStart.name, runBatchEnd.name);
255
+ }
245
256
  }
246
257
  // endregion Batch
247
258
  // region Single Task
@@ -413,7 +424,8 @@ class TaskOrchestrator {
413
424
  }
414
425
  }
415
426
  async startContinuousTask(task, groupId) {
416
- if (this.runningTasksService.getRunningTasks([task.id]).length) {
427
+ if (this.runningTasksService &&
428
+ this.runningTasksService.getRunningTasks([task.id]).length) {
417
429
  await this.preRunSteps([task], { groupId });
418
430
  if (this.tuiEnabled) {
419
431
  this.options.lifeCycle.setTaskStatus(task.id, 8 /* NativeTaskStatus.Shared */);
@@ -1 +1 @@
1
- export declare function isCI(): boolean;
1
+ export declare function isCI(): string | boolean;
@@ -2,7 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isCI = isCI;
4
4
  function isCI() {
5
- return ((process.env.CI && process.env.CI !== 'false') ||
5
+ if (process.env.CI === 'false') {
6
+ return false;
7
+ }
8
+ return (process.env.CI ||
6
9
  process.env.TF_BUILD === 'true' ||
7
10
  process.env.GITHUB_ACTIONS === 'true' ||
8
11
  process.env.BUILDKITE === 'true' ||
@@ -44,6 +44,7 @@ export declare function getPackageManagerCommand(packageManager?: PackageManager
44
44
  * but it can also be passed in explicitly.
45
45
  */
46
46
  export declare function getPackageManagerVersion(packageManager?: PackageManager, cwd?: string): string;
47
+ export declare function parseVersionFromPackageManagerField(requestedPackageManager: string, packageManagerFieldValue: string | undefined): null | string;
47
48
  /**
48
49
  * Checks for a project level npmrc file by crawling up the file tree until
49
50
  * hitting a package.json file, as this is how npm finds them as well.
@@ -4,6 +4,7 @@ exports.detectPackageManager = detectPackageManager;
4
4
  exports.isWorkspacesEnabled = isWorkspacesEnabled;
5
5
  exports.getPackageManagerCommand = getPackageManagerCommand;
6
6
  exports.getPackageManagerVersion = getPackageManagerVersion;
7
+ exports.parseVersionFromPackageManagerField = parseVersionFromPackageManagerField;
7
8
  exports.findFileInPackageJsonDirectory = findFileInPackageJsonDirectory;
8
9
  exports.modifyYarnRcYmlToFitNewDirectory = modifyYarnRcYmlToFitNewDirectory;
9
10
  exports.modifyYarnRcToFitNewDirectory = modifyYarnRcToFitNewDirectory;
@@ -175,30 +176,42 @@ function getPackageManagerCommand(packageManager = detectPackageManager(), root
175
176
  */
176
177
  function getPackageManagerVersion(packageManager = detectPackageManager(), cwd = process.cwd()) {
177
178
  let version;
178
- try {
179
- version = (0, child_process_1.execSync)(`${packageManager} --version`, {
180
- cwd,
181
- encoding: 'utf-8',
182
- windowsHide: true,
183
- }).trim();
179
+ if ((0, fs_1.existsSync)((0, path_1.join)(cwd, 'package.json'))) {
180
+ const packageManagerEntry = (0, fileutils_1.readJsonFile)((0, path_1.join)(cwd, 'package.json'))?.packageManager;
181
+ version = parseVersionFromPackageManagerField(packageManager, packageManagerEntry);
184
182
  }
185
- catch {
186
- if ((0, fs_1.existsSync)((0, path_1.join)(cwd, 'package.json'))) {
187
- const packageVersion = (0, fileutils_1.readJsonFile)((0, path_1.join)(cwd, 'package.json'))?.packageManager;
188
- if (packageVersion) {
189
- const [packageManagerFromPackageJson, versionFromPackageJson] = packageVersion.split('@');
190
- if (packageManagerFromPackageJson === packageManager &&
191
- versionFromPackageJson) {
192
- version = versionFromPackageJson;
193
- }
194
- }
183
+ if (!version) {
184
+ try {
185
+ version = (0, child_process_1.execSync)(`${packageManager} --version`, {
186
+ cwd,
187
+ encoding: 'utf-8',
188
+ windowsHide: true,
189
+ }).trim();
195
190
  }
191
+ catch { }
196
192
  }
197
193
  if (!version) {
198
194
  throw new Error(`Cannot determine the version of ${packageManager}.`);
199
195
  }
200
196
  return version;
201
197
  }
198
+ function parseVersionFromPackageManagerField(requestedPackageManager, packageManagerFieldValue) {
199
+ if (!packageManagerFieldValue)
200
+ return null;
201
+ const [packageManagerFromPackageJson, versionFromPackageJson] = packageManagerFieldValue.split('@');
202
+ if (versionFromPackageJson &&
203
+ // If it's a URL, it's not a valid range by default, unless users set `COREPACK_ENABLE_UNSAFE_CUSTOM_URLS=1`.
204
+ // In the unsafe case, there's no way to reliably pare out the version since it could be anything, e.g. http://mydomain.com/bin/yarn.js.
205
+ // See: https://github.com/nodejs/corepack/blob/2b43f26/sources/corepackUtils.ts#L110-L112
206
+ !URL.canParse(versionFromPackageJson) &&
207
+ packageManagerFromPackageJson === requestedPackageManager &&
208
+ versionFromPackageJson) {
209
+ // The range could have a validation hash attached, like "3.2.3+sha224.953c8233f7a92884eee2de69a1b92d1f2ec1655e66d08071ba9a02fa".
210
+ // We just want to parse out the "<major>.<minor>.<patch>". Semver treats "+" as a build, which is not included in the resulting version.
211
+ return (0, semver_1.parse)(versionFromPackageJson)?.version ?? null;
212
+ }
213
+ return null;
214
+ }
202
215
  /**
203
216
  * Checks for a project level npmrc file by crawling up the file tree until
204
217
  * hitting a package.json file, as this is how npm finds them as well.
@@ -1,32 +0,0 @@
1
- import { NxReleaseChangelogConfiguration } from '../../../config/nx-json';
2
- import { Reference } from './git';
3
- import { ReleaseVersion } from './shared';
4
- export type RepoSlug = `${string}/${string}`;
5
- interface GithubRequestConfig {
6
- repo: string;
7
- hostname: string;
8
- apiBaseUrl: string;
9
- token: string | null;
10
- }
11
- interface GithubRelease {
12
- id?: string;
13
- tag_name: string;
14
- target_commitish?: string;
15
- name?: string;
16
- body?: string;
17
- draft?: boolean;
18
- prerelease?: boolean;
19
- make_latest?: 'legacy' | boolean;
20
- }
21
- export interface GithubRepoData {
22
- hostname: string;
23
- slug: RepoSlug;
24
- apiBaseUrl: string;
25
- }
26
- export declare function getGitHubRepoData(remoteName: string, createReleaseConfig: NxReleaseChangelogConfiguration['createRelease']): GithubRepoData | null;
27
- export declare function createOrUpdateGithubRelease(createReleaseConfig: NxReleaseChangelogConfiguration['createRelease'], releaseVersion: ReleaseVersion, changelogContents: string, latestCommit: string, { dryRun }: {
28
- dryRun: boolean;
29
- }): Promise<void>;
30
- export declare function getGithubReleaseByTag(config: GithubRequestConfig, tag: string): Promise<GithubRelease>;
31
- export declare function formatReferences(references: Reference[], repoData: GithubRepoData): string;
32
- export {};