diff --git a/docs/shared/configuration/packagejson.md b/docs/shared/configuration/packagejson.md index 685eadf222718..fcd00208102d6 100644 --- a/docs/shared/configuration/packagejson.md +++ b/docs/shared/configuration/packagejson.md @@ -133,10 +133,10 @@ Targets can depend on other targets. This is the relevant portion of the configu ```json "build": { -"dependsOn": ["^build"] + "dependsOn": ["^build"] }, "test": { -"dependsOn": ["build"] + "dependsOn": ["build"] } ``` @@ -152,14 +152,32 @@ instance, `"dependsOn": ["build"]` of the `test` target tells Nx that before it can test `mylib` it needs to make sure that `mylib` is built, which will result in `mylib`'s dependencies being built as well. -> You can also express the same configuration using +You can also express the same configuration using: ```json "build": { -"dependsOn": [{projects: "dependencies", target: "build"}] + "dependsOn": [{ "projects": "dependencies", "target": "build" }] }, "test": { -"dependsOn": [{projects: "self", target: "build"}] + "dependsOn": [{ "projects": "self", "target": "build" }] +} +``` + +With the expanded syntax, you also have a third option available to configure how to handle the params passed to the target +dependencies. You can either forward them to the dependency target, or you can ignore them (default). + +```json +"build": { + // forward params passed to this target to the dependency targets + "dependsOn": [{ "projects": "dependencies", "target": "build", "params": "forward" }] +}, +"test": { + // ignore params passed to this target, won't be forwarded to the dependency targets + "dependsOn": [{ "projects": "self", "target": "build", "params": "ignore" }] +} +"lint": { + // ignore params passed to this target, won't be forwarded to the dependency targets + "dependsOn": [{ "projects": "self", "target": "build" }] } ``` diff --git a/docs/shared/configuration/projectjson.md b/docs/shared/configuration/projectjson.md index faec0ed43c493..822afbe8a1e8f 100644 --- a/docs/shared/configuration/projectjson.md +++ b/docs/shared/configuration/projectjson.md @@ -298,14 +298,32 @@ Another common scenario is for a target to depend on another target of the same the `test` target tells Nx that before it can test `mylib` it needs to make sure that `mylib` is built, which will result in `mylib`'s dependencies being built as well. -> You can also express the same configuration using +You can also express the same configuration using: ```json "build": { - "dependsOn": [{ projects: "dependencies", target: "build"}] + "dependsOn": [{ "projects": "dependencies", "target": "build" }] }, "test": { - "dependsOn": [{ projects: "self", target: "build"}] + "dependsOn": [{ "projects": "self", "target": "build" }] +} +``` + +With the expanded syntax, you also have a third option available to configure how to handle the params passed to the target +dependencies. You can either forward them to the dependency target, or you can ignore them (default). + +```json +"build": { + // forward params passed to this target to the dependency targets + "dependsOn": [{ "projects": "dependencies", "target": "build", "params": "forward" }] +}, +"test": { + // ignore params passed to this target, won't be forwarded to the dependency targets + "dependsOn": [{ "projects": "self", "target": "build", "params": "ignore" }] +} +"lint": { + // ignore params passed to this target, won't be forwarded to the dependency targets + "dependsOn": [{ "projects": "self", "target": "build" }] } ``` diff --git a/packages/nx/schemas/nx-schema.json b/packages/nx/schemas/nx-schema.json index 5efb8658cf8e3..cd6506d99b2b2 100644 --- a/packages/nx/schemas/nx-schema.json +++ b/packages/nx/schemas/nx-schema.json @@ -191,9 +191,16 @@ "target": { "type": "string", "description": "The name of the target." + }, + "params": { + "type": "string", + "description": "Configuration for params handling.", + "enum": ["ignore", "forward"], + "default": "ignore" } }, - "additionalProperties": false + "additionalProperties": false, + "required": ["projects", "target"] } ] } @@ -223,9 +230,16 @@ "target": { "type": "string", "description": "The name of the target." + }, + "params": { + "type": "string", + "description": "Configuration for params handling.", + "enum": ["ignore", "forward"], + "default": "ignore" } }, - "additionalProperties": false + "additionalProperties": false, + "required": ["projects", "target"] } ] } diff --git a/packages/nx/schemas/project-schema.json b/packages/nx/schemas/project-schema.json index ee820d3eccd78..60a77577f5f0b 100644 --- a/packages/nx/schemas/project-schema.json +++ b/packages/nx/schemas/project-schema.json @@ -58,9 +58,16 @@ "target": { "type": "string", "description": "The name of the target." + }, + "params": { + "type": "string", + "description": "Configuration for params handling.", + "enum": ["ignore", "forward"], + "default": "ignore" } }, - "additionalProperties": false + "additionalProperties": false, + "required": ["projects", "target"] } ] } diff --git a/packages/nx/schemas/workspace-schema.json b/packages/nx/schemas/workspace-schema.json index ae8cfbeec0928..02c1513bf9054 100644 --- a/packages/nx/schemas/workspace-schema.json +++ b/packages/nx/schemas/workspace-schema.json @@ -57,19 +57,33 @@ "type": "array", "description": "Target dependency.", "items": { - "type": "object", - "properties": { - "projects": { - "type": "string", - "description": "The projects that the targets belong to.", - "enum": ["self", "dependencies"] + "oneOf": [ + { + "type": "string" }, - "target": { - "type": "string", - "description": "The name of the target." + { + "type": "object", + "properties": { + "projects": { + "type": "string", + "description": "The projects that the targets belong to.", + "enum": ["self", "dependencies"] + }, + "target": { + "type": "string", + "description": "The name of the target." + }, + "params": { + "type": "string", + "description": "Configuration for params handling.", + "enum": ["ignore", "forward"], + "default": "ignore" + } + }, + "additionalProperties": false, + "required": ["projects", "target"] } - }, - "additionalProperties": false + ] } } } diff --git a/packages/nx/src/config/workspace-json-project-json.ts b/packages/nx/src/config/workspace-json-project-json.ts index 5bafb73eb6c28..406c7dc9c0502 100644 --- a/packages/nx/src/config/workspace-json-project-json.ts +++ b/packages/nx/src/config/workspace-json-project-json.ts @@ -112,6 +112,11 @@ export interface TargetDependencyConfig { * The name of the target */ target: string; + + /** + * Configuration for params handling. + */ + params?: 'ignore' | 'forward'; } export type InputDefinition = 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 4bcf1b79035a7..2db27db7f15d9 100644 --- a/packages/nx/src/tasks-runner/create-task-graph.spec.ts +++ b/packages/nx/src/tasks-runner/create-task-graph.spec.ts @@ -3,6 +3,7 @@ import { createTaskGraph } from 'nx/src/tasks-runner/create-task-graph'; describe('createTaskGraph', () => { let projectGraph: ProjectGraph; + beforeEach(() => { projectGraph = { nodes: { @@ -167,6 +168,133 @@ describe('createTaskGraph', () => { }); }); + it('should forward args when configured', () => { + projectGraph = { + nodes: { + app1: { + name: 'app1', + type: 'app', + data: { + root: 'app1-root', + files: [], + targets: { + 'prebuild-base': {}, + prebuild: {}, + build: { + dependsOn: [ + { + projects: 'dependencies', + target: 'build', + params: 'forward', + }, + { projects: 'self', target: 'prebuild', params: 'forward' }, + ], + }, + test: {}, + serve: {}, + }, + }, + }, + lib1: { + name: 'lib1', + type: 'lib', + data: { + root: 'lib1-root', + files: [], + targets: { + build: { + dependsOn: [ + { + projects: 'dependencies', + target: 'build', + params: 'ignore', + }, + ], + }, + test: {}, + }, + }, + }, + lib2: { + name: 'lib2', + type: 'lib', + data: { + root: 'lib2-root', + files: [], + targets: { build: {}, test: {} }, + }, + }, + }, + dependencies: { + app1: [ + { source: 'app1', target: 'lib1', type: 'static' }, + { source: 'app1', target: 'lib2', type: 'static' }, + ], + lib1: [{ source: 'lib1', target: 'lib2', type: 'static' }], + lib2: [], + }, + }; + + const taskResult = createTaskGraph( + projectGraph, + {}, + ['app1'], + ['build'], + 'development', + { + myFlag: 'flag value', + } + ); + + expect(taskResult).toEqual({ + roots: ['lib2:build', 'app1:prebuild'], + tasks: { + 'app1:build': { + id: 'app1:build', + target: { + project: 'app1', + target: 'build', + }, + overrides: { myFlag: 'flag value' }, + projectRoot: 'app1-root', + }, + 'app1:prebuild': { + id: 'app1:prebuild', + target: { + project: 'app1', + target: 'prebuild', + }, + overrides: { myFlag: 'flag value' }, + projectRoot: 'app1-root', + }, + 'lib1:build': { + id: 'lib1:build', + target: { + project: 'lib1', + target: 'build', + }, + overrides: { myFlag: 'flag value' }, + projectRoot: 'lib1-root', + }, + 'lib2:build': { + id: 'lib2:build', + target: { + project: 'lib2', + target: 'build', + }, + overrides: { __overrides_unparsed__: [] }, + projectRoot: 'lib2-root', + }, + }, + dependencies: { + 'app1:build': ['lib1:build', 'lib2:build', 'app1:prebuild'], + 'app1:prebuild': [], + 'lib1:build': ['lib2:build'], + 'lib2:build': [], + }, + }); + }); + it('should create graphs with dependencies', () => { const taskGraph = createTaskGraph( projectGraph, diff --git a/packages/nx/src/tasks-runner/create-task-graph.ts b/packages/nx/src/tasks-runner/create-task-graph.ts index 16805e893a0a7..2e1b91adaf70f 100644 --- a/packages/nx/src/tasks-runner/create-task-graph.ts +++ b/packages/nx/src/tasks-runner/create-task-graph.ts @@ -1,5 +1,4 @@ import { ProjectGraph, ProjectGraphProjectNode } from '../config/project-graph'; -import { TargetDependencyConfig } from '../config/workspace-json-project-json'; import { getDependencyConfigs, interpolate } from './utils'; import { projectHasTarget, @@ -45,7 +44,7 @@ export class ProcessTasks { } for (const taskId of Object.keys(this.tasks)) { const task = this.tasks[taskId]; - this.processTask(task, task.target.project, configuration); + this.processTask(task, task.target.project, configuration, overrides); } return Object.keys(this.dependencies).filter( (d) => this.dependencies[d].length === 0 @@ -55,7 +54,8 @@ export class ProcessTasks { processTask( task: Task, projectUsedToDeriveDependencies: string, - configuration: string + configuration: string, + overrides: Object ) { const seenKey = `${task.id}-${projectUsedToDeriveDependencies}`; if (this.seen.has(seenKey)) { @@ -69,6 +69,11 @@ export class ProcessTasks { this.projectGraph ); for (const dependencyConfig of dependencyConfigs) { + const taskOverrides = + dependencyConfig.params === 'forward' + ? overrides + : { __overrides_unparsed__: [] }; + if (dependencyConfig.projects === 'dependencies') { for (const dep of this.projectGraph.dependencies[ projectUsedToDeriveDependencies @@ -101,15 +106,25 @@ export class ProcessTasks { depProject, dependencyConfig.target, resolvedConfiguration, - { __overrides_unparsed__: [] } + taskOverrides ); this.tasks[depTargetId] = newTask; this.dependencies[depTargetId] = []; - this.processTask(newTask, newTask.target.project, configuration); + this.processTask( + newTask, + newTask.target.project, + configuration, + taskOverrides + ); } } else { - this.processTask(task, depProject.name, configuration); + this.processTask( + task, + depProject.name, + configuration, + taskOverrides + ); } } } else { @@ -137,11 +152,16 @@ export class ProcessTasks { selfProject, dependencyConfig.target, resolvedConfiguration, - { __overrides_unparsed__: [] } + taskOverrides ); this.tasks[selfTaskId] = newTask; this.dependencies[selfTaskId] = []; - this.processTask(newTask, newTask.target.project, configuration); + this.processTask( + newTask, + newTask.target.project, + configuration, + taskOverrides + ); } } }