diff --git a/garden-service/src/commands/dev.ts b/garden-service/src/commands/dev.ts index d42ffdb871..0b3c34fb28 100644 --- a/garden-service/src/commands/dev.ts +++ b/garden-service/src/commands/dev.ts @@ -133,49 +133,14 @@ export class DevCommand extends Command { } } - const initialTasks = flatten( - await Bluebird.map(modules, async (module) => { - // Build the module (in case there are no tests, tasks or services here that need to be run) - const buildTasks = await BuildTask.factory({ - garden, - log, - module, - force: false, - }) - - // Run all tests in module - const testTasks = skipTests - ? [] - : await getTestTasks({ - garden, - graph, - log, - module, - force: false, - forceBuild: false, - }) - - // Deploy all enabled services in module - const services = await graph.getServices({ names: module.serviceNames, includeDisabled: true }) - const deployTasks = services - .filter((s) => !s.disabled) - .map( - (service) => - new DeployTask({ - garden, - log, - graph, - service, - force: false, - forceBuild: false, - fromWatch: false, - hotReloadServiceNames, - }) - ) - - return [...buildTasks, ...testTasks, ...deployTasks] - }) - ) + const initialTasks = await getDevCommandInitialTasks({ + garden, + log, + graph, + modules, + hotReloadServiceNames, + skipTests, + }) const results = await processModules({ garden, @@ -202,6 +167,67 @@ export class DevCommand extends Command { } } +export async function getDevCommandInitialTasks({ + garden, + log, + graph, + modules, + hotReloadServiceNames, + skipTests, +}: { + garden: Garden + log: LogEntry + graph: ConfigGraph + modules: Module[] + hotReloadServiceNames: string[] + skipTests: boolean +}) { + return flatten( + await Bluebird.map(modules, async (module) => { + // Build the module (in case there are no tests, tasks or services here that need to be run) + const buildTasks = await BuildTask.factory({ + garden, + log, + module, + force: false, + }) + + // Run all tests in module + const testTasks = skipTests + ? [] + : await getTestTasks({ + garden, + graph, + log, + module, + hotReloadServiceNames, + force: false, + forceBuild: false, + }) + + // Deploy all enabled services in module + const services = await graph.getServices({ names: module.serviceNames, includeDisabled: true }) + const deployTasks = services + .filter((s) => !s.disabled) + .map( + (service) => + new DeployTask({ + garden, + log, + graph, + service, + force: false, + forceBuild: false, + fromWatch: false, + hotReloadServiceNames, + }) + ) + + return [...buildTasks, ...testTasks, ...deployTasks] + }) + ) +} + export async function getDevCommandWatchTasks({ garden, log, diff --git a/garden-service/test/data/test-project-a/module-a/garden.yml b/garden-service/test/data/test-project-a/module-a/garden.yml index 33c94c547e..af88619a40 100644 --- a/garden-service/test/data/test-project-a/module-a/garden.yml +++ b/garden-service/test/data/test-project-a/module-a/garden.yml @@ -10,6 +10,8 @@ tests: command: [echo, OK] - name: integration command: [echo, OK] + dependencies: + - service-a tasks: - name: task-a command: [echo, OK] diff --git a/garden-service/test/unit/src/commands/dev.ts b/garden-service/test/unit/src/commands/dev.ts index b7e1d17f01..e62a5d0095 100644 --- a/garden-service/test/unit/src/commands/dev.ts +++ b/garden-service/test/unit/src/commands/dev.ts @@ -6,12 +6,21 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +import Bluebird from "bluebird" +import { flattenDeep } from "lodash" import pEvent from "p-event" import { expect } from "chai" -import { DevCommand, DevCommandArgs, DevCommandOpts, getDevCommandWatchTasks } from "../../../../src/commands/dev" +import { + DevCommand, + DevCommandArgs, + DevCommandOpts, + getDevCommandWatchTasks, + getDevCommandInitialTasks, +} from "../../../../src/commands/dev" import { makeTestGardenA, withDefaultGlobalOpts, TestGarden } from "../../../helpers" import { ParameterValues } from "../../../../src/commands/base" import { GlobalOptions } from "../../../../src/cli/cli" +import { BaseTask } from "../../../../src/tasks/base" describe("DevCommand", () => { const command = new DevCommand() @@ -106,6 +115,38 @@ describe("DevCommand", () => { return promise }) + it("should initially deploy services with hot reloading when requested", async () => { + const garden = await makeTestGardenA() + const log = garden.log + const graph = await garden.getConfigGraph(log) + const modules = await graph.getModules() + + const initialTasks = await getDevCommandInitialTasks({ + garden, + log, + graph, + modules, + // Note: service-a is a runtime dependency of module-a's integration test spec, so in this test case + // we're implicitly verifying that tests with runtime dependencies on services being deployed with + // hot reloading don't request non-hot-reload-enabled deploys for those same services. + hotReloadServiceNames: ["service-a"], + skipTests: false, + }) + + const withDeps = async (task: BaseTask) => { + const deps = await task.getDependencies() + return [task, await Bluebird.map(deps, async (dep) => await withDeps(dep))] + } + + const initialTasksWithDeps: BaseTask[] = flattenDeep(await Bluebird.map(initialTasks, withDeps)) + const deployTasksForServiceA = initialTasksWithDeps.filter((t) => t.getKey() === "deploy.service-a") + + expect(deployTasksForServiceA.length).to.be.greaterThan(0) + for (const deployTask of deployTasksForServiceA) { + expect(deployTask!["hotReloadServiceNames"]).to.eql(["service-a"]) + } + }) + it("should skip disabled services", async () => { const garden = await makeTestGardenA() diff --git a/garden-service/test/unit/src/commands/test.ts b/garden-service/test/unit/src/commands/test.ts index 1df2e7d99e..b2c604a791 100644 --- a/garden-service/test/unit/src/commands/test.ts +++ b/garden-service/test/unit/src/commands/test.ts @@ -208,6 +208,8 @@ describe("TestCommand", () => { expect(Object.keys(taskResultOutputs(result!)).sort()).to.eql([ "build.module-a", "build.module-b", + "deploy.service-a", + "get-service-status.service-a", "stage-build.module-a", "stage-build.module-b", "test.module-a.integration", diff --git a/garden-service/test/unit/src/config/base.ts b/garden-service/test/unit/src/config/base.ts index 187f76aef1..4a9e2cbead 100644 --- a/garden-service/test/unit/src/config/base.ts +++ b/garden-service/test/unit/src/config/base.ts @@ -152,6 +152,7 @@ describe("loadConfig", () => { { name: "integration", command: ["echo", "OK"], + dependencies: ["service-a"], }, ], },