diff --git a/packages/nx/src/tasks-runner/create-task-graph.spec.ts b/packages/nx/src/tasks-runner/create-task-graph.spec.ts index 9ee524d83bf71..674824a375b76 100644 --- a/packages/nx/src/tasks-runner/create-task-graph.spec.ts +++ b/packages/nx/src/tasks-runner/create-task-graph.spec.ts @@ -1443,4 +1443,62 @@ describe('createTaskGraph', () => { }, }); }); + + it('should handle glob patterns in dependsOn', () => { + const graph: ProjectGraph = { + nodes: { + app1: { + name: 'app1', + type: 'app', + data: { + root: 'app1-root', + files: [], + targets: { + build: { + executor: 'nx:run-commands', + dependsOn: [{ target: 'build', projects: 'lib*' }], + }, + }, + }, + }, + lib1: { + name: 'lib1', + type: 'lib', + data: { + root: 'lib1-root', + files: [], + targets: { + build: { + executor: 'nx:run-commands', + }, + }, + }, + }, + lib2: { + name: 'lib2', + type: 'lib', + data: { + root: 'lib2-root', + files: [], + targets: { + build: { + executor: 'nx:run-commands', + }, + }, + }, + }, + }, + dependencies: { + app1: [], + }, + }; + const taskGraph = createTaskGraph(graph, {}, ['app1'], ['build'], null, {}); + expect(taskGraph.tasks).toHaveProperty('app1:build'); + expect(taskGraph.tasks).toHaveProperty('lib1:build'); + expect(taskGraph.tasks).toHaveProperty('lib2:build'); + expect(taskGraph.dependencies['app1:build']).toEqual([ + 'lib1:build', + 'lib2:build', + ]); + }); }); diff --git a/packages/nx/src/tasks-runner/create-task-graph.ts b/packages/nx/src/tasks-runner/create-task-graph.ts index 9022b7906a789..f3df1821c075b 100644 --- a/packages/nx/src/tasks-runner/create-task-graph.ts +++ b/packages/nx/src/tasks-runner/create-task-graph.ts @@ -7,6 +7,8 @@ import { import { Task, TaskGraph } from '../config/task-graph'; import { TargetDependencies } from '../config/nx-json'; import { TargetDependencyConfig } from '../devkit-exports'; +import { findMatchingProjects } from '../utils/find-matching-projects'; +import { output } from '../utils/output'; export class ProcessTasks { private readonly seen = new Set(); @@ -168,20 +170,33 @@ export class ProcessTasks { // Since we need to maintain support for dependencies, it is more coherent // that we also support self. // TODO(@agentender): Remove this part in v17 - const projectName = + const matchingProjects = + /** LERNA SUPPORT START - Remove in v17 */ projectSpecifier === 'self' && !this.projectGraph.nodes[projectSpecifier] - ? task.target.project - : projectSpecifier; + ? [task.target.project] + : /** LERNA SUPPORT END */ + findMatchingProjects([projectSpecifier], this.projectGraph.nodes); - this.processTasksForSingleProject( - task, - projectName, - dependencyConfig, - configuration, - taskOverrides, - overrides - ); + if (matchingProjects.length === 0) { + output.warn({ + title: `\`dependsOn\` is misconfigured for ${task.target.project}:${task.target.target}`, + bodyLines: [ + `Project pattern "${projectSpecifier}" does not match any projects.`, + ], + }); + } + + for (const projectName of matchingProjects) { + this.processTasksForSingleProject( + task, + projectName, + dependencyConfig, + configuration, + taskOverrides, + overrides + ); + } } } } diff --git a/packages/nx/src/tasks-runner/utils.ts b/packages/nx/src/tasks-runner/utils.ts index 0583cb104a2f1..a2127db4f8993 100644 --- a/packages/nx/src/tasks-runner/utils.ts +++ b/packages/nx/src/tasks-runner/utils.ts @@ -37,25 +37,6 @@ export function getDependencyConfigs( : config ); for (const dependencyConfig of dependencyConfigs) { - const specifiers = - typeof dependencyConfig.projects === 'string' - ? [dependencyConfig.projects] - : dependencyConfig.projects; - for (const specifier of specifiers ?? []) { - if ( - !(specifier in projectGraph.nodes) && - // Todo(@agentender): Remove the check for self / dependencies in v17 - !['self', 'dependencies'].includes(specifier) - ) { - output.error({ - title: `dependsOn is improperly configured for ${project}:${target}`, - bodyLines: [ - `${specifier} in dependsOn.projects is invalid. It should be "self", "dependencies", or a project name.`, - ], - }); - process.exit(1); - } - } if (dependencyConfig.projects && dependencyConfig.dependencies) { output.error({ title: `dependsOn is improperly configured for ${project}:${target}`,