Skip to content

Commit

Permalink
fix(cli): ensure 'noProject' commands run in invalid projects
Browse files Browse the repository at this point in the history
  • Loading branch information
eysi09 committed Jan 13, 2020
1 parent 279343d commit 4e7ff83
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 26 deletions.
52 changes: 33 additions & 19 deletions garden-service/src/cli/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,21 +67,33 @@ const OUTPUT_RENDERERS = {
const GLOBAL_OPTIONS_GROUP_NAME = "Global options"
const DEFAULT_CLI_LOGGER_TYPE = "fancy"

// For initializing garden without a project config
export const MOCK_CONFIG: ProjectConfig = {
path: process.cwd(),
apiVersion: DEFAULT_API_VERSION,
kind: "Project",
name: "mock-project",
defaultEnvironment: "local",
dotIgnoreFiles: defaultDotIgnoreFiles,
environments: defaultEnvironments,
providers: [
{
name: "local-kubernetes",
},
],
variables: {},
/**
* Dummy Garden class that doesn't scan for modules nor resolves providers.
* Used by commands that have noProject=true. That is, commands that need
* to run outside of valid Garden projects.
*/
class DummyGarden extends Garden {
async resolveProviders() {
return []
}
async scanModules() {}
}

export async function makeDummyGarden(root: string, gardenOpts: GardenOpts) {
const config: ProjectConfig = {
path: root,
apiVersion: DEFAULT_API_VERSION,
kind: "Project",
name: "no-project",
defaultEnvironment: "",
dotIgnoreFiles: defaultDotIgnoreFiles,
environments: defaultEnvironments,
providers: [],
variables: {},
}
gardenOpts.config = config

return DummyGarden.factory(root, gardenOpts)
}

// The help text for these commands is only displayed when calling `garden options`.
Expand Down Expand Up @@ -285,9 +297,7 @@ export class GardenCli {
environmentName: env,
log,
}
if (command.noProject) {
contextOpts.config = MOCK_CONFIG
}

let garden: Garden
let result: any

Expand All @@ -303,7 +313,11 @@ export class GardenCli {

do {
try {
garden = await Garden.factory(root, contextOpts)
if (command.noProject) {
garden = await makeDummyGarden(root, contextOpts)
} else {
garden = await Garden.factory(root, contextOpts)
}
// 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, garden.gardenDirPath)
Expand Down
2 changes: 1 addition & 1 deletion garden-service/src/commands/migrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export class MigrateCommand extends Command<Args, Opts> {
await writeFile(path, out)
} else {
if (configPaths.length > 1) {
log.info(`# Updated config for garden.yml file at path ${path}`)
log.info(`# Updated config for garden.yml file at path ${path}:`)
}
log.info(out)
}
Expand Down
36 changes: 36 additions & 0 deletions garden-service/test/unit/src/cli/cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2018 Garden Technologies, Inc. <[email protected]>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import { expect } from "chai"
import { makeDummyGarden } from "../../../../src/cli/cli"
import { getDataDir } from "../../../helpers"

describe("cli", () => {
describe("makeDummyGarden", () => {
it("should initialise and resolve config graph in a directory with no project", async () => {
const garden = await makeDummyGarden("./foobarbas", {})
const dg = await garden.getConfigGraph(garden.log)
expect(garden).to.be.ok
expect(await dg.getModules()).to.not.throw
})
it("should initialise and resolve config graph in a project with invalid config", async () => {
const root = getDataDir("test-project-invalid-config")
const garden = await makeDummyGarden(root, {})
const dg = await garden.getConfigGraph(garden.log)
expect(garden).to.be.ok
expect(await dg.getModules()).to.not.throw
})
it("should initialise and resolve config graph in a project with template strings", async () => {
const root = getDataDir("test-project-templated")
const garden = await makeDummyGarden(root, {})
const dg = await garden.getConfigGraph(garden.log)
expect(garden).to.be.ok
expect(await dg.getModules()).to.not.throw
})
})
})
6 changes: 0 additions & 6 deletions garden-service/test/unit/src/garden.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import {
testGitUrl,
} from "../../helpers"
import { getNames, findByName, deepOmitUndefined } from "../../../src/util/util"
import { MOCK_CONFIG } from "../../../src/cli/cli"
import { LinkedSource } from "../../../src/config-store"
import { ModuleVersion } from "../../../src/vcs/vcs"
import { getModuleCacheContext } from "../../../src/types/module"
Expand Down Expand Up @@ -80,11 +79,6 @@ describe("Garden", () => {
expect((<any>actions).actionHandlers.prepareEnvironment["test-plugin-b"]).to.be.ok
})

it("should initialize with MOCK_CONFIG", async () => {
const garden = await Garden.factory("./", { config: MOCK_CONFIG })
expect(garden).to.be.ok
})

it("should initialize a project with config files with yaml and yml extensions", async () => {
const garden = await makeTestGarden(getDataDir("test-project-yaml-file-extensions"))
expect(garden).to.be.ok
Expand Down

0 comments on commit 4e7ff83

Please sign in to comment.