feat(core): allow dependsOn to accept a single project dependency (#16100)
This commit is contained in:
parent
7989facc85
commit
f2f6e356a7
@ -276,6 +276,9 @@ result in `mylib`'s dependencies being built as well.
|
||||
|
||||
You can also express the same configuration using:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="Version < 16" %}
|
||||
|
||||
```json
|
||||
"build": {
|
||||
"dependsOn": [{ "projects": "dependencies", "target": "build" }]
|
||||
@ -285,8 +288,26 @@ You can also express the same configuration using:
|
||||
}
|
||||
```
|
||||
|
||||
{% /tab %}
|
||||
{% tab label="Version 16+" %}
|
||||
|
||||
```json
|
||||
"build": {
|
||||
"dependsOn": [{ "projects": "{dependencies}", "target": "build" }]
|
||||
},
|
||||
"test": {
|
||||
"dependsOn": [{ "projects": "{self}", "target": "build" }]
|
||||
}
|
||||
```
|
||||
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
With the expanded syntax, you also have a third option available to configure how to handle the params passed to the target. You can either forward them or you can ignore them (default).
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="Version < 16" %}
|
||||
|
||||
```json
|
||||
"build": {
|
||||
// forward params passed to this target to the dependency targets
|
||||
@ -302,8 +323,32 @@ With the expanded syntax, you also have a third option available to configure ho
|
||||
}
|
||||
```
|
||||
|
||||
{% /tab %}
|
||||
{% tab label="Version 16+" %}
|
||||
|
||||
```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": "{dependencies}", "target": "build", "params": "ignore" }]
|
||||
}
|
||||
"lint": {
|
||||
// ignore params passed to this target, won't be forwarded to the dependency targets
|
||||
"dependsOn": [{ "projects": "{dependencies}", "target": "build" }]
|
||||
}
|
||||
```
|
||||
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
Obviously this also works when defining a relation for the target of the project itself using `"projects": "self"`:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="Version < 16" %}
|
||||
|
||||
```json
|
||||
"build": {
|
||||
// forward params passed to this target to the project target
|
||||
@ -311,6 +356,28 @@ Obviously this also works when defining a relation for the target of the project
|
||||
}
|
||||
```
|
||||
|
||||
{% /tab %}
|
||||
{% tab label="Version 16+" %}
|
||||
|
||||
```json
|
||||
"build": {
|
||||
// forward params passed to this target to the project target
|
||||
"dependsOn": [{ "projects": "{self}", "target": "pre-build", "params": "forward" }]
|
||||
}
|
||||
```
|
||||
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
Additionally, when using the expanded object syntax, you can specify individual projects in version 16 or greater.
|
||||
|
||||
```json
|
||||
"build": {
|
||||
// Run is-even:pre-build and is-odd:pre-build before this target
|
||||
"dependsOn": [{ "projects": ["is-even", "is-odd"], "target": "pre-build" }]
|
||||
}
|
||||
```
|
||||
|
||||
This configuration is usually not needed. Nx comes with reasonable defaults (imported in `nx.json`) which implement the
|
||||
configuration above.
|
||||
|
||||
|
||||
@ -59,6 +59,12 @@
|
||||
"version": "16.0.0-beta.0",
|
||||
"description": "Remove @nrwl/cli.",
|
||||
"implementation": "./src/migrations/update-16-0-0/remove-nrwl-cli"
|
||||
},
|
||||
"16.0.0-tokens-for-depends-on": {
|
||||
"cli": "nx",
|
||||
"version": "16.0.0-beta.0",
|
||||
"description": "Replace `dependsOn.projects` with {self} or {dependencies} tokens so that it matches the new expected formatting.",
|
||||
"implementation": "./src/migrations/update-16-0-0/update-depends-on-to-tokens"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -247,9 +247,19 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"projects": {
|
||||
"type": "string",
|
||||
"description": "The projects that the targets belong to.",
|
||||
"enum": ["self", "dependencies"]
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "{self}, {dependencies}, or a project name."
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"description": "An array of project specifiers: {self}, {dependencies}, or a project name.",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"target": {
|
||||
"type": "string",
|
||||
|
||||
@ -55,9 +55,19 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"projects": {
|
||||
"type": "string",
|
||||
"description": "The projects that the targets belong to.",
|
||||
"enum": ["self", "dependencies"]
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "{self}, {dependencies}, or a project name."
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"description": "An array of project specifiers: {self}, {dependencies}, or a project name.",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"target": {
|
||||
"type": "string",
|
||||
|
||||
@ -65,9 +65,19 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"projects": {
|
||||
"type": "string",
|
||||
"description": "The projects that the targets belong to.",
|
||||
"enum": ["self", "dependencies"]
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "{self}, {dependencies}, or a project name."
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"description": "An array of project specifiers: {self}, {dependencies}, or a project name.",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"target": {
|
||||
"type": "string",
|
||||
|
||||
@ -102,12 +102,15 @@ export interface ProjectConfiguration {
|
||||
|
||||
export interface TargetDependencyConfig {
|
||||
/**
|
||||
* This the projects that the targets belong to
|
||||
* A list of projects that have `target`. Supports project names or two special values:
|
||||
*
|
||||
* 'self': This target depends on another target of the same project
|
||||
* 'deps': This target depends on targets of the projects of it's deps.
|
||||
* - '{self}': This target depends on another target of the same project
|
||||
* - '{dependencies}': This target depends on targets of the projects of it's deps.
|
||||
*
|
||||
* The special values {self}/{dependencies} should be preferred - they prevent cases where a project
|
||||
* that needs to be built is missed.
|
||||
*/
|
||||
projects: 'self' | 'dependencies';
|
||||
projects: string[] | string;
|
||||
|
||||
/**
|
||||
* The name of the target
|
||||
|
||||
@ -0,0 +1,104 @@
|
||||
import {
|
||||
addProjectConfiguration,
|
||||
getProjects,
|
||||
readNxJson,
|
||||
readProjectConfiguration,
|
||||
} from '../../generators/utils/project-configuration';
|
||||
import { Tree } from '../../generators/tree';
|
||||
|
||||
import update from './update-depends-on-to-tokens';
|
||||
import { updateJson, writeJson } from 'nx/src/devkit-exports';
|
||||
import { createTreeWithEmptyWorkspace } from '../../generators/testing-utils/create-tree-with-empty-workspace';
|
||||
|
||||
describe('update-depends-on-to-tokens', () => {
|
||||
it('should update nx.json', async () => {
|
||||
const tree = createTreeWithEmptyWorkspace();
|
||||
updateJson(tree, 'nx.json', (json) => {
|
||||
json.targetDefaults = {
|
||||
build: {
|
||||
dependsOn: [
|
||||
{
|
||||
projects: 'self',
|
||||
},
|
||||
],
|
||||
},
|
||||
test: {
|
||||
dependsOn: [
|
||||
{
|
||||
projects: 'dependencies',
|
||||
},
|
||||
],
|
||||
},
|
||||
other: {
|
||||
dependsOn: ['^deps'],
|
||||
},
|
||||
};
|
||||
return json;
|
||||
});
|
||||
await update(tree);
|
||||
const nxJson = readNxJson(tree);
|
||||
const build = nxJson.targetDefaults.build.dependsOn[0] as any;
|
||||
const test = nxJson.targetDefaults.test.dependsOn[0] as any;
|
||||
expect(build.projects).toEqual('{self}');
|
||||
expect(test.projects).toEqual('{dependencies}');
|
||||
expect(nxJson.targetDefaults.other.dependsOn).toEqual(['^deps']);
|
||||
});
|
||||
|
||||
it('should update project configurations', async () => {
|
||||
const tree = createTreeWithEmptyWorkspace();
|
||||
addProjectConfiguration(tree, 'proj1', {
|
||||
root: 'proj1',
|
||||
targets: {
|
||||
build: {
|
||||
dependsOn: [
|
||||
{
|
||||
projects: 'self',
|
||||
target: 'build',
|
||||
},
|
||||
],
|
||||
},
|
||||
test: {
|
||||
dependsOn: [
|
||||
{
|
||||
projects: 'dependencies',
|
||||
target: 'test',
|
||||
},
|
||||
],
|
||||
},
|
||||
other: {
|
||||
dependsOn: ['^deps'],
|
||||
},
|
||||
},
|
||||
});
|
||||
await update(tree);
|
||||
const project = readProjectConfiguration(tree, 'proj1');
|
||||
const build = project.targets.build.dependsOn[0] as any;
|
||||
const test = project.targets.test.dependsOn[0] as any;
|
||||
expect(build.projects).toEqual('{self}');
|
||||
expect(test.projects).toEqual('{dependencies}');
|
||||
expect(project.targets.other.dependsOn).toEqual(['^deps']);
|
||||
});
|
||||
|
||||
it('should not throw on nulls', async () => {
|
||||
const tree = createTreeWithEmptyWorkspace();
|
||||
addProjectConfiguration(tree, 'proj1', {
|
||||
root: 'proj1',
|
||||
});
|
||||
addProjectConfiguration(tree, 'proj2', {
|
||||
root: 'proj2',
|
||||
targets: {
|
||||
build: {},
|
||||
},
|
||||
});
|
||||
writeJson(tree, 'nx.json', {});
|
||||
let promise = update(tree);
|
||||
await expect(promise).resolves.toBeUndefined();
|
||||
writeJson(tree, 'nx.json', {
|
||||
targetDefaults: {
|
||||
build: {},
|
||||
},
|
||||
});
|
||||
promise = update(tree);
|
||||
await expect(promise).resolves.toBeUndefined();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,56 @@
|
||||
import {
|
||||
getProjects,
|
||||
readNxJson,
|
||||
updateNxJson,
|
||||
updateProjectConfiguration,
|
||||
} from '../../generators/utils/project-configuration';
|
||||
import { Tree } from '../../generators/tree';
|
||||
|
||||
export default async function (tree: Tree) {
|
||||
updateDependsOnInsideNxJson(tree);
|
||||
|
||||
const projectsConfigurations = getProjects(tree);
|
||||
for (const [projectName, projectConfiguration] of projectsConfigurations) {
|
||||
let projectChanged = false;
|
||||
for (const [targetName, targetConfiguration] of Object.entries(
|
||||
projectConfiguration.targets ?? {}
|
||||
)) {
|
||||
for (const dependency of targetConfiguration.dependsOn ?? []) {
|
||||
if (typeof dependency !== 'string') {
|
||||
if (dependency.projects === 'self') {
|
||||
dependency.projects = '{self}';
|
||||
projectChanged = true;
|
||||
} else if (dependency.projects === 'dependencies') {
|
||||
dependency.projects = '{dependencies}';
|
||||
projectChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (projectChanged) {
|
||||
updateProjectConfiguration(tree, projectName, projectConfiguration);
|
||||
}
|
||||
}
|
||||
}
|
||||
function updateDependsOnInsideNxJson(tree: Tree) {
|
||||
const nxJson = readNxJson(tree);
|
||||
let nxJsonChanged = false;
|
||||
for (const [target, defaults] of Object.entries(
|
||||
nxJson?.targetDefaults ?? {}
|
||||
)) {
|
||||
for (const dependency of defaults.dependsOn ?? []) {
|
||||
if (typeof dependency !== 'string') {
|
||||
if (dependency.projects === 'self') {
|
||||
dependency.projects = '{self}';
|
||||
nxJsonChanged = true;
|
||||
} else if (dependency.projects === 'dependencies') {
|
||||
dependency.projects = '{dependencies}';
|
||||
nxJsonChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nxJsonChanged) {
|
||||
updateNxJson(tree, nxJson);
|
||||
}
|
||||
}
|
||||
@ -17,17 +17,24 @@ describe('createTaskGraph', () => {
|
||||
prebuild: {
|
||||
executor: 'nx:run-commands',
|
||||
},
|
||||
prebuild2: {
|
||||
executor: 'nx:run-commands',
|
||||
},
|
||||
build: {
|
||||
executor: 'nx:run-commands',
|
||||
dependsOn: [
|
||||
{
|
||||
projects: 'dependencies',
|
||||
projects: '{dependencies}',
|
||||
target: 'build',
|
||||
},
|
||||
{
|
||||
projects: 'self',
|
||||
projects: '{self}',
|
||||
target: 'prebuild',
|
||||
},
|
||||
{
|
||||
projects: 'app1',
|
||||
target: 'prebuild2',
|
||||
},
|
||||
],
|
||||
},
|
||||
test: {
|
||||
@ -166,7 +173,7 @@ describe('createTaskGraph', () => {
|
||||
},
|
||||
dependsOn: [
|
||||
{
|
||||
projects: 'dependencies',
|
||||
projects: '{dependencies}',
|
||||
target: 'build',
|
||||
},
|
||||
],
|
||||
@ -189,7 +196,7 @@ describe('createTaskGraph', () => {
|
||||
defaultConfiguration: 'libDefault',
|
||||
dependsOn: [
|
||||
{
|
||||
projects: 'dependencies',
|
||||
projects: '{dependencies}',
|
||||
target: 'build',
|
||||
},
|
||||
],
|
||||
@ -330,7 +337,7 @@ describe('createTaskGraph', () => {
|
||||
executor: 'my-executor',
|
||||
dependsOn: [
|
||||
{
|
||||
projects: 'dependencies',
|
||||
projects: '{dependencies}',
|
||||
target: 'build',
|
||||
},
|
||||
],
|
||||
@ -501,11 +508,11 @@ describe('createTaskGraph', () => {
|
||||
executor: 'nx:run-commands',
|
||||
dependsOn: [
|
||||
{
|
||||
projects: 'dependencies',
|
||||
projects: '{dependencies}',
|
||||
target: 'build',
|
||||
params: 'forward',
|
||||
},
|
||||
{ projects: 'self', target: 'prebuild', params: 'forward' },
|
||||
{ projects: '{self}', target: 'prebuild', params: 'forward' },
|
||||
],
|
||||
},
|
||||
test: {
|
||||
@ -528,7 +535,7 @@ describe('createTaskGraph', () => {
|
||||
executor: 'nx:run-commands',
|
||||
dependsOn: [
|
||||
{
|
||||
projects: 'dependencies',
|
||||
projects: '{dependencies}',
|
||||
target: 'build',
|
||||
params: 'ignore',
|
||||
},
|
||||
@ -640,7 +647,7 @@ describe('createTaskGraph', () => {
|
||||
);
|
||||
// prebuild should also be in here
|
||||
expect(taskGraph).toEqual({
|
||||
roots: ['lib1:build', 'app1:prebuild'],
|
||||
roots: ['lib1:build', 'app1:prebuild', 'app1:prebuild2'],
|
||||
tasks: {
|
||||
'app1:build': {
|
||||
id: 'app1:build',
|
||||
@ -664,6 +671,17 @@ describe('createTaskGraph', () => {
|
||||
},
|
||||
projectRoot: 'app1-root',
|
||||
},
|
||||
'app1:prebuild2': {
|
||||
id: 'app1:prebuild2',
|
||||
target: {
|
||||
project: 'app1',
|
||||
target: 'prebuild2',
|
||||
},
|
||||
overrides: {
|
||||
__overrides_unparsed__: [],
|
||||
},
|
||||
projectRoot: 'app1-root',
|
||||
},
|
||||
'lib1:build': {
|
||||
id: 'lib1:build',
|
||||
target: {
|
||||
@ -677,8 +695,9 @@ describe('createTaskGraph', () => {
|
||||
},
|
||||
},
|
||||
dependencies: {
|
||||
'app1:build': ['lib1:build', 'app1:prebuild'],
|
||||
'app1:build': ['lib1:build', 'app1:prebuild', 'app1:prebuild2'],
|
||||
'app1:prebuild': [],
|
||||
'app1:prebuild2': [],
|
||||
'lib1:build': [],
|
||||
},
|
||||
});
|
||||
@ -697,7 +716,7 @@ describe('createTaskGraph', () => {
|
||||
);
|
||||
// prebuild should also be in here
|
||||
expect(taskGraph).toEqual({
|
||||
roots: ['app1:prebuild', 'lib1:build'],
|
||||
roots: ['app1:prebuild', 'lib1:build', 'app1:prebuild2'],
|
||||
tasks: {
|
||||
'app1:build': {
|
||||
id: 'app1:build',
|
||||
@ -721,6 +740,17 @@ describe('createTaskGraph', () => {
|
||||
},
|
||||
projectRoot: 'app1-root',
|
||||
},
|
||||
'app1:prebuild2': {
|
||||
id: 'app1:prebuild2',
|
||||
target: {
|
||||
project: 'app1',
|
||||
target: 'prebuild2',
|
||||
},
|
||||
overrides: {
|
||||
__overrides_unparsed__: [],
|
||||
},
|
||||
projectRoot: 'app1-root',
|
||||
},
|
||||
'lib1:build': {
|
||||
id: 'lib1:build',
|
||||
target: {
|
||||
@ -734,8 +764,9 @@ describe('createTaskGraph', () => {
|
||||
},
|
||||
},
|
||||
dependencies: {
|
||||
'app1:build': ['lib1:build', 'app1:prebuild'],
|
||||
'app1:build': ['lib1:build', 'app1:prebuild', 'app1:prebuild2'],
|
||||
'app1:prebuild': [],
|
||||
'app1:prebuild2': [],
|
||||
'lib1:build': [],
|
||||
},
|
||||
});
|
||||
@ -813,7 +844,7 @@ describe('createTaskGraph', () => {
|
||||
{
|
||||
build: [
|
||||
{
|
||||
projects: 'dependencies',
|
||||
projects: '{dependencies}',
|
||||
target: 'build',
|
||||
},
|
||||
],
|
||||
@ -974,9 +1005,9 @@ describe('createTaskGraph', () => {
|
||||
{
|
||||
build: ['^build'],
|
||||
apply: [
|
||||
{ projects: 'dependencies', target: 'build' },
|
||||
{ projects: '{dependencies}', target: 'build' },
|
||||
{
|
||||
projects: 'dependencies',
|
||||
projects: '{dependencies}',
|
||||
target: 'apply',
|
||||
params: 'forward',
|
||||
},
|
||||
@ -1052,11 +1083,11 @@ describe('createTaskGraph', () => {
|
||||
targets: {
|
||||
build: {
|
||||
executor: 'nx:run-commands',
|
||||
dependsOn: [{ target: 'test', projects: 'self' }],
|
||||
dependsOn: [{ target: 'test', projects: '{self}' }],
|
||||
},
|
||||
test: {
|
||||
executor: 'nx:run-commands',
|
||||
dependsOn: [{ target: 'build', projects: 'self' }],
|
||||
dependsOn: [{ target: 'build', projects: '{self}' }],
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -1161,7 +1192,7 @@ describe('createTaskGraph', () => {
|
||||
const taskGraph = createTaskGraph(
|
||||
projectGraph,
|
||||
{
|
||||
build: [{ target: 'build', projects: 'dependencies' }],
|
||||
build: [{ target: 'build', projects: '{dependencies}' }],
|
||||
},
|
||||
['app1'],
|
||||
['build'],
|
||||
@ -1252,7 +1283,7 @@ describe('createTaskGraph', () => {
|
||||
const taskGraph = createTaskGraph(
|
||||
projectGraph,
|
||||
{
|
||||
build: [{ target: 'build', projects: 'dependencies' }],
|
||||
build: [{ target: 'build', projects: '{dependencies}' }],
|
||||
},
|
||||
['app1'],
|
||||
['build'],
|
||||
@ -1307,8 +1338,8 @@ describe('createTaskGraph', () => {
|
||||
build: {
|
||||
executor: 'nx:run-commands',
|
||||
dependsOn: [
|
||||
{ target: 'prebuild', projects: 'self' },
|
||||
{ target: 'build', projects: 'dependencies' },
|
||||
{ target: 'prebuild', projects: '{self}' },
|
||||
{ target: 'build', projects: '{dependencies}' },
|
||||
],
|
||||
},
|
||||
prebuild: {
|
||||
|
||||
@ -6,6 +6,7 @@ import {
|
||||
} from '../utils/project-graph-utils';
|
||||
import { Task, TaskGraph } from '../config/task-graph';
|
||||
import { TargetDependencies } from '../config/nx-json';
|
||||
import { TargetDependencyConfig } from '../devkit-exports';
|
||||
|
||||
export class ProcessTasks {
|
||||
private readonly seen = new Set<string>();
|
||||
@ -104,92 +105,150 @@ export class ProcessTasks {
|
||||
dependencyConfig.params === 'forward'
|
||||
? overrides
|
||||
: { __overrides_unparsed__: [] };
|
||||
const targetProjectSpecifiers =
|
||||
typeof dependencyConfig.projects === 'string'
|
||||
? [dependencyConfig.projects]
|
||||
: dependencyConfig.projects;
|
||||
for (const projectSpecifier of targetProjectSpecifiers) {
|
||||
// Lerna uses `dependencies` in `prepNxOptions`, so we need to maintain
|
||||
// support for it until lerna can be updated to use the new tokens.
|
||||
// TODO(@agentender): Remove this part in v17
|
||||
if (
|
||||
projectSpecifier === '{dependencies}' ||
|
||||
(projectSpecifier === 'dependencies' &&
|
||||
!this.projectGraph.nodes[projectSpecifier])
|
||||
) {
|
||||
this.processTasksForDependencies(
|
||||
projectUsedToDeriveDependencies,
|
||||
dependencyConfig,
|
||||
configuration,
|
||||
task,
|
||||
taskOverrides,
|
||||
overrides
|
||||
);
|
||||
} else {
|
||||
// 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 =
|
||||
projectSpecifier === '{self}' ||
|
||||
(projectSpecifier === 'self' &&
|
||||
!this.projectGraph.nodes[projectSpecifier])
|
||||
? task.target.project
|
||||
: projectSpecifier;
|
||||
|
||||
if (dependencyConfig.projects === 'dependencies') {
|
||||
for (const dep of this.projectGraph.dependencies[
|
||||
projectUsedToDeriveDependencies
|
||||
]) {
|
||||
const depProject = this.projectGraph.nodes[
|
||||
dep.target
|
||||
] as ProjectGraphProjectNode;
|
||||
this.processTasksForSingleProject(
|
||||
task,
|
||||
projectName,
|
||||
dependencyConfig,
|
||||
configuration,
|
||||
taskOverrides,
|
||||
overrides
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this is to handle external dependencies
|
||||
if (!depProject) continue;
|
||||
private processTasksForSingleProject(
|
||||
task: Task,
|
||||
projectName: string,
|
||||
dependencyConfig: TargetDependencyConfig,
|
||||
configuration: string,
|
||||
taskOverrides: Object | { __overrides_unparsed__: any[] },
|
||||
overrides: Object
|
||||
) {
|
||||
const selfProject = this.projectGraph.nodes[
|
||||
projectName
|
||||
] as ProjectGraphProjectNode;
|
||||
|
||||
if (projectHasTarget(depProject, dependencyConfig.target)) {
|
||||
const resolvedConfiguration = this.resolveConfiguration(
|
||||
depProject,
|
||||
dependencyConfig.target,
|
||||
configuration
|
||||
);
|
||||
const depTargetId = this.getId(
|
||||
depProject.name,
|
||||
dependencyConfig.target,
|
||||
resolvedConfiguration
|
||||
);
|
||||
if (projectHasTarget(selfProject, dependencyConfig.target)) {
|
||||
const resolvedConfiguration = this.resolveConfiguration(
|
||||
selfProject,
|
||||
dependencyConfig.target,
|
||||
configuration
|
||||
);
|
||||
const selfTaskId = this.getId(
|
||||
selfProject.name,
|
||||
dependencyConfig.target,
|
||||
resolvedConfiguration
|
||||
);
|
||||
if (task.id !== selfTaskId) {
|
||||
this.dependencies[task.id].push(selfTaskId);
|
||||
}
|
||||
if (!this.tasks[selfTaskId]) {
|
||||
const newTask = this.createTask(
|
||||
selfTaskId,
|
||||
selfProject,
|
||||
dependencyConfig.target,
|
||||
resolvedConfiguration,
|
||||
taskOverrides
|
||||
);
|
||||
this.tasks[selfTaskId] = newTask;
|
||||
this.dependencies[selfTaskId] = [];
|
||||
this.processTask(
|
||||
newTask,
|
||||
newTask.target.project,
|
||||
configuration,
|
||||
overrides
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (task.id !== depTargetId) {
|
||||
this.dependencies[task.id].push(depTargetId);
|
||||
}
|
||||
if (!this.tasks[depTargetId]) {
|
||||
const newTask = this.createTask(
|
||||
depTargetId,
|
||||
depProject,
|
||||
dependencyConfig.target,
|
||||
resolvedConfiguration,
|
||||
taskOverrides
|
||||
);
|
||||
this.tasks[depTargetId] = newTask;
|
||||
this.dependencies[depTargetId] = [];
|
||||
private processTasksForDependencies(
|
||||
projectUsedToDeriveDependencies: string,
|
||||
dependencyConfig: TargetDependencyConfig,
|
||||
configuration: string,
|
||||
task: Task,
|
||||
taskOverrides: Object | { __overrides_unparsed__: any[] },
|
||||
overrides: Object
|
||||
) {
|
||||
for (const dep of this.projectGraph.dependencies[
|
||||
projectUsedToDeriveDependencies
|
||||
]) {
|
||||
const depProject = this.projectGraph.nodes[
|
||||
dep.target
|
||||
] as ProjectGraphProjectNode;
|
||||
|
||||
this.processTask(
|
||||
newTask,
|
||||
newTask.target.project,
|
||||
configuration,
|
||||
overrides
|
||||
);
|
||||
}
|
||||
} else {
|
||||
this.processTask(task, depProject.name, configuration, overrides);
|
||||
}
|
||||
// this is to handle external dependencies
|
||||
if (!depProject) continue;
|
||||
|
||||
if (projectHasTarget(depProject, dependencyConfig.target)) {
|
||||
const resolvedConfiguration = this.resolveConfiguration(
|
||||
depProject,
|
||||
dependencyConfig.target,
|
||||
configuration
|
||||
);
|
||||
const depTargetId = this.getId(
|
||||
depProject.name,
|
||||
dependencyConfig.target,
|
||||
resolvedConfiguration
|
||||
);
|
||||
|
||||
if (task.id !== depTargetId) {
|
||||
this.dependencies[task.id].push(depTargetId);
|
||||
}
|
||||
if (!this.tasks[depTargetId]) {
|
||||
const newTask = this.createTask(
|
||||
depTargetId,
|
||||
depProject,
|
||||
dependencyConfig.target,
|
||||
resolvedConfiguration,
|
||||
taskOverrides
|
||||
);
|
||||
this.tasks[depTargetId] = newTask;
|
||||
this.dependencies[depTargetId] = [];
|
||||
|
||||
this.processTask(
|
||||
newTask,
|
||||
newTask.target.project,
|
||||
configuration,
|
||||
overrides
|
||||
);
|
||||
}
|
||||
} else {
|
||||
const selfProject = this.projectGraph.nodes[
|
||||
task.target.project
|
||||
] as ProjectGraphProjectNode;
|
||||
|
||||
if (projectHasTarget(selfProject, dependencyConfig.target)) {
|
||||
const resolvedConfiguration = this.resolveConfiguration(
|
||||
selfProject,
|
||||
dependencyConfig.target,
|
||||
configuration
|
||||
);
|
||||
const selfTaskId = this.getId(
|
||||
selfProject.name,
|
||||
dependencyConfig.target,
|
||||
resolvedConfiguration
|
||||
);
|
||||
if (task.id !== selfTaskId) {
|
||||
this.dependencies[task.id].push(selfTaskId);
|
||||
}
|
||||
if (!this.tasks[selfTaskId]) {
|
||||
const newTask = this.createTask(
|
||||
selfTaskId,
|
||||
selfProject,
|
||||
dependencyConfig.target,
|
||||
resolvedConfiguration,
|
||||
taskOverrides
|
||||
);
|
||||
this.tasks[selfTaskId] = newTask;
|
||||
this.dependencies[selfTaskId] = [];
|
||||
this.processTask(
|
||||
newTask,
|
||||
newTask.target.project,
|
||||
configuration,
|
||||
overrides
|
||||
);
|
||||
}
|
||||
}
|
||||
this.processTask(task, depProject.name, configuration, overrides);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,17 +32,26 @@ export function getDependencyConfigs(
|
||||
[]
|
||||
);
|
||||
for (const dependencyConfig of dependencyConfigs) {
|
||||
if (
|
||||
dependencyConfig.projects !== 'dependencies' &&
|
||||
dependencyConfig.projects !== 'self'
|
||||
) {
|
||||
output.error({
|
||||
title: `dependsOn is improperly configured for ${project}:${target}`,
|
||||
bodyLines: [
|
||||
`dependsOn.projects is "${dependencyConfig.projects}" but should be "self" or "dependencies"`,
|
||||
],
|
||||
});
|
||||
process.exit(1);
|
||||
const specifiers =
|
||||
typeof dependencyConfig.projects === 'string'
|
||||
? [dependencyConfig.projects]
|
||||
: dependencyConfig.projects;
|
||||
for (const specifier of specifiers) {
|
||||
if (
|
||||
!(specifier in projectGraph.nodes) &&
|
||||
// Todo(@agentender): Remove the non-token forms of these for v17
|
||||
!['{self}', '{dependencies}', '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);
|
||||
}
|
||||
}
|
||||
}
|
||||
return dependencyConfigs;
|
||||
@ -54,9 +63,9 @@ function expandDependencyConfigSyntaxSugar(
|
||||
return deps.map((d) => {
|
||||
if (typeof d === 'string') {
|
||||
if (d.startsWith('^')) {
|
||||
return { projects: 'dependencies', target: d.substring(1) };
|
||||
return { projects: '{dependencies}', target: d.substring(1) };
|
||||
} else {
|
||||
return { projects: 'self', target: d };
|
||||
return { projects: '{self}', target: d };
|
||||
}
|
||||
} else {
|
||||
return d;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user