diff --git a/garden-service/src/dependency-graph.ts b/garden-service/src/dependency-graph.ts index 3b92f03174..54f997597b 100644 --- a/garden-service/src/dependency-graph.ts +++ b/garden-service/src/dependency-graph.ts @@ -62,12 +62,8 @@ export class DependencyGraph { private testConfigModuleMap: { [key: string]: Module } static async factory(garden: Garden) { - const { modules, services, tasks } = await Bluebird.props({ - modules: garden.getModules(), - services: garden.getServices(), - tasks: garden.getTasks(), - }) - + const modules = await garden.getModules() + const { services, tasks } = await garden.getServicesAndTasks() return new DependencyGraph(garden, modules, services, tasks) } diff --git a/garden-service/src/garden.ts b/garden-service/src/garden.ts index 3a2a65b266..ef823fe4eb 100644 --- a/garden-service/src/garden.ts +++ b/garden-service/src/garden.ts @@ -814,23 +814,17 @@ export class Garden { this.modulesScanned = true - await this.detectCircularDependencies() - const moduleConfigContext = new ModuleConfigContext( this, this.log, this.environment, Object.values(this.moduleConfigs), ) this.moduleConfigs = await resolveTemplateStrings(this.moduleConfigs, moduleConfigContext) + + await this.detectCircularDependencies() }) } private async detectCircularDependencies() { - const { modules, services, tasks } = await Bluebird.props({ - modules: this.getModules(), - services: this.getServices(), - tasks: this.getTasks(), - }) - - return detectCircularDependencies(modules, services, tasks) + return detectCircularDependencies(Object.values(this.moduleConfigs)) } /* diff --git a/garden-service/src/util/detectCycles.ts b/garden-service/src/util/detectCycles.ts index 95016d4502..261c865de4 100644 --- a/garden-service/src/util/detectCycles.ts +++ b/garden-service/src/util/detectCycles.ts @@ -8,12 +8,11 @@ import dedent = require("dedent") import { get, isEqual, join, set, uniqWith } from "lodash" -import { Module, getModuleKey } from "../types/module" -import { - ConfigurationError, -} from "../exceptions" -import { Service } from "../types/service" -import { Task } from "../types/task" +import { getModuleKey } from "../types/module" +import { ConfigurationError } from "../exceptions" +import { ServiceConfig } from "../config/service" +import { TaskConfig } from "../config/task" +import { ModuleConfig } from "../config/module" export type Cycle = string[] @@ -24,16 +23,18 @@ export type Cycle = string[] Throws an error if cycles were found. */ -export async function detectCircularDependencies(modules: Module[], services: Service[], tasks: Task[]) { +export async function detectCircularDependencies(moduleConfigs: ModuleConfig[]) { // Sparse matrices const buildGraph = {} const runtimeGraph = {} + const services: ServiceConfig[] = [] + const tasks: TaskConfig[] = [] /* There's no need to account for test dependencies here, since any circularities there are accounted for via service dependencies. */ - for (const module of modules) { + for (const module of moduleConfigs) { // Build dependencies for (const buildDep of module.build.dependencies) { const depName = getModuleKey(buildDep.name, buildDep.plugin) @@ -42,12 +43,14 @@ export async function detectCircularDependencies(modules: Module[], services: Se // Runtime (service & task) dependencies for (const service of module.serviceConfigs || []) { + services.push(service) for (const depName of service.dependencies) { set(runtimeGraph, [service.name, depName], { distance: 1, next: depName }) } } for (const task of module.taskConfigs || []) { + tasks.push(task) for (const depName of task.dependencies) { set(runtimeGraph, [task.name, depName], { distance: 1, next: depName }) } @@ -56,7 +59,7 @@ export async function detectCircularDependencies(modules: Module[], services: Se const serviceNames = services.map(s => s.name) const taskNames = tasks.map(w => w.name) - const buildCycles = detectCycles(buildGraph, modules.map(m => m.name)) + const buildCycles = detectCycles(buildGraph, moduleConfigs.map(m => m.name)) const runtimeCycles = detectCycles(runtimeGraph, serviceNames.concat(taskNames)) if (buildCycles.length > 0 || runtimeCycles.length > 0) { diff --git a/garden-service/test/src/tasks/helpers.ts b/garden-service/test/src/tasks/helpers.ts index 236ef7e69e..aff2da525e 100644 --- a/garden-service/test/src/tasks/helpers.ts +++ b/garden-service/test/src/tasks/helpers.ts @@ -9,7 +9,9 @@ import { BaseTask } from "../../../src/tasks/base" import { LogEntry } from "../../../src/logger/log-entry" async function sortedBaseKeysWithDependencies(tasks: BaseTask[]): Promise { - return sortedBaseKeys(flatten([tasks].concat(await Bluebird.map(tasks, t => t.getDependencies())))) + const dependencies = await Bluebird.map(tasks, async (t) => t.getDependencies(), { concurrency: 1 }) + const tasksWithDependencies = flatten([tasks].concat(dependencies)) + return sortedBaseKeys(tasksWithDependencies) } function sortedBaseKeys(tasks: BaseTask[]): string[] { @@ -17,7 +19,6 @@ function sortedBaseKeys(tasks: BaseTask[]): string[] { } describe("TaskHelpers", () => { - let garden: Garden let log: LogEntry @@ -34,6 +35,8 @@ describe("TaskHelpers", () => { it("returns the correct set of tasks for the changed module", async () => { const module = await garden.getModule("good-morning") + await garden.getDependencyGraph() + const tasks = await getTasksForModule({ garden, log, module, hotReloadServiceNames: [], force: true, forceBuild: true, fromWatch: false, includeDependants: false,