diff --git a/garden-service/src/actions.ts b/garden-service/src/actions.ts index 11cee4abda..022ae66de9 100644 --- a/garden-service/src/actions.ts +++ b/garden-service/src/actions.ts @@ -123,7 +123,14 @@ export class ActionHelper implements TypeGuard { { pluginName, log }: ActionHelperParams, ): Promise { const handlers = this.garden.getActionHandlers("getEnvironmentStatus", pluginName) - return Bluebird.props(mapValues(handlers, h => h({ ...this.commonParams(h, log) }))) + const logEntry = log.debug({ + msg: "Getting status...", + status: "active", + section: `${this.garden.environment.name} environment`, + }) + const res = await Bluebird.props(mapValues(handlers, h => h({ ...this.commonParams(h, logEntry) }))) + logEntry.setSuccess("Ready") + return res } /** diff --git a/garden-service/src/cli/cli.ts b/garden-service/src/cli/cli.ts index 87245830b3..70c17afbef 100644 --- a/garden-service/src/cli/cli.ts +++ b/garden-service/src/cli/cli.ts @@ -32,6 +32,7 @@ import { GardenError, PluginError, toGardenError, + InternalError, } from "../exceptions" import { Garden, ContextOpts } from "../garden" @@ -67,17 +68,14 @@ const OUTPUT_RENDERERS = { }, } -const logLevelKeys = getEnumKeys(LogLevel) -// Allow string or numeric log levels -const logLevelChoices = [...logLevelKeys, ...range(logLevelKeys.length).map(String)] +const FILE_WRITER_CONFIGS = [ + { filename: "development.log" }, + { filename: ERROR_LOG_FILENAME, level: LogLevel.error }, + { filename: ERROR_LOG_FILENAME, level: LogLevel.error, path: ".", truncatePrevious: true }, +] -const getLogLevelFromArg = (level: string) => { - const lvl = parseInt(level, 10) - if (lvl) { - return lvl - } - return LogLevel[level] -} +const GLOBAL_OPTIONS_GROUP_NAME = "Global options" +const DEFAULT_CLI_LOGGER_TYPE = LoggerType.fancy // For initializing garden without a project config export const MOCK_CONFIG: GardenConfig = { @@ -99,6 +97,11 @@ export const MOCK_CONFIG: GardenConfig = { }, } +const getLogLevelNames = () => getEnumKeys(LogLevel) +const getNumericLogLevels = () => range(getLogLevelNames().length) +// Allow string or numeric log levels as CLI choices +const getLogLevelChoices = () => [...getLogLevelNames(), ...getNumericLogLevels().map(String)] + export const GLOBAL_OPTIONS = { root: new StringParameter({ alias: "r", @@ -113,7 +116,7 @@ export const GLOBAL_OPTIONS = { env: new EnvironmentOption(), loglevel: new ChoicesParameter({ alias: "l", - choices: logLevelChoices, + choices: getLogLevelChoices(), help: "Set logger level. Values can be either string or numeric and are prioritized from 0 to 5 " + "(highest to lowest) as follows: error: 0, warn: 1, info: 2, verbose: 3, debug: 4, silly: 5.", @@ -131,8 +134,39 @@ export const GLOBAL_OPTIONS = { defaultValue: envSupportsEmoji(), }), } -const GLOBAL_OPTIONS_GROUP_NAME = "Global options" -const DEFAULT_CLI_LOGGER_TYPE = LoggerType.fancy + +function parseLogLevel(level: string): LogLevel { + let lvl: LogLevel + const parsed = parseInt(level, 10) + if (parsed) { + lvl = parsed + } else { + lvl = LogLevel[level] + } + if (!getNumericLogLevels().includes(lvl)) { + throw new InternalError( + `Unexpected log level, expected one of ${getLogLevelChoices().join(", ")}, got ${level}`, + {}, + ) + } + return lvl +} + +function initLogger({ level, logEnabled, loggerType, emoji }: { + level: LogLevel, logEnabled: boolean, loggerType: LoggerType, emoji: boolean, +}) { + let writers: Writer[] = [] + + if (logEnabled) { + if (loggerType === LoggerType.fancy) { + writers.push(new FancyTerminalWriter()) + } else if (loggerType === LoggerType.basic) { + writers.push(new BasicTerminalWriter()) + } + } + + return Logger.initialize({ level, writers, useEmoji: emoji }) +} export interface ParseResults { argv: any @@ -146,8 +180,9 @@ interface SywacParseResults extends ParseResults { } export class GardenCli { - program: any - commands: { [key: string]: Command } = {} + private program: any + private commands: { [key: string]: Command } = {} + private fileWritersInitialized: boolean = false constructor() { const version = require("../../package.json").version @@ -169,13 +204,28 @@ export class GardenCli { .style(styleConfig) const commands = coreCommands - const globalOptions = Object.entries(GLOBAL_OPTIONS) commands.forEach(command => this.addCommand(command, this.program)) globalOptions.forEach(([key, opt]) => this.addGlobalOption(key, opt)) } + async initFileWriters(logger: Logger, projectRoot: string) { + if (this.fileWritersInitialized) { + return + } + for (const config of FILE_WRITER_CONFIGS) { + logger.writers.push( + await FileWriter.factory({ + level: logger.level, + root: projectRoot, + ...config, + }), + ) + } + this.fileWritersInitialized = true + } + addGlobalOption(key: string, option: Parameter): void { this.program.option(getOptionSynopsis(key, option), { ...prepareOptionConfig(option), @@ -211,35 +261,36 @@ export class GardenCli { const action = async (argv, cliContext) => { // Sywac returns positional args and options in a single object which we separate into args and opts - const parsedArgs = filterByKeys(argv, argKeys) const parsedOpts = filterByKeys(argv, optKeys.concat(globalKeys)) const root = resolve(process.cwd(), parsedOpts.root) const { emoji, env, loglevel, silent, output } = parsedOpts // Init logger - const level = getLogLevelFromArg(loglevel) - let writers: Writer[] = [] - - if (!silent && !output && loggerType !== LoggerType.quiet) { - if (loggerType === LoggerType.fancy) { - writers.push(new FancyTerminalWriter()) - } else if (loggerType === LoggerType.basic) { - writers.push(new BasicTerminalWriter()) - } + const logEnabled = !silent && !output && loggerType !== LoggerType.quiet + const level = parseLogLevel(loglevel) + const logger = initLogger({ level, logEnabled, loggerType, emoji }) + + // Currently we initialise an empty placeholder log entry and pass that to the + // framework as opposed to the logger itself. This is mainly for type conformity. + // A log entry has the same capabilities as the logger itself (they both extend a log node) + // but can additionally be updated after it's created, whereas the logger can create only new + // entries (i.e. print new lines). + const log = logger.placeholder() + + const contextOpts: ContextOpts = { env, log } + if (command.noProject) { + contextOpts.config = MOCK_CONFIG } - - const logger = Logger.initialize({ level, writers, useEmoji: emoji }) let garden: Garden let result do { - const contextOpts: ContextOpts = { env, logger } - if (command.noProject) { - contextOpts.config = MOCK_CONFIG - } garden = await Garden.factory(root, contextOpts) - // Indent -1 so that the children of this entry get printed with indent 0 - const log = garden.log.info({ indent: -1 }) + + // Register log file writers. We need to do this after the Garden class is initialised because + // the file writers depend on the project root. + await this.initFileWriters(logger, garden.projectRoot) + // TODO: enforce that commands always output DeepPrimitiveMap result = await command.action({ garden, diff --git a/garden-service/src/commands/create/module.ts b/garden-service/src/commands/create/module.ts index e8a0ccce19..c37c36cb2b 100644 --- a/garden-service/src/commands/create/module.ts +++ b/garden-service/src/commands/create/module.ts @@ -96,7 +96,8 @@ export class CreateModuleCommand extends Command { } else { // Prompt for type log.info("---------") - log.stop() + // Stop logger while prompting + log.stopAll() type = (await prompts.addConfigForModule(moduleName)).type log.info("---------") if (!type) { diff --git a/garden-service/src/commands/create/project.ts b/garden-service/src/commands/create/project.ts index 534c57eed4..9d9dd63bb9 100644 --- a/garden-service/src/commands/create/project.ts +++ b/garden-service/src/commands/create/project.ts @@ -117,7 +117,7 @@ export class CreateProjectCommand extends Command { log.info(`Initializing new Garden project ${projectName}`) log.info("---------") // Stop logger while prompting - log.stop() + log.stopAll() if (moduleParentDirs.length > 0) { // If module-dirs option provided we scan for modules in the parent dir(s) and add them one by one diff --git a/garden-service/src/commands/dev.ts b/garden-service/src/commands/dev.ts index 586761da6f..a87141d24b 100644 --- a/garden-service/src/commands/dev.ts +++ b/garden-service/src/commands/dev.ts @@ -65,7 +65,7 @@ export class DevCommand extends Command { async action({ garden, log, opts }: CommandParams): Promise { // print ANSI banner image const data = await readFile(ansiBannerPath) - console.log(data.toString()) + log.info(data.toString()) log.info(chalk.gray.italic(`\nGood ${getGreetingTime()}! Let's get your environment wired up...\n`)) diff --git a/garden-service/src/garden.ts b/garden-service/src/garden.ts index ee17d035dc..ecb23042ef 100644 --- a/garden-service/src/garden.ts +++ b/garden-service/src/garden.ts @@ -56,7 +56,6 @@ import { import { DEFAULT_NAMESPACE, MODULE_CONFIG_FILENAME, - ERROR_LOG_FILENAME, } from "./constants" import { ConfigurationError, @@ -75,7 +74,6 @@ import { } from "./task-graph" import { getLogger, - Logger, } from "./logger/logger" import { pluginActionNames, @@ -103,13 +101,12 @@ import { } from "./util/ext-source-util" import { BuildDependencyConfig, ModuleConfig } from "./config/module" import { ProjectConfigContext, ModuleConfigContext } from "./config/config-context" -import { FileWriter } from "./logger/writers/file-writer" -import { LogLevel } from "./logger/log-node" import { ActionHelper } from "./actions" import { createPluginContext } from "./plugin-context" import { ModuleAndRuntimeActions, Plugins, RegisterPluginParam } from "./types/plugin/plugin" import { SUPPORTED_PLATFORMS, SupportedPlatform } from "./constants" import { platform, arch } from "os" +import { LogEntry } from "./logger/log-entry" export interface ActionHandlerMap { [actionName: string]: PluginActions[T] @@ -136,20 +133,14 @@ export type ModuleActionMap = { export interface ContextOpts { config?: GardenConfig, env?: string, - logger?: Logger, + log?: LogEntry, plugins?: Plugins, } const scanLock = new AsyncLock() -const fileWriterConfigs = [ - { filename: "development.log" }, - { filename: ERROR_LOG_FILENAME, level: LogLevel.error }, - { filename: ERROR_LOG_FILENAME, level: LogLevel.error, path: ".", truncatePrevious: true }, -] - export class Garden { - public readonly log: Logger + public readonly log: LogEntry public readonly actionHandlers: PluginActionMap public readonly moduleActionHandlers: ModuleActionMap public dependencyGraph: DependencyGraph @@ -174,7 +165,7 @@ export class Garden { public readonly environment: Environment, public readonly projectSources: SourceConfig[] = [], public readonly buildDir: BuildDir, - logger?: Logger, + log?: LogEntry, ) { // make sure we're on a supported platform const currentPlatform = platform() @@ -189,7 +180,7 @@ export class Garden { } this.modulesScanned = false - this.log = logger || getLogger() + this.log = log || getLogger().placeholder() // TODO: Support other VCS options. this.vcs = new GitHandler(this.projectRoot) this.localConfigStore = new LocalConfigStore(this.projectRoot) @@ -203,12 +194,12 @@ export class Garden { this.actionHandlers = fromPairs(pluginActionNames.map(n => [n, {}])) this.moduleActionHandlers = fromPairs(moduleActionNames.map(n => [n, {}])) - this.taskGraph = new TaskGraph(this.log.info({ indent: -1 })) + this.taskGraph = new TaskGraph(this.log) this.actions = new ActionHelper(this) this.hotReloadScheduler = new HotReloadScheduler() } - static async factory(currentDirectory: string, { env, config, logger, plugins = {} }: ContextOpts = {}) { + static async factory(currentDirectory: string, { env, config, log, plugins = {} }: ContextOpts = {}) { let parsedConfig: GardenConfig if (config) { @@ -293,26 +284,13 @@ export class Garden { const buildDir = await BuildDir.factory(projectRoot) - // Register log writers - if (logger) { - for (const writerConfig of fileWriterConfigs) { - logger.writers.push( - await FileWriter.factory({ - level: logger.level, - root: projectRoot, - ...writerConfig, - }), - ) - } - } - const garden = new Garden( projectRoot, projectName, environment, projectSources, buildDir, - logger, + log, ) // Register plugins @@ -822,7 +800,7 @@ export class Garden { await this.detectCircularDependencies() const moduleConfigContext = new ModuleConfigContext( - this, this.log.info({ indent: -1 }), this.environment, Object.values(this.moduleConfigs), + this, this.log, this.environment, Object.values(this.moduleConfigs), ) this.moduleConfigs = await resolveTemplateStrings(this.moduleConfigs, moduleConfigContext) }) diff --git a/garden-service/src/logger/log-entry.ts b/garden-service/src/logger/log-entry.ts index 38540d785c..834c386ae5 100644 --- a/garden-service/src/logger/log-entry.ts +++ b/garden-service/src/logger/log-entry.ts @@ -85,7 +85,7 @@ export class LogEntry extends LogNode { this.opts = { ...this.opts, ...nextOpts, msg } } - // Update node and child nodes + // Update node and child nodes private deepSetState(opts: UpdateOpts): void { const wasActive = this.opts.status === "active" @@ -101,17 +101,20 @@ export class LogEntry extends LogNode { } } - createNode(level: LogLevel, parent: LogNode, param?: CreateParam) { - // Empty entries inherit their parent's indentation level - let { indent } = this.opts - if (param) { - indent = (indent || 0) + 1 - } + protected createNode(level: LogLevel, param: CreateParam) { + // A child entry must not have a higher level than its parent + const childLevel = this.level > level ? this.level : level const opts = { - indent, + indent: (this.opts.indent || 0) + 1, ...resolveParam(param), } - return new LogEntry({ level, opts, parent }) + return new LogEntry({ level: childLevel, opts, parent: this }) + } + + placeholder(level: LogLevel = LogLevel.info): LogEntry { + // Ensure placeholder child entries align with parent context + const indent = Math.max((this.opts.indent || 0) - 1, - 1) + return this.appendNode(level, { indent }) } // Preserves status @@ -149,6 +152,10 @@ export class LogEntry extends LogNode { return !!this.opts.fromStdStream } + stopAll() { + return this.root.stop() + } + stop() { // Stop gracefully if still in active state if (this.opts.status === "active") { diff --git a/garden-service/src/logger/log-node.ts b/garden-service/src/logger/log-node.ts index 21a06db91b..e7e5c577e6 100644 --- a/garden-service/src/logger/log-node.ts +++ b/garden-service/src/logger/log-node.ts @@ -43,36 +43,42 @@ export abstract class LogNode { this.children = [] } - abstract createNode(level: LogLevel, parent: LogNode, param?: U): T + protected abstract createNode(level: LogLevel, param: U): T - protected appendNode(level: LogLevel, param?: U): T { - const node = this.createNode(level, this, param) + /** + * A placeholder entry is an empty entry whose children should be aligned with the parent context. + * Useful for setting a placeholder in the middle of the log that can later be populated. + */ + abstract placeholder(level: LogLevel): T + + protected appendNode(level: LogLevel, param: U): T { + const node = this.createNode(level, param) this.children.push(node) this.root.onGraphChange(node) return node } - silly(param?: U): T { + silly(param: U): T { return this.appendNode(LogLevel.silly, param) } - debug(param?: U): T { + debug(param: U): T { return this.appendNode(LogLevel.debug, param) } - verbose(param?: U): T { + verbose(param: U): T { return this.appendNode(LogLevel.verbose, param) } - info(param?: U): T { + info(param: U): T { return this.appendNode(LogLevel.info, param) } - warn(param?: U): T { + warn(param: U): T { return this.appendNode(LogLevel.warn, param) } - error(param?: U): T { + error(param: U): T { return this.appendNode(LogLevel.error, param) } diff --git a/garden-service/src/logger/logger.ts b/garden-service/src/logger/logger.ts index 34c9c2701b..a338ef64fe 100644 --- a/garden-service/src/logger/logger.ts +++ b/garden-service/src/logger/logger.ts @@ -8,7 +8,7 @@ import chalk from "chalk" -import { RootLogNode, LogNode } from "./log-node" +import { RootLogNode } from "./log-node" import { LogEntry, CreateOpts, resolveParam } from "./log-entry" import { getChildEntries } from "./util" import { Writer } from "./writers/base" @@ -60,7 +60,7 @@ export class Logger extends RootLogNode { return Logger.instance } - static initialize(config: LoggerConfig) { + static initialize(config: LoggerConfig): Logger { if (Logger.instance) { throw new InternalError("Logger already initialized", {}) } @@ -94,10 +94,15 @@ export class Logger extends RootLogNode { this.useEmoji = config.useEmoji === false ? false : true } - createNode(level: LogLevel, _parent: LogNode, opts: CreateOpts) { + protected createNode(level: LogLevel, opts: CreateOpts): LogEntry { return new LogEntry({ level, parent: this, opts: resolveParam(opts) }) } + placeholder(level: LogLevel = LogLevel.info): LogEntry { + // Ensure placeholder child entries align with parent context + return this.appendNode(level, { indent: - 1 }) + } + onGraphChange(entry: LogEntry) { this.writers.forEach(writer => writer.onGraphChange(entry, this)) } diff --git a/garden-service/src/plugins/kubernetes/init.ts b/garden-service/src/plugins/kubernetes/init.ts index 0d923cd365..686828e730 100644 --- a/garden-service/src/plugins/kubernetes/init.ts +++ b/garden-service/src/plugins/kubernetes/init.ts @@ -147,13 +147,11 @@ export async function cleanupEnvironment({ ctx, log }: CleanupEnvironmentParams) // TODO: any cast is required until https://github.com/kubernetes-client/javascript/issues/52 is fixed await api.core.deleteNamespace(namespace, {}) } catch (err) { - entry && entry.setError(err.message) + entry.setError(err.message) const availableNamespaces = await getAllGardenNamespaces(api) throw new NotFoundError(err, { namespace, availableNamespaces }) } - entry && entry.setSuccess() - await logout({ ctx, log }) // Wait until namespace has been deleted @@ -163,6 +161,7 @@ export async function cleanupEnvironment({ ctx, log }: CleanupEnvironmentParams) const nsNames = await getAllGardenNamespaces(api) if (!nsNames.includes(namespace)) { + entry.setSuccess() break } diff --git a/garden-service/src/process.ts b/garden-service/src/process.ts index 12045f721e..209f6525fe 100644 --- a/garden-service/src/process.ts +++ b/garden-service/src/process.ts @@ -8,6 +8,8 @@ import Bluebird = require("bluebird") import chalk from "chalk" +import { padEnd } from "lodash" + import { Module } from "./types/module" import { Service } from "./types/service" import { BaseTask } from "./tasks/base" @@ -61,13 +63,21 @@ export async function processServices( export async function processModules( { garden, log, modules, watch, handler, changeHandler }: ProcessModulesParams, ): Promise { + // Let the user know if any modules are linked to a local path + const linkedModulesMsg = modules + .filter(m => isModuleLinked(m, garden)) + .map(m => `${chalk.cyan(m.name)} linked to path ${chalk.white(m.path)}`) + .map(msg => " " + msg) // indent list + + if (linkedModulesMsg.length > 0) { + const divider = padEnd("", 80, "—") + log.info(divider) + log.info(chalk.gray(`Following modules are linked to a local path:\n${linkedModulesMsg.join("\n")}`)) + log.info(divider) + } + for (const module of modules) { const tasks = await handler(module) - if (isModuleLinked(module, garden)) { - 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)) } diff --git a/garden-service/test/helpers.ts b/garden-service/test/helpers.ts index 035f170678..b28748bc42 100644 --- a/garden-service/test/helpers.ts +++ b/garden-service/test/helpers.ts @@ -165,13 +165,13 @@ export const testPlugin: PluginFactory = (): GardenPlugin => { }, async runTask( - { ctx, task, interactive, runtimeContext, logEntry, buildDependencies }: RunTaskParams, + { ctx, task, interactive, runtimeContext, log, buildDependencies }: RunTaskParams, ) { const result = await runModule({ ctx, buildDependencies, interactive, - logEntry, + log, runtimeContext, module: task.module, command: task.spec.command || [], diff --git a/garden-service/test/src/actions.ts b/garden-service/test/src/actions.ts index 172bbb3cdd..9833829e8e 100644 --- a/garden-service/test/src/actions.ts +++ b/garden-service/test/src/actions.ts @@ -52,7 +52,7 @@ describe("ActionHelper", () => { before(async () => { const plugins = { "test-plugin": testPlugin, "test-plugin-b": testPluginB } garden = await makeTestGardenA(plugins) - log = garden.log.info() + log = garden.log actions = garden.actions module = await garden.getModule("module-a") service = await garden.getService("service-a") @@ -323,6 +323,7 @@ describe("ActionHelper", () => { describe("runTask", () => { it("should correctly call the corresponding plugin handler", async () => { const result = await actions.runTask({ + log, task, interactive: true, runtimeContext: { diff --git a/garden-service/test/src/build-dir.ts b/garden-service/test/src/build-dir.ts index b69d9a1c52..0881a21ed3 100644 --- a/garden-service/test/src/build-dir.ts +++ b/garden-service/test/src/build-dir.ts @@ -63,7 +63,7 @@ describe("BuildDir", () => { it("should sync dependency products to their specified destinations", async () => { const garden = await makeGarden() - const log = garden.log.info() + const log = garden.log try { await garden.clearBuilds() diff --git a/garden-service/test/src/commands/build.ts b/garden-service/test/src/commands/build.ts index 7fe9bd7fbb..c900849d4e 100644 --- a/garden-service/test/src/commands/build.ts +++ b/garden-service/test/src/commands/build.ts @@ -6,7 +6,7 @@ import { taskResultOutputs } from "../../helpers" describe("commands.build", () => { it("should build all modules in a project", async () => { const garden = await makeTestGardenA() - const log = garden.log.info() + const log = garden.log const command = new BuildCommand() const { result } = await command.action({ @@ -25,7 +25,7 @@ describe("commands.build", () => { it("should optionally build single module and its dependencies", async () => { const garden = await makeTestGardenA() - const log = garden.log.info() + const log = garden.log const command = new BuildCommand() const { result } = await command.action({ diff --git a/garden-service/test/src/commands/call.ts b/garden-service/test/src/commands/call.ts index b53f809e45..12de685e98 100644 --- a/garden-service/test/src/commands/call.ts +++ b/garden-service/test/src/commands/call.ts @@ -59,7 +59,7 @@ describe("commands.call", () => { it("should find the ingress for a service and call it with the specified path", async () => { const garden = await Garden.factory(projectRootB, { plugins }) - const log = garden.log.info() + const log = garden.log const command = new CallCommand() nock("http://service-a.test-project-b.local.app.garden:32000") @@ -83,7 +83,7 @@ describe("commands.call", () => { it("should default to the path '/' if that is exposed if no path is requested", async () => { const garden = await Garden.factory(projectRootB, { plugins }) - const log = garden.log.info() + const log = garden.log const command = new CallCommand() nock("http://service-a.test-project-b.local.app.garden:32000") @@ -106,7 +106,7 @@ describe("commands.call", () => { it("should otherwise use the first defined ingress if no path is requested", async () => { const garden = await Garden.factory(projectRootB, { plugins }) - const log = garden.log.info() + const log = garden.log const command = new CallCommand() nock("http://service-b.test-project-b.local.app.garden:32000") @@ -129,7 +129,7 @@ describe("commands.call", () => { it("should error if service isn't running", async () => { const garden = await Garden.factory(projectRootB, { plugins }) - const log = garden.log.info() + const log = garden.log const command = new CallCommand() try { @@ -149,7 +149,7 @@ describe("commands.call", () => { it("should error if service has no ingresses", async () => { const garden = await Garden.factory(projectRootB, { plugins }) - const log = garden.log.info() + const log = garden.log const command = new CallCommand() try { @@ -169,7 +169,7 @@ describe("commands.call", () => { it("should error if service has no matching ingresses", async () => { const garden = await Garden.factory(projectRootB, { plugins }) - const log = garden.log.info() + const log = garden.log const command = new CallCommand() try { diff --git a/garden-service/test/src/commands/create/module.ts b/garden-service/test/src/commands/create/module.ts index 4b204cc6bd..125af13351 100644 --- a/garden-service/test/src/commands/create/module.ts +++ b/garden-service/test/src/commands/create/module.ts @@ -35,7 +35,7 @@ describe("CreateModuleCommand", () => { it("should add a module config to the current directory", async () => { replaceAddConfigForModule() const garden = await makeTestGarden(projectRoot) - const log = garden.log.info() + const log = garden.log const { result } = await cmd.action({ garden, @@ -54,7 +54,7 @@ describe("CreateModuleCommand", () => { it("should add a module config to new-module directory", async () => { replaceAddConfigForModule() const garden = await makeTestGarden(projectRoot) - const log = garden.log.info() + const log = garden.log const { result } = await cmd.action({ garden, @@ -72,7 +72,7 @@ describe("CreateModuleCommand", () => { it("should optionally name the module my-module", async () => { replaceAddConfigForModule() const garden = await makeTestGarden(projectRoot) - const log = garden.log.info() + const log = garden.log const { result } = await cmd.action({ garden, @@ -89,7 +89,7 @@ describe("CreateModuleCommand", () => { // garden create module --type=google-cloud-function it("should optionally create a module of a specific type (without prompting)", async () => { const garden = await makeTestGarden(projectRoot) - const log = garden.log.info() + const log = garden.log const { result } = await cmd.action({ garden, @@ -107,7 +107,7 @@ describe("CreateModuleCommand", () => { it("should throw if module name is invalid when inherited from current directory", async () => { replaceAddConfigForModule() const garden = await makeTestGarden(projectRoot) - const log = garden.log.info() + const log = garden.log await expectError( async () => await cmd.action({ @@ -123,7 +123,7 @@ describe("CreateModuleCommand", () => { it("should throw if module name is invalid when explicitly specified", async () => { replaceAddConfigForModule() const garden = await makeTestGarden(projectRoot) - const log = garden.log.info() + const log = garden.log await expectError( async () => await cmd.action({ @@ -139,7 +139,7 @@ describe("CreateModuleCommand", () => { it("should throw if invalid type provided", async () => { replaceAddConfigForModule() const garden = await makeTestGarden(projectRoot) - const log = garden.log.info() + const log = garden.log await expectError( async () => await cmd.action({ diff --git a/garden-service/test/src/commands/create/project.ts b/garden-service/test/src/commands/create/project.ts index 43db85936c..c7825fb1f9 100644 --- a/garden-service/test/src/commands/create/project.ts +++ b/garden-service/test/src/commands/create/project.ts @@ -48,7 +48,7 @@ describe("CreateProjectCommand", () => { beforeEach(async () => { garden = await makeTestGarden(projectRoot) - log = garden.log.info() + log = garden.log }) afterEach(async () => { diff --git a/garden-service/test/src/commands/delete.ts b/garden-service/test/src/commands/delete.ts index 5f375b9192..5908c6d022 100644 --- a/garden-service/test/src/commands/delete.ts +++ b/garden-service/test/src/commands/delete.ts @@ -17,7 +17,7 @@ describe("DeleteSecretCommand", () => { it("should delete a secret", async () => { const garden = await makeTestGardenA() - const log = garden.log.info() + const log = garden.log const command = new DeleteSecretCommand() const key = "mykey" @@ -32,7 +32,7 @@ describe("DeleteSecretCommand", () => { it("should throw on missing key", async () => { const garden = await makeTestGardenA() - const log = garden.log.info() + const log = garden.log const command = new DeleteSecretCommand() await expectError( @@ -71,7 +71,7 @@ describe("DeleteEnvironmentCommand", () => { it("should destroy environment", async () => { const garden = await Garden.factory(projectRootB, { plugins }) - const log = garden.log.info() + const log = garden.log const { result } = await command.action({ garden, log, args: {}, opts: {} }) @@ -112,7 +112,7 @@ describe("DeleteServiceCommand", () => { it("should return the status of the deleted service", async () => { const garden = await Garden.factory(projectRootB, { plugins }) - const log = garden.log.info() + const log = garden.log const { result } = await command.action({ garden, log, args: { service: ["service-a"] }, opts: {} }) expect(result).to.eql({ @@ -122,7 +122,7 @@ describe("DeleteServiceCommand", () => { it("should return the status of the deleted services", async () => { const garden = await Garden.factory(projectRootB, { plugins }) - const log = garden.log.info() + const log = garden.log const { result } = await command.action({ garden, diff --git a/garden-service/test/src/commands/deploy.ts b/garden-service/test/src/commands/deploy.ts index 52fd0dc7c8..6b160a3a41 100644 --- a/garden-service/test/src/commands/deploy.ts +++ b/garden-service/test/src/commands/deploy.ts @@ -93,7 +93,7 @@ describe("DeployCommand", () => { it("should build and deploy all modules in a project", async () => { const garden = await Garden.factory(projectRootB, { plugins }) - const log = garden.log.info() + const log = garden.log const command = new DeployCommand() const { result } = await command.action({ @@ -128,7 +128,7 @@ describe("DeployCommand", () => { it("should optionally build and deploy single service and its dependencies", async () => { const garden = await Garden.factory(projectRootB, { plugins }) - const log = garden.log.info() + const log = garden.log const command = new DeployCommand() const { result } = await command.action({ diff --git a/garden-service/test/src/commands/get.ts b/garden-service/test/src/commands/get.ts index 652c8d2059..10b66e6661 100644 --- a/garden-service/test/src/commands/get.ts +++ b/garden-service/test/src/commands/get.ts @@ -8,7 +8,7 @@ describe("GetSecretCommand", () => { it("should get a config variable", async () => { const garden = await makeTestGardenA() - const log = garden.log.info() + const log = garden.log const command = new GetSecretCommand() await garden.actions.setSecret({ @@ -30,7 +30,7 @@ describe("GetSecretCommand", () => { it("should throw on missing key", async () => { const garden = await makeTestGardenA() - const log = garden.log.info() + const log = garden.log const command = new GetSecretCommand() await expectError( diff --git a/garden-service/test/src/commands/link.ts b/garden-service/test/src/commands/link.ts index cf8af77580..fe0f5cbe1b 100644 --- a/garden-service/test/src/commands/link.ts +++ b/garden-service/test/src/commands/link.ts @@ -23,7 +23,7 @@ describe("LinkCommand", () => { beforeEach(async () => { garden = await makeTestGarden(projectRoot) - log = garden.log.info() + log = garden.log stubExtSources(garden) }) @@ -91,7 +91,7 @@ describe("LinkCommand", () => { beforeEach(async () => { garden = await makeTestGarden(projectRoot) - log = garden.log.info() + log = garden.log stubExtSources(garden) }) diff --git a/garden-service/test/src/commands/publish.ts b/garden-service/test/src/commands/publish.ts index c5186e29fc..d50617e86e 100644 --- a/garden-service/test/src/commands/publish.ts +++ b/garden-service/test/src/commands/publish.ts @@ -51,7 +51,7 @@ describe("PublishCommand", () => { it("should build and publish modules in a project", async () => { const garden = await getTestGarden() - const log = garden.log.info() + const log = garden.log const command = new PublishCommand() const { result } = await command.action({ @@ -77,7 +77,7 @@ describe("PublishCommand", () => { it("should optionally force new build", async () => { const garden = await getTestGarden() - const log = garden.log.info() + const log = garden.log const command = new PublishCommand() const { result } = await command.action({ @@ -103,7 +103,7 @@ describe("PublishCommand", () => { it("should optionally build selected module", async () => { const garden = await getTestGarden() - const log = garden.log.info() + const log = garden.log const command = new PublishCommand() const { result } = await command.action({ @@ -126,7 +126,7 @@ describe("PublishCommand", () => { it("should respect allowPublish flag", async () => { const garden = await getTestGarden() - const log = garden.log.info() + const log = garden.log const command = new PublishCommand() const { result } = await command.action({ @@ -148,7 +148,7 @@ describe("PublishCommand", () => { it("should fail gracefully if module does not have a provider for publish", async () => { const garden = await makeTestGardenA() - const log = garden.log.info() + const log = garden.log await garden.clearBuilds() const command = new PublishCommand() @@ -190,7 +190,7 @@ describe("PublishCommand", () => { } }) garden = await getTestGarden() - log = garden.log.info() + log = garden.log }) it("should throw if module is dirty", async () => { diff --git a/garden-service/test/src/commands/run/module.ts b/garden-service/test/src/commands/run/module.ts index 969127d0cc..c65399dcef 100644 --- a/garden-service/test/src/commands/run/module.ts +++ b/garden-service/test/src/commands/run/module.ts @@ -18,7 +18,7 @@ describe("RunModuleCommand", () => { beforeEach(async () => { td.replace(Garden.prototype, "resolveVersion", async () => testModuleVersion) garden = await makeTestGardenA() - log = garden.log.info() + log = garden.log }) it("should run a module without a command param", async () => { diff --git a/garden-service/test/src/commands/run/service.ts b/garden-service/test/src/commands/run/service.ts index 5bd876ada6..134ac6dc1d 100644 --- a/garden-service/test/src/commands/run/service.ts +++ b/garden-service/test/src/commands/run/service.ts @@ -19,7 +19,7 @@ describe("RunServiceCommand", () => { beforeEach(async () => { td.replace(Garden.prototype, "resolveVersion", async () => testModuleVersion) garden = await makeTestGardenA() - log = garden.log.info() + log = garden.log }) it("should run a service", async () => { diff --git a/garden-service/test/src/commands/run/task.ts b/garden-service/test/src/commands/run/task.ts index 5346061fca..c482afad56 100644 --- a/garden-service/test/src/commands/run/task.ts +++ b/garden-service/test/src/commands/run/task.ts @@ -7,9 +7,11 @@ describe("RunTaskCommand", () => { it("should run a task", async () => { const garden = await makeTestGardenA() + const log = garden.log const cmd = new RunTaskCommand() const { result } = await cmd.action({ + log, garden, args: { task: "task-a" }, opts: { "force-build": false }, diff --git a/garden-service/test/src/commands/scan.ts b/garden-service/test/src/commands/scan.ts index abe4fc030f..620338ce34 100644 --- a/garden-service/test/src/commands/scan.ts +++ b/garden-service/test/src/commands/scan.ts @@ -6,7 +6,7 @@ describe("ScanCommand", () => { for (const [name, path] of Object.entries(getExampleProjects())) { it(`should successfully scan the ${name} project`, async () => { const garden = await Garden.factory(path) - const log = garden.log.info() + const log = garden.log const command = new ScanCommand() await command.action({ diff --git a/garden-service/test/src/commands/set.ts b/garden-service/test/src/commands/set.ts index 11961902af..3ee6dbe4c2 100644 --- a/garden-service/test/src/commands/set.ts +++ b/garden-service/test/src/commands/set.ts @@ -8,7 +8,7 @@ describe("SetSecretCommand", () => { it("should set a config variable", async () => { const garden = await makeTestGardenA() - const log = garden.log.info() + const log = garden.log const command = new SetSecretCommand() await command.action({ diff --git a/garden-service/test/src/commands/test.ts b/garden-service/test/src/commands/test.ts index cba05e072d..3eb5b19806 100644 --- a/garden-service/test/src/commands/test.ts +++ b/garden-service/test/src/commands/test.ts @@ -6,7 +6,7 @@ import { makeTestGardenA, taskResultOutputs } from "../../helpers" describe("commands.test", () => { it("should run all tests in a simple project", async () => { const garden = await makeTestGardenA() - const log = garden.log.info() + const log = garden.log const command = new TestCommand() const { result } = await command.action({ @@ -43,7 +43,7 @@ describe("commands.test", () => { it("should optionally test single module", async () => { const garden = await makeTestGardenA() - const log = garden.log.info() + const log = garden.log const command = new TestCommand() const { result } = await command.action({ diff --git a/garden-service/test/src/commands/unlink.ts b/garden-service/test/src/commands/unlink.ts index 9345a6c36a..7c44bc2169 100644 --- a/garden-service/test/src/commands/unlink.ts +++ b/garden-service/test/src/commands/unlink.ts @@ -25,7 +25,7 @@ describe("UnlinkCommand", () => { beforeEach(async () => { garden = await makeTestGarden(projectRoot) - log = garden.log.info() + log = garden.log stubExtSources(garden) await linkCmd.action({ @@ -93,7 +93,7 @@ describe("UnlinkCommand", () => { beforeEach(async () => { garden = await makeTestGarden(projectRoot) - log = garden.log.info() + log = garden.log stubExtSources(garden) diff --git a/garden-service/test/src/commands/update-remote.ts b/garden-service/test/src/commands/update-remote.ts index 674a44c25c..0d841f50dd 100644 --- a/garden-service/test/src/commands/update-remote.ts +++ b/garden-service/test/src/commands/update-remote.ts @@ -23,7 +23,7 @@ describe("UpdateRemoteCommand", () => { beforeEach(async () => { garden = await makeTestGarden(projectRoot) - log = garden.log.info() + log = garden.log stubGitCli() }) @@ -83,7 +83,7 @@ describe("UpdateRemoteCommand", () => { beforeEach(async () => { garden = await makeTestGarden(projectRoot) - log = garden.log.info() + log = garden.log stubExtSources(garden) }) diff --git a/garden-service/test/src/commands/validate.ts b/garden-service/test/src/commands/validate.ts index 40d7c33ddc..3360694e82 100644 --- a/garden-service/test/src/commands/validate.ts +++ b/garden-service/test/src/commands/validate.ts @@ -8,7 +8,7 @@ describe("commands.validate", () => { for (const [name, path] of Object.entries(getExampleProjects())) { it(`should successfully validate the ${name} project`, async () => { const garden = await Garden.factory(path) - const log = garden.log.info() + const log = garden.log const command = new ValidateCommand() await command.action({ @@ -29,7 +29,7 @@ describe("commands.validate", () => { it("should fail validating the bad-module project", async () => { const root = join(__dirname, "data", "validate", "bad-module") const garden = await Garden.factory(root) - const log = garden.log.info() + const log = garden.log const command = new ValidateCommand() await expectError(async () => await command.action({ diff --git a/garden-service/test/src/config/config-context.ts b/garden-service/test/src/config/config-context.ts index 9f68d59a7a..8e4cd5c56e 100644 --- a/garden-service/test/src/config/config-context.ts +++ b/garden-service/test/src/config/config-context.ts @@ -233,7 +233,7 @@ describe("ModuleConfigContext", () => { await garden.scanModules() c = new ModuleConfigContext( garden, - garden.log.info(), + garden.log, garden.environment, Object.values((garden).moduleConfigs), ) diff --git a/garden-service/test/src/logger.ts b/garden-service/test/src/logger.ts index 12edc538bd..b31e36a8a9 100644 --- a/garden-service/test/src/logger.ts +++ b/garden-service/test/src/logger.ts @@ -100,15 +100,15 @@ describe("RootLogNode", () => { describe("Writers", () => { describe("BasicTerminalWriter", () => { describe("render", () => { - it("should return a string if level is geq than entry level and entry contains a message", () => { + it("should return a formatted message if level is geq than entry level", () => { const writer = new BasicTerminalWriter() - const entry = logger.info("") + const entry = logger.info("hello logger") const out = writer.render(entry, logger) - expect(out).to.eql("\n") + expect(out).to.eql(formatForTerminal(entry)) }) - it("should override root level if level is set", () => { - const writer = new BasicTerminalWriter({ level: LogLevel.verbose }) - const entry = logger.verbose("") + it("should return a new line if message is an empty string", () => { + const writer = new BasicTerminalWriter() + const entry = logger.info("") const out = writer.render(entry, logger) expect(out).to.eql("\n") }) @@ -118,9 +118,15 @@ describe("Writers", () => { const out = writer.render(entry, logger) expect(out).to.eql(null) }) + it("should override root level if level is set", () => { + const writer = new BasicTerminalWriter({ level: LogLevel.verbose }) + const entry = logger.verbose("") + const out = writer.render(entry, logger) + expect(out).to.eql("\n") + }) it("should return an empty string if entry is empty", () => { const writer = new BasicTerminalWriter() - const entry = logger.info() + const entry = logger.placeholder() const out = writer.render(entry, logger) expect(out).to.eql("") }) @@ -157,7 +163,7 @@ describe("Writers", () => { expect(terminalEntries).to.eql([]) }) it("should skip entry if entry is empty", () => { - logger.info() + logger.placeholder() const terminalEntries = writer.toTerminalEntries(logger) expect(terminalEntries).to.eql([]) }) @@ -184,24 +190,53 @@ describe("Writers", () => { }) describe("LogEntry", () => { - const entry = logger.info() - describe("createNode", () => { - it("should set the correct indentation level", () => { - const nested = entry.info("nested") - const deepNested = nested.info("deep nested") - const deepDeepNested = deepNested.info("deep deep inside") - const deepDeepEmpty = deepDeepNested.info() - const indentations = [ - nested.opts.indent, - deepNested.opts.indent, - deepDeepNested.opts.indent, - deepDeepEmpty.opts.indent, - ] - expect(indentations).to.eql([1, 2, 3, 3]) - }) + it("should dedent placeholder log entries", () => { + const ph1 = logger.placeholder() + const ph2 = ph1.placeholder() + const nonEmpty = ph1.info("foo") + const nested = nonEmpty.info("foo") + const nestedPh = nested.placeholder() + const indents = [ + ph1.opts.indent, + ph2.opts.indent, + nonEmpty.opts.indent, + nested.opts.indent, + nestedPh.opts.indent, + ] + expect(indents).to.eql([-1, -1, 0, 1, 0]) + }) + it("should indent nested log entries", () => { + const entry = logger.info("hello") + const nested = entry.info("nested") + const deepNested = nested.info("deep nested") + const deepDeepNested = deepNested.info("deep deep inside") + const deepDeepPh = deepDeepNested.placeholder() + const deepDeepNested2 = deepDeepPh.info("") + const indents = [ + entry.opts.indent, + nested.opts.indent, + deepNested.opts.indent, + deepDeepNested.opts.indent, + deepDeepPh.opts.indent, + deepDeepNested2.opts.indent, + ] + expect(indents).to.eql([undefined, 1, 2, 3, 2, 3]) + }) + it("should create a log entry with level geq to its parent", () => { + const verbose = logger.verbose("") + const levels = [ + verbose.error("").level, + verbose.warn("").level, + verbose.info("").level, + verbose.verbose("").level, + verbose.debug("").level, + verbose.silly("").level, + ] + expect(levels).to.eql([3, 3, 3, 3, 4, 5]) }) describe("setState", () => { it("should update entry state and optionally append new msg to previous msg", () => { + const entry = logger.info("") entry.setState("new") expect(entry.opts.msg).to.equal("new") entry.setState({ msg: "new2", append: true }) @@ -210,6 +245,7 @@ describe("LogEntry", () => { }) describe("setState", () => { it("should preserve status", () => { + const entry = logger.info("") entry.setSuccess() entry.setState("change text") expect(entry.opts.status).to.equal("success") @@ -217,12 +253,14 @@ describe("LogEntry", () => { }) describe("setDone", () => { it("should update entry state and set status to done", () => { + const entry = logger.info("") entry.setDone() expect(entry.opts.status).to.equal("done") }) }) describe("setSuccess", () => { it("should update entry state and set status and symbol to success", () => { + const entry = logger.info("") entry.setSuccess() expect(entry.opts.status).to.equal("success") expect(entry.opts.symbol).to.equal("success") @@ -230,6 +268,7 @@ describe("LogEntry", () => { }) describe("setError", () => { it("should update entry state and set status and symbol to error", () => { + const entry = logger.info("") entry.setError() expect(entry.opts.status).to.equal("error") expect(entry.opts.symbol).to.equal("error") @@ -237,6 +276,7 @@ describe("LogEntry", () => { }) describe("setWarn", () => { it("should update entry state and set status and symbol to warn", () => { + const entry = logger.info("") entry.setWarn() expect(entry.opts.status).to.equal("warn") expect(entry.opts.symbol).to.equal("warning") @@ -247,7 +287,7 @@ describe("LogEntry", () => { describe("renderers", () => { describe("renderMsg", () => { it("should return an empty string if the entry is empty", () => { - const entry = logger.info() + const entry = logger.placeholder() expect(renderMsg(entry)).to.equal("") }) it("should render the message with the message style", () => { @@ -282,7 +322,7 @@ describe("renderers", () => { expect(formatForTerminal(entry)).to.equal("\n") }) it("should return an empty string without a new line if the entry is empty", () => { - const entry = logger.info() + const entry = logger.placeholder() expect(formatForTerminal(entry)).to.equal("") }) }) diff --git a/garden-service/test/src/plugins/container.ts b/garden-service/test/src/plugins/container.ts index a84f7a38b7..baca9ed215 100644 --- a/garden-service/test/src/plugins/container.ts +++ b/garden-service/test/src/plugins/container.ts @@ -60,7 +60,7 @@ describe("plugins.container", () => { beforeEach(async () => { garden = await makeTestGarden(projectRoot, { container: gardenPlugin }) - log = garden.log.info() + log = garden.log ctx = garden.getPluginContext("container") td.replace(garden.buildDir, "syncDependencyProducts", () => null) diff --git a/garden-service/test/src/plugins/generic.ts b/garden-service/test/src/plugins/generic.ts index 38111272aa..be09d3a16c 100644 --- a/garden-service/test/src/plugins/generic.ts +++ b/garden-service/test/src/plugins/generic.ts @@ -25,7 +25,7 @@ describe("generic plugin", () => { beforeEach(async () => { garden = await makeTestGarden(projectRoot, { generic: gardenPlugin }) - log = garden.log.info() + log = garden.log await garden.clearBuilds() }) diff --git a/garden-service/test/src/task-graph.ts b/garden-service/test/src/task-graph.ts index 55fca36717..78bece8c56 100644 --- a/garden-service/test/src/task-graph.ts +++ b/garden-service/test/src/task-graph.ts @@ -36,7 +36,7 @@ class TestTask extends BaseTask { ) { super({ garden, - log: garden.log.info(), + log: garden.log, version: { versionString: "12345-6789", dirtyTimestamp: 6789, @@ -93,7 +93,7 @@ describe("task-graph", () => { it("should successfully process a single task without dependencies", async () => { const garden = await getGarden() - const graph = new TaskGraph(garden.log.info()) + const graph = new TaskGraph(garden.log) const task = new TestTask(garden, "a") await graph.addTask(task) @@ -116,7 +116,7 @@ describe("task-graph", () => { it("should process multiple tasks in dependency order", async () => { const garden = await getGarden() - const graph = new TaskGraph(garden.log.info()) + const graph = new TaskGraph(garden.log) const callbackResults = {} const resultOrder: string[] = [] @@ -208,7 +208,7 @@ describe("task-graph", () => { it("should recursively cancel a task's dependants when it throws an error", async () => { const garden = await getGarden() - const graph = new TaskGraph(garden.log.info()) + const graph = new TaskGraph(garden.log) const resultOrder: string[] = [] @@ -249,7 +249,7 @@ describe("task-graph", () => { "should process a task as an inheritor of an existing, in-progress task when they have the same base key", async () => { const garden = await getGarden() - const graph = new TaskGraph(garden.log.info()) + const graph = new TaskGraph(garden.log) let callbackResults = {} let resultOrder: string[] = [] diff --git a/garden-service/test/src/tasks/helpers.ts b/garden-service/test/src/tasks/helpers.ts index 4b7e2c30cd..50f1192599 100644 --- a/garden-service/test/src/tasks/helpers.ts +++ b/garden-service/test/src/tasks/helpers.ts @@ -6,6 +6,7 @@ import { Garden } from "../../../src/garden" import { makeTestGarden, dataDir } from "../../helpers" import { getTasksForModule } from "../../../src/tasks/helpers" 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())))) @@ -18,9 +19,11 @@ function sortedBaseKeys(tasks: BaseTask[]): string[] { describe("TaskHelpers", () => { let garden: Garden + let log: LogEntry before(async () => { garden = await makeTestGarden(resolve(dataDir, "test-project-dependants")) + log = garden.log }) /** @@ -32,7 +35,7 @@ describe("TaskHelpers", () => { it("returns the correct set of tasks for the changed module", async () => { const module = await garden.getModule("good-morning") const tasks = await getTasksForModule({ - garden, module, hotReloadServiceNames: [], force: true, forceBuild: true, + garden, log, module, hotReloadServiceNames: [], force: true, forceBuild: true, fromWatch: false, includeDependants: false, }) @@ -154,7 +157,7 @@ describe("TaskHelpers", () => { it(`returns the correct set of tasks for ${moduleName} and its dependants`, async () => { const module = await garden.getModule(moduleName) const tasks = await getTasksForModule({ - garden, module, hotReloadServiceNames: [], force: true, forceBuild: true, + garden, log, module, hotReloadServiceNames: [], force: true, forceBuild: true, fromWatch: true, includeDependants: true, }) expect(sortedBaseKeys(tasks)).to.eql(withoutDependencies) @@ -212,7 +215,7 @@ describe("TaskHelpers", () => { it(`returns the correct set of tasks for ${moduleName} and its dependants`, async () => { const module = await garden.getModule(moduleName) const tasks = await getTasksForModule({ - garden, module, hotReloadServiceNames: ["good-morning"], force: true, forceBuild: true, + garden, log, module, hotReloadServiceNames: ["good-morning"], force: true, forceBuild: true, fromWatch: true, includeDependants: true, }) expect(sortedBaseKeys(tasks)).to.eql(withoutDependencies) diff --git a/garden-service/test/src/tasks/test.ts b/garden-service/test/src/tasks/test.ts index f757383378..038f6198b2 100644 --- a/garden-service/test/src/tasks/test.ts +++ b/garden-service/test/src/tasks/test.ts @@ -12,7 +12,7 @@ describe("TestTask", () => { beforeEach(async () => { garden = await makeTestGarden(resolve(dataDir, "test-project-test-deps")) - log = garden.log.info() + log = garden.log }) it("should correctly resolve version for tests with dependencies", async () => {