nx 19.5.0-canary.20240712-0b0db78 → 19.5.0-canary.20240716-34da542

Sign up to get free protection for your applications and to get access to all the features.
@@ -185,6 +185,7 @@ export interface Target {
185
185
  outputs?: Array<string>
186
186
  options?: string
187
187
  configurations?: string
188
+ parallelism?: boolean
188
189
  }
189
190
 
190
191
  export interface Task {
Binary file
@@ -14,6 +14,7 @@ function transformProjectGraphForRust(graph) {
14
14
  outputs: targetConfig.outputs,
15
15
  options: JSON.stringify(targetConfig.options),
16
16
  configurations: JSON.stringify(targetConfig.configurations),
17
+ parallelism: targetConfig.parallelism,
17
18
  };
18
19
  }
19
20
  nodes[projectName] = {
@@ -18,6 +18,7 @@ const minimatch_1 = require("minimatch");
18
18
  const path_1 = require("path");
19
19
  const perf_hooks_1 = require("perf_hooks");
20
20
  const error_types_1 = require("../error-types");
21
+ const globs_1 = require("../../utils/globs");
21
22
  function mergeProjectConfigurationIntoRootMap(projectRootMap, project, configurationSourceMaps, sourceInformation,
22
23
  // This function is used when reading project configuration
23
24
  // in generators, where we don't want to do this.
@@ -709,10 +710,23 @@ function readTargetDefaultsForTarget(targetName, targetDefaults, executor) {
709
710
  const key = [executor, targetName].find((x) => targetDefaults?.[x]);
710
711
  return key ? targetDefaults?.[key] : null;
711
712
  }
712
- else {
713
+ else if (targetDefaults?.[targetName]) {
713
714
  // If the executor is not defined, the only key we have is the target name.
714
715
  return targetDefaults?.[targetName];
715
716
  }
717
+ let matchingTargetDefaultKey = null;
718
+ for (const key in targetDefaults ?? {}) {
719
+ if ((0, globs_1.isGlobPattern)(key) && (0, minimatch_1.minimatch)(targetName, key)) {
720
+ if (!matchingTargetDefaultKey ||
721
+ matchingTargetDefaultKey.length < key.length) {
722
+ matchingTargetDefaultKey = key;
723
+ }
724
+ }
725
+ }
726
+ if (matchingTargetDefaultKey) {
727
+ return targetDefaults[matchingTargetDefaultKey];
728
+ }
729
+ return {};
716
730
  }
717
731
  function createRootMap(projectRootMap) {
718
732
  const map = {};
@@ -748,11 +762,17 @@ function resolveCommandSyntacticSugar(target, key) {
748
762
  * @returns The normalized target configuration
749
763
  */
750
764
  function normalizeTarget(target, project) {
765
+ target = {
766
+ ...target,
767
+ configurations: {
768
+ ...target.configurations,
769
+ },
770
+ };
751
771
  target = resolveCommandSyntacticSugar(target, project.root);
752
772
  target.options = resolveNxTokensInOptions(target.options, project, `${project.root}:${target}`);
753
- target.configurations ??= {};
754
773
  for (const configuration in target.configurations) {
755
774
  target.configurations[configuration] = resolveNxTokensInOptions(target.configurations[configuration], project, `${project.root}:${target}:${configuration}`);
756
775
  }
776
+ target.parallelism ??= true;
757
777
  return target;
758
778
  }
@@ -156,6 +156,7 @@ class ProcessTasks {
156
156
  overrides: interpolatedOverrides,
157
157
  outputs: (0, utils_1.getOutputs)(this.projectGraph.nodes, qualifiedTarget, interpolatedOverrides),
158
158
  cache: project.data.targets[target].cache,
159
+ parallelism: project.data.targets[target].parallelism ?? true,
159
160
  };
160
161
  }
161
162
  resolveConfiguration(project, target, configuration) {
@@ -14,6 +14,7 @@ export declare class TasksSchedule {
14
14
  private reverseProjectGraph;
15
15
  private scheduledBatches;
16
16
  private scheduledTasks;
17
+ private runningTasks;
17
18
  private completedTasks;
18
19
  private scheduleRequestsExecutionChain;
19
20
  constructor(projectGraph: ProjectGraph, taskGraph: TaskGraph, options: DefaultTasksRunnerOptions);
@@ -14,6 +14,7 @@ class TasksSchedule {
14
14
  this.reverseProjectGraph = (0, operators_1.reverse)(this.projectGraph);
15
15
  this.scheduledBatches = [];
16
16
  this.scheduledTasks = [];
17
+ this.runningTasks = new Set();
17
18
  this.completedTasks = new Set();
18
19
  this.scheduleRequestsExecutionChain = Promise.resolve();
19
20
  }
@@ -31,6 +32,7 @@ class TasksSchedule {
31
32
  complete(taskIds) {
32
33
  for (const taskId of taskIds) {
33
34
  this.completedTasks.add(taskId);
35
+ this.runningTasks.delete(taskId);
34
36
  }
35
37
  this.notScheduledTaskGraph = (0, utils_1.removeTasksFromTaskGraph)(this.notScheduledTaskGraph, taskIds);
36
38
  }
@@ -84,6 +86,7 @@ class TasksSchedule {
84
86
  (0, project_graph_utils_1.findAllProjectNodeDependencies)(project1, this.reverseProjectGraph)
85
87
  .length);
86
88
  });
89
+ this.runningTasks.add(taskId);
87
90
  }
88
91
  async scheduleBatches() {
89
92
  const batchMap = {};
@@ -102,7 +105,7 @@ class TasksSchedule {
102
105
  this.scheduledBatches.push({ executorName, taskGraph });
103
106
  }
104
107
  async processTaskForBatches(batches, task, rootExecutorName, isRoot) {
105
- if (!this.canBatchTaskBeScheduled(task.id, batches[rootExecutorName])) {
108
+ if (!this.canBatchTaskBeScheduled(task, batches[rootExecutorName])) {
106
109
  return;
107
110
  }
108
111
  const { batchImplementationFactory } = (0, utils_1.getExecutorForTask)(task, this.projectGraph);
@@ -131,12 +134,33 @@ class TasksSchedule {
131
134
  await this.processTaskForBatches(batches, depTask, rootExecutorName, false);
132
135
  }
133
136
  }
134
- canBatchTaskBeScheduled(taskId, batchTaskGraph) {
137
+ canBatchTaskBeScheduled(task, batchTaskGraph) {
138
+ // task self needs to have parallelism true
135
139
  // all deps have either completed or belong to the same batch
136
- return this.taskGraph.dependencies[taskId].every((id) => this.completedTasks.has(id) || !!batchTaskGraph?.tasks[id]);
140
+ return (task.parallelism === true &&
141
+ this.taskGraph.dependencies[task.id].every((id) => this.completedTasks.has(id) || !!batchTaskGraph?.tasks[id]));
137
142
  }
138
143
  canBeScheduled(taskId) {
139
- return this.taskGraph.dependencies[taskId].every((id) => this.completedTasks.has(id));
144
+ const hasDependenciesCompleted = this.taskGraph.dependencies[taskId].every((id) => this.completedTasks.has(id));
145
+ // if dependencies have not completed, cannot schedule
146
+ if (!hasDependenciesCompleted) {
147
+ return false;
148
+ }
149
+ // if there are no running tasks, can schedule anything
150
+ if (this.runningTasks.size === 0) {
151
+ return true;
152
+ }
153
+ const runningTasksNotSupportParallelism = Array.from(this.runningTasks).some((taskId) => {
154
+ return this.taskGraph.tasks[taskId].parallelism === false;
155
+ });
156
+ if (runningTasksNotSupportParallelism) {
157
+ // if any running tasks do not support parallelism, no other tasks can be scheduled
158
+ return false;
159
+ }
160
+ else {
161
+ // if all running tasks support parallelism, can only schedule task with parallelism
162
+ return this.taskGraph.tasks[taskId].parallelism === true;
163
+ }
140
164
  }
141
165
  }
142
166
  exports.TasksSchedule = TasksSchedule;
@@ -36,6 +36,7 @@ const executor_utils_1 = require("../command-line/run/executor-utils");
36
36
  const project_graph_1 = require("../project-graph/project-graph");
37
37
  const find_matching_projects_1 = require("../utils/find-matching-projects");
38
38
  const minimatch_1 = require("minimatch");
39
+ const globs_1 = require("../utils/globs");
39
40
  function getDependencyConfigs({ project, target }, extraTargetDependencies, projectGraph, allTargetNames) {
40
41
  const dependencyConfigs = (projectGraph.nodes[project].data?.targets[target]?.dependsOn ??
41
42
  // This is passed into `run-command` from programmatic invocations
@@ -77,7 +78,7 @@ function expandDependencyConfigSyntaxSugar(dependencyConfigString, graph) {
77
78
  // Weakmap let's the cache get cleared by garbage collector if allTargetNames is no longer used
78
79
  const patternResultCache = new WeakMap();
79
80
  function expandWildcardTargetConfiguration(dependencyConfig, allTargetNames) {
80
- if (!find_matching_projects_1.GLOB_CHARACTERS.some((char) => dependencyConfig.target.includes(char))) {
81
+ if (!(0, globs_1.isGlobPattern)(dependencyConfig.target)) {
81
82
  return [dependencyConfig];
82
83
  }
83
84
  let cache = patternResultCache.get(allTargetNames);
@@ -1,8 +1,4 @@
1
1
  import type { ProjectGraphProjectNode } from '../config/project-graph';
2
- /**
3
- * The presence of these characters in a string indicates that it might be a glob pattern.
4
- */
5
- export declare const GLOB_CHARACTERS: string[];
6
2
  /**
7
3
  * Find matching project names given a list of potential project names or globs.
8
4
  *
@@ -1,18 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getMatchingStringsWithCache = exports.GLOB_CHARACTERS = void 0;
3
+ exports.getMatchingStringsWithCache = void 0;
4
4
  exports.findMatchingProjects = findMatchingProjects;
5
5
  const minimatch_1 = require("minimatch");
6
+ const globs_1 = require("./globs");
6
7
  const validPatternTypes = [
7
8
  'name', // Pattern is based on the project's name
8
9
  'tag', // Pattern is based on the project's tags
9
10
  'directory', // Pattern is based on the project's root directory
10
11
  'unlabeled', // Pattern was passed without specifying a type
11
12
  ];
12
- /**
13
- * The presence of these characters in a string indicates that it might be a glob pattern.
14
- */
15
- exports.GLOB_CHARACTERS = ['*', '|', '{', '}', '(', ')'];
16
13
  /**
17
14
  * Find matching project names given a list of potential project names or globs.
18
15
  *
@@ -113,7 +110,7 @@ function addMatchingProjectsByName(projectNames, projects, pattern, matchedProje
113
110
  }
114
111
  return;
115
112
  }
116
- if (!exports.GLOB_CHARACTERS.some((c) => pattern.value.includes(c))) {
113
+ if (!(0, globs_1.isGlobPattern)(pattern.value)) {
117
114
  return;
118
115
  }
119
116
  const matchedProjectNames = (0, exports.getMatchingStringsWithCache)(pattern.value, projectNames);
@@ -138,7 +135,7 @@ function addMatchingProjectsByTag(projectNames, projects, pattern, matchedProjec
138
135
  }
139
136
  continue;
140
137
  }
141
- if (!exports.GLOB_CHARACTERS.some((c) => pattern.value.includes(c))) {
138
+ if (!(0, globs_1.isGlobPattern)(pattern.value)) {
142
139
  continue;
143
140
  }
144
141
  if ((0, exports.getMatchingStringsWithCache)(pattern.value, tags).length) {
@@ -1 +1,3 @@
1
1
  export declare function combineGlobPatterns(...patterns: (string | string[])[]): string;
2
+ export declare const GLOB_CHARACTERS: Set<string>;
3
+ export declare function isGlobPattern(pattern: string): boolean;
@@ -1,7 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GLOB_CHARACTERS = void 0;
3
4
  exports.combineGlobPatterns = combineGlobPatterns;
5
+ exports.isGlobPattern = isGlobPattern;
4
6
  function combineGlobPatterns(...patterns) {
5
7
  const p = patterns.flat();
6
8
  return p.length > 1 ? '{' + p.join(',') + '}' : p.length === 1 ? p[0] : '';
7
9
  }
10
+ exports.GLOB_CHARACTERS = new Set(['*', '|', '{', '}', '(', ')', '[']);
11
+ function isGlobPattern(pattern) {
12
+ for (const c of pattern) {
13
+ if (exports.GLOB_CHARACTERS.has(c)) {
14
+ return true;
15
+ }
16
+ }
17
+ return false;
18
+ }