diff --git a/garden-cli/src/process.ts b/garden-cli/src/process.ts index 097ce8f8ed..8019c31489 100644 --- a/garden-cli/src/process.ts +++ b/garden-cli/src/process.ts @@ -13,10 +13,8 @@ import { Service } from "./types/service" import { Task } from "./tasks/base" import { TaskResults } from "./task-graph" import { FSWatcher } from "./watch" -import { padEnd, values } from "lodash" import { registerCleanupFunction } from "./util/util" import { PluginContext } from "./plugin-context" -import { toGardenError } from "./exceptions" import { isModuleLinked } from "./util/ext-source-util" import { Garden } from "./garden" @@ -63,35 +61,17 @@ export async function processServices( export async function processModules( { ctx, garden, modules, watch, handler, changeHandler }: ProcessModulesParams, ): Promise { - const linkedModules: Module[] = [] - - // TODO: log errors as they happen, instead of after processing all tasks - const logErrors = (taskResults: TaskResults) => { - for (const result of values(taskResults).filter(r => !!r.error)) { - const divider = padEnd("", 80, "—") - const error = toGardenError(result.error!) - const msg = `\nFailed ${result.description}. Here is the output:\n${divider}\n${error.message}\n${divider}\n` - - ctx.log.error({ msg, error }) - } - } - for (const module of modules) { const tasks = await handler(module) if (isModuleLinked(module, ctx)) { - linkedModules.push(module) + ctx.log.info( + chalk.gray(`Reading module ${chalk.cyan(module.name)} from linked local path ${chalk.white(module.path)}`), + ) } await Bluebird.map(tasks, t => garden.addTask(t)) } - for (const module of linkedModules) { - ctx.log.info( - chalk.gray(`Reading module ${chalk.cyan(module.name)} from linked local path ${chalk.white(module.path)}`), - ) - } - const results = await garden.processTasks() - logErrors(results) if (!watch) { return { @@ -123,7 +103,7 @@ export async function processModules( }) } - logErrors(await garden.processTasks()) + await garden.processTasks() }) registerCleanupFunction("clearAutoReloadWatches", () => { diff --git a/garden-cli/src/task-graph.ts b/garden-cli/src/task-graph.ts index 7bc81a5ae1..1b20508abc 100644 --- a/garden-cli/src/task-graph.ts +++ b/garden-cli/src/task-graph.ts @@ -8,12 +8,13 @@ import * as Bluebird from "bluebird" import chalk from "chalk" -import { merge, pick } from "lodash" +import { merge, padEnd, pick } from "lodash" import { Task, TaskDefinitionError } from "./tasks/base" import { EntryStyle, LogSymbolType } from "./logger/types" import { LogEntry } from "./logger/logger" import { PluginContext } from "./plugin-context" +import { toGardenError } from "./exceptions" class TaskGraphError extends Error { } @@ -159,6 +160,7 @@ export class TaskGraph { result = await node.process(dependencyResults) } catch (error) { result = { type, description, error } + this.logTaskError(node, error) this.cancelDependants(node) } finally { results[baseKey] = result @@ -297,6 +299,12 @@ export class TaskGraph { } } + private logTaskError(node: TaskNode, err) { + const divider = padEnd("", 80, "—") + const error = toGardenError(err) + const msg = `\nFailed ${node.getDescription()}. Here is the output:\n${divider}\n${error.message}\n${divider}\n` + this.ctx.log.error({ msg, error }) + } } function getIndexKey(task: Task) { diff --git a/garden-cli/src/tasks/build.ts b/garden-cli/src/tasks/build.ts index 8ca513603e..9480c04318 100644 --- a/garden-cli/src/tasks/build.ts +++ b/garden-cli/src/tasks/build.ts @@ -62,12 +62,18 @@ export class BuildTask extends Task { entryStyle: EntryStyle.activity, }) - const result = await this.ctx.buildModule({ - moduleName, - logEntry, - }) - logEntry.setSuccess({ msg: chalk.green(`Done (took ${logEntry.getDuration(1)} sec)`), append: true }) + let result: BuildResult + try { + result = await this.ctx.buildModule({ + moduleName, + logEntry, + }) + } catch (err) { + logEntry.setError() + throw err + } + logEntry.setSuccess({ msg: chalk.green(`Done (took ${logEntry.getDuration(1)} sec)`), append: true }) return result } } diff --git a/garden-cli/src/tasks/deploy.ts b/garden-cli/src/tasks/deploy.ts index 8a6fd277b0..f8ed11a854 100644 --- a/garden-cli/src/tasks/deploy.ts +++ b/garden-cli/src/tasks/deploy.ts @@ -105,15 +105,20 @@ export class DeployTask extends Task { const dependencies = await this.ctx.getServices(this.service.config.dependencies) - const result = await this.ctx.deployService({ - serviceName: this.service.name, - runtimeContext: await prepareRuntimeContext(this.ctx, this.service.module, dependencies), - logEntry, - force: this.force, - }) + let result: ServiceStatus + try { + result = await this.ctx.deployService({ + serviceName: this.service.name, + runtimeContext: await prepareRuntimeContext(this.ctx, this.service.module, dependencies), + logEntry, + force: this.force, + }) + } catch (err) { + logEntry.setError() + throw err + } logEntry.setSuccess({ msg: chalk.green(`Ready`), append: true }) - return result } } diff --git a/garden-cli/src/tasks/push.ts b/garden-cli/src/tasks/push.ts index 6865b1e626..134afec8d6 100644 --- a/garden-cli/src/tasks/push.ts +++ b/garden-cli/src/tasks/push.ts @@ -70,7 +70,13 @@ export class PushTask extends Task { entryStyle: EntryStyle.activity, }) - const result = await this.ctx.pushModule({ moduleName: this.module.name, logEntry }) + let result: PushResult + try { + result = await this.ctx.pushModule({ moduleName: this.module.name, logEntry }) + } catch (err) { + logEntry.setError() + throw err + } if (result.pushed) { logEntry.setSuccess({ msg: chalk.green(result.message || `Ready`), append: true }) diff --git a/garden-cli/src/tasks/test.ts b/garden-cli/src/tasks/test.ts index 422460ea81..7f461e2ccf 100644 --- a/garden-cli/src/tasks/test.ts +++ b/garden-cli/src/tasks/test.ts @@ -113,14 +113,19 @@ export class TestTask extends Task { const dependencies = await getTestDependencies(this.ctx, this.testConfig) const runtimeContext = await prepareRuntimeContext(this.ctx, this.module, dependencies) - const result = await this.ctx.testModule({ - interactive: false, - moduleName: this.module.name, - runtimeContext, - silent: true, - testConfig: this.testConfig, - }) - + let result: TestResult + try { + result = await this.ctx.testModule({ + interactive: false, + moduleName: this.module.name, + runtimeContext, + silent: true, + testConfig: this.testConfig, + }) + } catch (err) { + entry.setError() + throw err + } if (result.success) { entry.setSuccess({ msg: chalk.green(`Success`), append: true }) } else {