fix(core): include dependencies of projects which do not have a target (#6309)
This commit is contained in:
parent
d35d03e55e
commit
033579712f
@ -1,5 +1,113 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`TaskGraphCreator (tasks with dependency configurations) should create a task graph (builds depend on builds of dependencies even with intermediate projects) 1`] = `
|
||||
Object {
|
||||
"dependencies": Object {
|
||||
"app1:build": Array [
|
||||
"common2:build",
|
||||
],
|
||||
"common2:build": Array [],
|
||||
},
|
||||
"roots": Array [
|
||||
"common2:build",
|
||||
],
|
||||
"tasks": Object {
|
||||
"app1:build": Object {
|
||||
"id": "app1:build",
|
||||
"overrides": Object {},
|
||||
"projectRoot": "app1-root",
|
||||
"target": Object {
|
||||
"configuration": undefined,
|
||||
"project": "app1",
|
||||
"target": "build",
|
||||
},
|
||||
},
|
||||
"common2:build": Object {
|
||||
"id": "common2:build",
|
||||
"overrides": Object {},
|
||||
"projectRoot": "common2-root",
|
||||
"target": Object {
|
||||
"configuration": undefined,
|
||||
"project": "common2",
|
||||
"target": "build",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`TaskGraphCreator (tasks with dependency configurations) should create a task graph (builds depend on builds of dependencies with intermediate projects and circular dependencies between projects) 1`] = `
|
||||
Object {
|
||||
"dependencies": Object {
|
||||
"app1:build": Array [
|
||||
"common2:build",
|
||||
],
|
||||
"common2:build": Array [],
|
||||
},
|
||||
"roots": Array [
|
||||
"common2:build",
|
||||
],
|
||||
"tasks": Object {
|
||||
"app1:build": Object {
|
||||
"id": "app1:build",
|
||||
"overrides": Object {},
|
||||
"projectRoot": "app1-root",
|
||||
"target": Object {
|
||||
"configuration": undefined,
|
||||
"project": "app1",
|
||||
"target": "build",
|
||||
},
|
||||
},
|
||||
"common2:build": Object {
|
||||
"id": "common2:build",
|
||||
"overrides": Object {},
|
||||
"projectRoot": "common2-root",
|
||||
"target": Object {
|
||||
"configuration": undefined,
|
||||
"project": "common2",
|
||||
"target": "build",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`TaskGraphCreator (tasks with dependency configurations) should create a task graph (builds depend on builds of dependencies with intermediate projects and circular dependencies between projects) 2 1`] = `
|
||||
Object {
|
||||
"dependencies": Object {
|
||||
"app1:build": Array [
|
||||
"common3:build",
|
||||
],
|
||||
"common3:build": Array [],
|
||||
},
|
||||
"roots": Array [
|
||||
"common3:build",
|
||||
],
|
||||
"tasks": Object {
|
||||
"app1:build": Object {
|
||||
"id": "app1:build",
|
||||
"overrides": Object {},
|
||||
"projectRoot": "app1-root",
|
||||
"target": Object {
|
||||
"configuration": undefined,
|
||||
"project": "app1",
|
||||
"target": "build",
|
||||
},
|
||||
},
|
||||
"common3:build": Object {
|
||||
"id": "common3:build",
|
||||
"overrides": Object {},
|
||||
"projectRoot": "common3",
|
||||
"target": Object {
|
||||
"configuration": undefined,
|
||||
"project": "common3",
|
||||
"target": "build",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`TaskGraphCreator (tasks with dependency configurations) should create task graph (builds depend on build of dependencies and prebuild of self) 1`] = `
|
||||
Object {
|
||||
"dependencies": Object {
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { TasksRunner } from './tasks-runner';
|
||||
import defaultTaskRunner from './default-tasks-runner';
|
||||
import { createTasksForProjectToRun, getRunner } from './run-command';
|
||||
import type { NxJsonConfiguration, ProjectGraph } from '@nrwl/devkit';
|
||||
import { DependencyType } from '@nrwl/devkit';
|
||||
import type { ProjectGraph, NxJsonConfiguration } from '@nrwl/devkit';
|
||||
|
||||
describe('createTasksForProjectToRun', () => {
|
||||
let projectGraph: ProjectGraph;
|
||||
@ -331,6 +331,279 @@ describe('createTasksForProjectToRun', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('should create tasks for multiple sets of dependencies for multiple targets', () => {
|
||||
projectGraph.nodes.app1.data.targets.build.dependsOn = [
|
||||
{
|
||||
target: 'prebuild',
|
||||
projects: 'dependencies',
|
||||
},
|
||||
{
|
||||
target: 'build',
|
||||
projects: 'dependencies',
|
||||
},
|
||||
];
|
||||
projectGraph.dependencies.app1.push({
|
||||
type: DependencyType.static,
|
||||
source: 'app1',
|
||||
target: 'lib1',
|
||||
});
|
||||
|
||||
projectGraph.nodes.lib1.data.targets.prebuild = {};
|
||||
|
||||
const tasks = createTasksForProjectToRun(
|
||||
[projectGraph.nodes.app1],
|
||||
{
|
||||
target: 'build',
|
||||
configuration: undefined,
|
||||
overrides: {},
|
||||
},
|
||||
projectGraph,
|
||||
projectGraph.nodes.app1.name
|
||||
);
|
||||
|
||||
expect(tasks).toEqual([
|
||||
{
|
||||
id: 'lib1:prebuild',
|
||||
overrides: {},
|
||||
projectRoot: 'lib1-root',
|
||||
target: {
|
||||
configuration: undefined,
|
||||
project: 'lib1',
|
||||
target: 'prebuild',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'lib1:build',
|
||||
overrides: {},
|
||||
projectRoot: 'lib1-root',
|
||||
target: {
|
||||
configuration: undefined,
|
||||
project: 'lib1',
|
||||
target: 'build',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'app1:build',
|
||||
overrides: {},
|
||||
projectRoot: 'app1-root',
|
||||
target: {
|
||||
configuration: undefined,
|
||||
project: 'app1',
|
||||
target: 'build',
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should include dependencies of projects without the same target', () => {
|
||||
// App 1 depends on builds of its dependencies
|
||||
projectGraph.nodes.app1.data.targets.build.dependsOn = [
|
||||
{
|
||||
target: 'build',
|
||||
projects: 'dependencies',
|
||||
},
|
||||
];
|
||||
|
||||
// App 1 depends on Lib 1
|
||||
projectGraph.dependencies.app1.push({
|
||||
type: DependencyType.static,
|
||||
source: 'app1',
|
||||
target: 'lib1',
|
||||
});
|
||||
|
||||
// Lib 1 does not have build but depends on Lib 2
|
||||
delete projectGraph.nodes.lib1.data.targets.build;
|
||||
projectGraph.dependencies.lib1.push({
|
||||
type: DependencyType.static,
|
||||
source: 'lib1',
|
||||
target: 'lib2',
|
||||
});
|
||||
|
||||
// Lib 2 has a build
|
||||
projectGraph.nodes.lib2 = {
|
||||
name: 'lib2',
|
||||
type: 'lib',
|
||||
data: {
|
||||
root: 'lib2-root',
|
||||
files: [],
|
||||
targets: {
|
||||
build: {},
|
||||
},
|
||||
},
|
||||
};
|
||||
projectGraph.dependencies.lib2 = [];
|
||||
|
||||
const tasks = createTasksForProjectToRun(
|
||||
[projectGraph.nodes.app1],
|
||||
{
|
||||
target: 'build',
|
||||
configuration: undefined,
|
||||
overrides: {},
|
||||
},
|
||||
projectGraph,
|
||||
projectGraph.nodes.app1.name
|
||||
);
|
||||
|
||||
expect(tasks).toContainEqual({
|
||||
id: 'app1:build',
|
||||
target: { project: 'app1', target: 'build' },
|
||||
projectRoot: 'app1-root',
|
||||
overrides: {},
|
||||
});
|
||||
expect(tasks).toContainEqual({
|
||||
id: 'lib2:build',
|
||||
target: { project: 'lib2', target: 'build' },
|
||||
projectRoot: 'lib2-root',
|
||||
overrides: {},
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle circular dependencies between projects', () => {
|
||||
// App 1 depends on builds of its dependencies
|
||||
projectGraph.nodes.app1.data.targets.build.dependsOn = [
|
||||
{
|
||||
target: 'build',
|
||||
projects: 'dependencies',
|
||||
},
|
||||
];
|
||||
|
||||
// App 1 depends on Lib 1
|
||||
projectGraph.dependencies.app1.push({
|
||||
type: DependencyType.static,
|
||||
source: 'app1',
|
||||
target: 'lib1',
|
||||
});
|
||||
|
||||
// Lib 1 does not have build but depends on Lib 2
|
||||
delete projectGraph.nodes.lib1.data.targets.build;
|
||||
projectGraph.dependencies.lib1.push(
|
||||
{
|
||||
type: DependencyType.static,
|
||||
source: 'lib1',
|
||||
target: 'app1',
|
||||
},
|
||||
{
|
||||
type: DependencyType.static,
|
||||
source: 'lib1',
|
||||
target: 'lib2',
|
||||
}
|
||||
);
|
||||
|
||||
// Lib 2 has a build
|
||||
projectGraph.nodes.lib2 = {
|
||||
name: 'lib2',
|
||||
type: 'lib',
|
||||
data: {
|
||||
root: 'lib2-root',
|
||||
files: [],
|
||||
targets: {
|
||||
build: {},
|
||||
},
|
||||
},
|
||||
};
|
||||
projectGraph.dependencies.lib2 = [
|
||||
{
|
||||
type: DependencyType.static,
|
||||
source: 'lib2',
|
||||
target: 'lib1',
|
||||
},
|
||||
];
|
||||
|
||||
const tasks = createTasksForProjectToRun(
|
||||
[projectGraph.nodes.app1],
|
||||
{
|
||||
target: 'build',
|
||||
configuration: undefined,
|
||||
overrides: {},
|
||||
},
|
||||
projectGraph,
|
||||
projectGraph.nodes.app1.name
|
||||
);
|
||||
|
||||
expect(tasks).toContainEqual({
|
||||
id: 'app1:build',
|
||||
target: { project: 'app1', target: 'build' },
|
||||
projectRoot: 'app1-root',
|
||||
overrides: {},
|
||||
});
|
||||
expect(tasks).toContainEqual({
|
||||
id: 'lib2:build',
|
||||
target: { project: 'lib2', target: 'build' },
|
||||
projectRoot: 'lib2-root',
|
||||
overrides: {},
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle circular dependencies between projects with no tasks', () => {
|
||||
// App 1 depends on builds of its dependencies
|
||||
projectGraph.nodes.app1.data.targets.build.dependsOn = [
|
||||
{
|
||||
target: 'build',
|
||||
projects: 'dependencies',
|
||||
},
|
||||
];
|
||||
|
||||
// App 1 depends on Lib 1
|
||||
projectGraph.dependencies.app1.push({
|
||||
type: DependencyType.static,
|
||||
source: 'app1',
|
||||
target: 'lib1',
|
||||
});
|
||||
|
||||
// Lib 1 does not have build but depends on Lib 2
|
||||
delete projectGraph.nodes.lib1.data.targets.build;
|
||||
projectGraph.dependencies.lib1.push(
|
||||
{
|
||||
type: DependencyType.static,
|
||||
source: 'lib1',
|
||||
target: 'app1',
|
||||
},
|
||||
{
|
||||
type: DependencyType.static,
|
||||
source: 'lib1',
|
||||
target: 'lib2',
|
||||
}
|
||||
);
|
||||
|
||||
// Lib 2 has a build
|
||||
projectGraph.nodes.lib2 = {
|
||||
name: 'lib2',
|
||||
type: 'lib',
|
||||
data: {
|
||||
root: 'lib2-root',
|
||||
files: [],
|
||||
targets: {
|
||||
build: {},
|
||||
},
|
||||
},
|
||||
};
|
||||
projectGraph.dependencies.lib2 = [];
|
||||
|
||||
const tasks = createTasksForProjectToRun(
|
||||
[projectGraph.nodes.app1],
|
||||
{
|
||||
target: 'build',
|
||||
configuration: undefined,
|
||||
overrides: {},
|
||||
},
|
||||
projectGraph,
|
||||
projectGraph.nodes.app1.name
|
||||
);
|
||||
|
||||
expect(tasks).toContainEqual({
|
||||
id: 'app1:build',
|
||||
target: { project: 'app1', target: 'build' },
|
||||
projectRoot: 'app1-root',
|
||||
overrides: {},
|
||||
});
|
||||
expect(tasks).toContainEqual({
|
||||
id: 'lib2:build',
|
||||
target: { project: 'lib2', target: 'build' },
|
||||
projectRoot: 'lib2-root',
|
||||
overrides: {},
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw an error for an invalid target', () => {
|
||||
jest.spyOn(process, 'exit').mockImplementation(() => {
|
||||
throw new Error();
|
||||
|
||||
@ -155,6 +155,7 @@ export function createTasksForProjectToRun(
|
||||
defaultDependencyConfigs: Record<string, TargetDependencyConfig[]> = {}
|
||||
) {
|
||||
const tasksMap: Map<string, Task> = new Map<string, Task>();
|
||||
const seenSet = new Set<string>();
|
||||
|
||||
for (const project of projectsToRun) {
|
||||
addTasksForProjectTarget(
|
||||
@ -166,7 +167,8 @@ export function createTasksForProjectToRun(
|
||||
defaultDependencyConfigs,
|
||||
projectGraph,
|
||||
tasksMap,
|
||||
[]
|
||||
[],
|
||||
seenSet
|
||||
);
|
||||
}
|
||||
return Array.from(tasksMap.values());
|
||||
@ -183,7 +185,8 @@ function addTasksForProjectTarget(
|
||||
defaultDependencyConfigs: Record<string, TargetDependencyConfig[]> = {},
|
||||
projectGraph: ProjectGraph,
|
||||
tasksMap: Map<string, Task>,
|
||||
path: string[]
|
||||
path: string[],
|
||||
seenSet: Set<string>
|
||||
) {
|
||||
const task = createTask({
|
||||
project,
|
||||
@ -211,7 +214,8 @@ function addTasksForProjectTarget(
|
||||
defaultDependencyConfigs,
|
||||
projectGraph,
|
||||
tasksMap,
|
||||
path
|
||||
path,
|
||||
seenSet
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -267,13 +271,15 @@ function addTasksForProjectDependencyConfig(
|
||||
defaultDependencyConfigs: Record<string, TargetDependencyConfig[]>,
|
||||
projectGraph: ProjectGraph,
|
||||
tasksMap: Map<string, Task>,
|
||||
path: string[]
|
||||
path: string[],
|
||||
seenSet: Set<string>
|
||||
) {
|
||||
const targetIdentifier = getId({
|
||||
project: project.name,
|
||||
target,
|
||||
configuration,
|
||||
});
|
||||
seenSet.add(project.name);
|
||||
|
||||
if (path.includes(targetIdentifier)) {
|
||||
output.error({
|
||||
@ -303,7 +309,23 @@ function addTasksForProjectDependencyConfig(
|
||||
defaultDependencyConfigs,
|
||||
projectGraph,
|
||||
tasksMap,
|
||||
[...path, targetIdentifier]
|
||||
[...path, targetIdentifier],
|
||||
seenSet
|
||||
);
|
||||
} else {
|
||||
if (seenSet.has(dep.target)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
addTasksForProjectDependencyConfig(
|
||||
projectGraph.nodes[dep.target],
|
||||
{ target, configuration },
|
||||
dependencyConfig,
|
||||
defaultDependencyConfigs,
|
||||
projectGraph,
|
||||
tasksMap,
|
||||
path,
|
||||
seenSet
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -319,7 +341,8 @@ function addTasksForProjectDependencyConfig(
|
||||
defaultDependencyConfigs,
|
||||
projectGraph,
|
||||
tasksMap,
|
||||
[...path, targetIdentifier]
|
||||
[...path, targetIdentifier],
|
||||
seenSet
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -294,6 +294,109 @@ describe('TaskGraphCreator', () => {
|
||||
expect(taskGraph).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should create a task graph (builds depend on builds of dependencies even with intermediate projects)', () => {
|
||||
delete projectGraph.nodes.common1.data.targets.build;
|
||||
projectGraph.dependencies.common1.push({
|
||||
type: DependencyType.static,
|
||||
source: 'common1',
|
||||
target: 'common2',
|
||||
});
|
||||
|
||||
const tasks = createTasksForProjectToRun(
|
||||
[projectGraph.nodes.app1],
|
||||
{
|
||||
target: 'build',
|
||||
configuration: undefined,
|
||||
overrides: {},
|
||||
},
|
||||
projectGraph,
|
||||
null
|
||||
);
|
||||
|
||||
const taskGraph = new TaskGraphCreator(projectGraph, {}).createTaskGraph(
|
||||
tasks
|
||||
);
|
||||
|
||||
expect(taskGraph).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should create a task graph (builds depend on builds of dependencies with intermediate projects and circular dependencies between projects)', () => {
|
||||
delete projectGraph.nodes.common1.data.targets.build;
|
||||
projectGraph.dependencies.common1.push({
|
||||
type: DependencyType.static,
|
||||
source: 'common1',
|
||||
target: 'common2',
|
||||
});
|
||||
|
||||
projectGraph.dependencies.common2.push({
|
||||
type: DependencyType.static,
|
||||
source: 'common2',
|
||||
target: 'common1',
|
||||
});
|
||||
|
||||
const tasks = createTasksForProjectToRun(
|
||||
[projectGraph.nodes.app1],
|
||||
{
|
||||
target: 'build',
|
||||
configuration: undefined,
|
||||
overrides: {},
|
||||
},
|
||||
projectGraph,
|
||||
null
|
||||
);
|
||||
|
||||
const taskGraph = new TaskGraphCreator(projectGraph, {}).createTaskGraph(
|
||||
tasks
|
||||
);
|
||||
|
||||
expect(taskGraph).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should create a task graph (builds depend on builds of dependencies with intermediate projects and circular dependencies between projects) 2', () => {
|
||||
delete projectGraph.nodes.common1.data.targets.build;
|
||||
projectGraph.dependencies.common1.push({
|
||||
type: DependencyType.static,
|
||||
source: 'common1',
|
||||
target: 'common2',
|
||||
});
|
||||
|
||||
delete projectGraph.nodes.common2.data.targets.build;
|
||||
projectGraph.dependencies.common2.push({
|
||||
type: DependencyType.static,
|
||||
source: 'common2',
|
||||
target: 'common3',
|
||||
});
|
||||
|
||||
projectGraph.nodes.common3 = {
|
||||
name: 'common3',
|
||||
type: 'lib',
|
||||
data: {
|
||||
root: 'common3',
|
||||
targets: {
|
||||
build: {},
|
||||
},
|
||||
},
|
||||
};
|
||||
projectGraph.dependencies.common3 = [];
|
||||
|
||||
const tasks = createTasksForProjectToRun(
|
||||
[projectGraph.nodes.app1],
|
||||
{
|
||||
target: 'build',
|
||||
configuration: undefined,
|
||||
overrides: {},
|
||||
},
|
||||
projectGraph,
|
||||
null
|
||||
);
|
||||
|
||||
const taskGraph = new TaskGraphCreator(projectGraph, {}).createTaskGraph(
|
||||
tasks
|
||||
);
|
||||
|
||||
expect(taskGraph).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should create task graph (builds depend on build of dependencies and prebuild of self)', () => {
|
||||
projectGraph.nodes.app1.data.targets.prebuild = {};
|
||||
projectGraph.nodes.app2.data.targets.prebuild = {};
|
||||
|
||||
@ -22,8 +22,8 @@ export class TaskGraphCreator {
|
||||
dependencies: {},
|
||||
};
|
||||
for (const task of tasks) {
|
||||
graph.tasks[task.id] = task;
|
||||
graph.dependencies[task.id] = [];
|
||||
this.addTaskToGraph(task, graph);
|
||||
|
||||
const dependencyConfigs = getDependencyConfigs(
|
||||
task.target,
|
||||
this.defaultTargetDependencies,
|
||||
@ -34,12 +34,22 @@ export class TaskGraphCreator {
|
||||
continue;
|
||||
}
|
||||
|
||||
const projectDependencies = new Set(
|
||||
this.projectGraph.dependencies[task.target.project].map(
|
||||
(dependency) => dependency.target
|
||||
)
|
||||
this.addTaskDependencies(task, dependencyConfigs, tasks, graph);
|
||||
}
|
||||
|
||||
graph.roots = Object.keys(graph.dependencies).filter(
|
||||
(k) => graph.dependencies[k].length === 0
|
||||
);
|
||||
|
||||
return graph;
|
||||
}
|
||||
|
||||
private addTaskDependencies(
|
||||
task: Task,
|
||||
dependencyConfigs: TargetDependencyConfig[],
|
||||
tasks: Task[],
|
||||
graph: TaskGraph
|
||||
) {
|
||||
for (const dependencyConfig of dependencyConfigs) {
|
||||
if (dependencyConfig.projects === 'self') {
|
||||
for (const t of tasks) {
|
||||
@ -51,22 +61,66 @@ export class TaskGraphCreator {
|
||||
}
|
||||
}
|
||||
} else if (dependencyConfig.projects === 'dependencies') {
|
||||
for (const t of tasks) {
|
||||
if (
|
||||
projectDependencies.has(t.target.project) &&
|
||||
t.target.target === dependencyConfig.target
|
||||
) {
|
||||
graph.dependencies[task.id].push(t.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const seen = new Set<string>();
|
||||
|
||||
graph.roots = Object.keys(graph.dependencies).filter(
|
||||
(k) => graph.dependencies[k].length === 0
|
||||
this.addDependencies(
|
||||
task.target.project,
|
||||
dependencyConfig.target,
|
||||
tasks,
|
||||
graph,
|
||||
task.id,
|
||||
seen
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return graph;
|
||||
private addDependencies(
|
||||
project: string,
|
||||
target: string,
|
||||
tasks: Task[],
|
||||
graph: TaskGraph,
|
||||
taskId: string,
|
||||
seen: Set<string>
|
||||
) {
|
||||
seen.add(project);
|
||||
const projectDependencies = this.projectGraph.dependencies[project].map(
|
||||
(dependency) => dependency.target
|
||||
);
|
||||
for (const projectDependency of projectDependencies) {
|
||||
if (seen.has(projectDependency)) {
|
||||
continue;
|
||||
}
|
||||
const dependency = this.findTask(
|
||||
{ project: projectDependency, target },
|
||||
tasks
|
||||
);
|
||||
if (dependency) {
|
||||
graph.dependencies[taskId].push(dependency.id);
|
||||
} else {
|
||||
this.addDependencies(
|
||||
projectDependency,
|
||||
target,
|
||||
tasks,
|
||||
graph,
|
||||
taskId,
|
||||
seen
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private findTask(
|
||||
{ project, target }: { project: string; target: string },
|
||||
tasks: Task[]
|
||||
): Task {
|
||||
return tasks.find(
|
||||
(t) => t.target.project === project && t.target.target === target
|
||||
);
|
||||
}
|
||||
|
||||
private addTaskToGraph(task: Task, graph: TaskGraph) {
|
||||
graph.tasks[task.id] = task;
|
||||
graph.dependencies[task.id] = [];
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user