fix(core): filter out task dependencies on itself (#28261)
<!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> <!-- If this is a particularly complex change or feature addition, you can request a dedicated Nx release for this pull request branch. Mention someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they will confirm if the PR warrants its own release for testing purposes, and generate it for you if appropriate. --> ## Current Behavior <!-- This is the behavior we have today --> Tasks can end up depending on themselves if they depend on a dummy task which ends up depending back on itself. This throws a weird error like: ``` NX Could not execute command because the task graph has a circular dependency devkit:build --> devkit:build-base --> nx:build-base --> nx:build-base ``` ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> Tasks cannot depend on themselves. No errors are thrown in those cases. ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #
This commit is contained in:
parent
23a217d8dd
commit
8c59a7eb40
@ -1490,6 +1490,71 @@ describe('createTaskGraph', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle cycles where tasks seem to depend on themselves (lib1:build -> lib2 -> lib1:build)', () => {
|
||||||
|
projectGraph = {
|
||||||
|
nodes: {
|
||||||
|
lib1: {
|
||||||
|
name: 'lib1',
|
||||||
|
type: 'lib',
|
||||||
|
data: {
|
||||||
|
root: 'lib1-root',
|
||||||
|
targets: {
|
||||||
|
build: {
|
||||||
|
executor: 'nx:run-commands',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lib2: {
|
||||||
|
name: 'lib2',
|
||||||
|
type: 'lib',
|
||||||
|
data: {
|
||||||
|
root: 'lib2-root',
|
||||||
|
targets: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
lib1: [{ source: 'lib1', target: 'lib2', type: 'static' }],
|
||||||
|
lib2: [{ source: 'lib2', target: 'lib1', type: 'static' }],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const taskGraph = createTaskGraph(
|
||||||
|
projectGraph,
|
||||||
|
{
|
||||||
|
build: [{ target: 'build', dependencies: true }],
|
||||||
|
},
|
||||||
|
['lib1'],
|
||||||
|
['build'],
|
||||||
|
'development',
|
||||||
|
{
|
||||||
|
__overrides_unparsed__: [],
|
||||||
|
}
|
||||||
|
);
|
||||||
|
expect(taskGraph).toEqual({
|
||||||
|
roots: ['lib1:build'],
|
||||||
|
tasks: {
|
||||||
|
'lib1:build': expect.objectContaining({
|
||||||
|
id: 'lib1:build',
|
||||||
|
target: {
|
||||||
|
project: 'lib1',
|
||||||
|
target: 'build',
|
||||||
|
},
|
||||||
|
outputs: expect.arrayContaining([expect.any(String)]),
|
||||||
|
overrides: {
|
||||||
|
__overrides_unparsed__: [],
|
||||||
|
},
|
||||||
|
projectRoot: 'lib1-root',
|
||||||
|
parallelism: true,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
'lib1:build': [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should handle cycles between projects where all projects do not contain the same task target (lib1:build -> lib2:build -> lib3 -> lib4:build -> lib1:build)', () => {
|
it('should handle cycles between projects where all projects do not contain the same task target (lib1:build -> lib2:build -> lib3 -> lib4:build -> lib1:build)', () => {
|
||||||
projectGraph = {
|
projectGraph = {
|
||||||
nodes: {
|
nodes: {
|
||||||
|
|||||||
@ -85,10 +85,12 @@ export class ProcessTasks {
|
|||||||
|
|
||||||
this.filterDummyTasks();
|
this.filterDummyTasks();
|
||||||
|
|
||||||
for (const projectName of Object.keys(this.dependencies)) {
|
for (const taskId of Object.keys(this.dependencies)) {
|
||||||
if (this.dependencies[projectName].length > 1) {
|
if (this.dependencies[taskId].length > 0) {
|
||||||
this.dependencies[projectName] = [
|
this.dependencies[taskId] = [
|
||||||
...new Set(this.dependencies[projectName]).values(),
|
...new Set(
|
||||||
|
this.dependencies[taskId].filter((d) => d !== taskId)
|
||||||
|
).values(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user