Skip to content

Commit

Permalink
refactor: split GardenContext into Garden and PluginContext
Browse files Browse the repository at this point in the history
This is to reduce the size and scope of the GardenContext object, as well
as to reduce visibility and access for plugin actions. I'm doing this now
because I'm about to make further changes to plugin flows, and wanted to
be done with this first.
  • Loading branch information
edvald committed Apr 13, 2018
1 parent 64bce4f commit 04b5417
Show file tree
Hide file tree
Showing 46 changed files with 651 additions and 573 deletions.
9 changes: 3 additions & 6 deletions src/build-dir.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,16 @@ import * as Rsync from "rsync"
import { GARDEN_DIR_NAME } from "./constants"
import { execRsyncCmd } from "./util"
import { Module } from "./types/module"
import { Garden } from "./garden"

// Lazily construct a directory of modules inside which all build steps are performed.

const buildDirRelPath = join(GARDEN_DIR_NAME, "build")

export class BuildDir {
buildDirPath: string
private ctx: Garden

constructor(ctx: Garden) {
this.ctx = ctx
this.buildDirPath = join(ctx.projectRoot, buildDirRelPath)
constructor(private projectRoot: string) {
this.buildDirPath = join(projectRoot, buildDirRelPath)
}

// Synchronous, so it can run in Garden's constructor.
Expand All @@ -44,7 +41,7 @@ export class BuildDir {

async syncFromSrc<T extends Module>(module: T) {
await this.sync(
resolve(this.ctx.projectRoot, module.path),
resolve(this.projectRoot, module.path),
this.buildDirPath)
}

Expand Down
7 changes: 5 additions & 2 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
ParameterValues,
Parameter,
StringParameter,
EnvironmentOption,
} from "./commands/base"
import { ValidateCommand } from "./commands/validate"
import { InternalError, PluginError } from "./exceptions"
Expand All @@ -42,6 +43,7 @@ const GLOBAL_OPTIONS = {
help: "override project root directory (defaults to working directory)",
defaultValue: process.cwd(),
}),
env: new EnvironmentOption(),
verbose: new BooleanParameter({
alias: "v",
help: "verbose logging",
Expand Down Expand Up @@ -263,6 +265,7 @@ export class GardenCli {
const argsForAction = filterByArray(argv, argKeys)
const optsForAction = filterByArray(argv, optKeys.concat(globalKeys))
const root = resolve(process.cwd(), optsForAction.root)
const env = optsForAction.env

// Update logger config
if (argv.silent) {
Expand All @@ -277,8 +280,8 @@ export class GardenCli {
)
}

const ctx = await Garden.factory(root, { logger, plugins: defaultPlugins })
return command.action(ctx, argsForAction, optsForAction)
const garden = await Garden.factory(root, { env, logger, plugins: defaultPlugins })
return command.action(garden.pluginContext, argsForAction, optsForAction)
}

// Command specific positional args and options are set inside the builder function
Expand Down
4 changes: 2 additions & 2 deletions src/commands/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import { Garden } from "../garden"
import { PluginContext } from "../plugin-context"

export class ValidationError extends Error { }

Expand Down Expand Up @@ -132,5 +132,5 @@ export abstract class Command<T extends Parameters = {}, U extends Parameters =
// subclass implementations need to explicitly set the types in the implemented function signature. So for now we
// can't enforce the types of `args` and `opts` automatically at the abstract class level and have to specify
// the types explicitly on the subclassed methods.
abstract async action(ctx: Garden, args: ParameterValues<T>, opts: ParameterValues<U>): Promise<any>
abstract async action(ctx: PluginContext, args: ParameterValues<T>, opts: ParameterValues<U>): Promise<any>
}
6 changes: 3 additions & 3 deletions src/commands/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import { PluginContext } from "../plugin-context"
import { BooleanParameter, Command, ParameterValues, StringParameter } from "./base"
import { Garden } from "../garden"
import { BuildTask } from "../tasks/build"
import { values } from "lodash"
import { TaskResults } from "../task-graph"
Expand All @@ -32,8 +32,8 @@ export class BuildCommand extends Command<typeof buildArguments, typeof buildOpt
arguments = buildArguments
options = buildOptions

async action(ctx: Garden, args: BuildArguments, opts: BuildOptions): Promise<TaskResults> {
await ctx.buildDir.clear()
async action(ctx: PluginContext, args: BuildArguments, opts: BuildOptions): Promise<TaskResults> {
await ctx.clearBuilds()
const names = args.module ? args.module.split(",") : undefined
const modules = await ctx.getModules(names)

Expand Down
16 changes: 3 additions & 13 deletions src/commands/call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
import { resolve } from "url"
import Axios from "axios"
import chalk from "chalk"
import { Command, EnvironmentOption, ParameterValues, StringParameter } from "./base"
import { Garden } from "../garden"
import { Command, ParameterValues, StringParameter } from "./base"
import { splitFirst } from "../util"
import { ParameterError, RuntimeError } from "../exceptions"
import { EntryStyle } from "../logger/types"
import { pick } from "lodash"
import { PluginContext } from "../plugin-context"

export const callArgs = {
serviceAndPath: new StringParameter({
Expand All @@ -23,25 +23,15 @@ export const callArgs = {
}),
}

export const options = {
env: new EnvironmentOption({
help: "The environment (and optionally namespace) to call to",
}),
}

export type Args = ParameterValues<typeof callArgs>
export type Opts = ParameterValues<typeof options>

export class CallCommand extends Command<typeof callArgs> {
name = "call"
help = "Call a service endpoint"

arguments = callArgs
options = options

async action(ctx: Garden, args: Args, opts: Opts) {
opts.env && ctx.setEnvironment(opts.env)

async action(ctx: PluginContext, args: Args) {
let [serviceName, path] = splitFirst(args.serviceAndPath, "/")
path = "/" + path

Expand Down
17 changes: 4 additions & 13 deletions src/commands/config/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import { Command, EnvironmentOption, ParameterValues, StringParameter } from "../base"
import { Garden } from "../../garden"
import { PluginContext } from "../../plugin-context"
import { Command, ParameterValues, StringParameter } from "../base"
import { NotFoundError } from "../../exceptions"

export const configDeleteArgs = {
Expand All @@ -17,27 +17,18 @@ export const configDeleteArgs = {
}),
}

export const configDeleteOpts = {
env: new EnvironmentOption({
help: "Set the environment (and optionally namespace) to delete the config variable from",
}),
}

export type DeleteArgs = ParameterValues<typeof configDeleteArgs>
export type DeleteOpts = ParameterValues<typeof configDeleteOpts>

// TODO: add --all option to remove all configs

export class ConfigDeleteCommand extends Command<typeof configDeleteArgs, typeof configDeleteOpts> {
export class ConfigDeleteCommand extends Command<typeof configDeleteArgs> {
name = "delete"
alias = "del"
help = "Delete a configuration variable"

arguments = configDeleteArgs
options = configDeleteOpts

async action(ctx: Garden, args: DeleteArgs, opts: DeleteOpts) {
opts.env && ctx.setEnvironment(opts.env)
async action(ctx: PluginContext, args: DeleteArgs) {
const res = await ctx.deleteConfig(args.key.split("."))

if (res.found) {
Expand Down
17 changes: 4 additions & 13 deletions src/commands/config/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import { Command, EnvironmentOption, ParameterValues, StringParameter } from "../base"
import { Garden } from "../../garden"
import { PluginContext } from "../../plugin-context"
import { Command, ParameterValues, StringParameter } from "../base"

export const configGetArgs = {
key: new StringParameter({
Expand All @@ -16,26 +16,17 @@ export const configGetArgs = {
}),
}

export const configGetOpts = {
env: new EnvironmentOption({
help: "Get the environment (and optionally namespace) where the config should be stored",
}),
}

export type GetArgs = ParameterValues<typeof configGetArgs>
export type GetOpts = ParameterValues<typeof configGetOpts>

// TODO: allow omitting key to return all configs

export class ConfigGetCommand extends Command<typeof configGetArgs, typeof configGetOpts> {
export class ConfigGetCommand extends Command<typeof configGetArgs> {
name = "get"
help = "Get a configuration variable"

arguments = configGetArgs
options = configGetOpts

async action(ctx: Garden, args: GetArgs, opts: GetOpts) {
opts.env && ctx.setEnvironment(opts.env)
async action(ctx: PluginContext, args: GetArgs) {
const res = await ctx.getConfig(args.key.split("."))

ctx.log.info(res)
Expand Down
17 changes: 4 additions & 13 deletions src/commands/config/set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import { Command, EnvironmentOption, ParameterValues, StringParameter } from "../base"
import { Garden } from "../../garden"
import { PluginContext } from "../../plugin-context"
import { Command, ParameterValues, StringParameter } from "../base"

export const configSetArgs = {
key: new StringParameter({
Expand All @@ -20,26 +20,17 @@ export const configSetArgs = {
}),
}

export const configSetOpts = {
env: new EnvironmentOption({
help: "Set the environment (and optionally namespace) where the config should be stored",
}),
}

export type SetArgs = ParameterValues<typeof configSetArgs>
export type SetOpts = ParameterValues<typeof configSetOpts>

// TODO: allow reading key/value pairs from a file

export class ConfigSetCommand extends Command<typeof configSetArgs, typeof configSetOpts> {
export class ConfigSetCommand extends Command<typeof configSetArgs> {
name = "set"
help = "Set a configuration variable"

arguments = configSetArgs
options = configSetOpts

async action(ctx: Garden, args: SetArgs, opts: SetOpts) {
opts.env && ctx.setEnvironment(opts.env)
async action(ctx: PluginContext, args: SetArgs) {
await ctx.setConfig(args.key.split("."), args.value)
ctx.log.info(`Set config key ${args.key}`)
return { ok: true }
Expand Down
12 changes: 4 additions & 8 deletions src/commands/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import { BooleanParameter, Command, EnvironmentOption, ParameterValues, StringParameter } from "./base"
import { Garden } from "../garden"
import { PluginContext } from "../plugin-context"
import { BooleanParameter, Command, ParameterValues, StringParameter } from "./base"
import { DeployTask } from "../tasks/deploy"
import { values } from "lodash"
import { Service } from "../types/service"
Expand All @@ -22,9 +22,6 @@ export const deployArgs = {
}

export const deployOpts = {
env: new EnvironmentOption({
help: "Set the environment (and optionally namespace) to deploy to",
}),
force: new BooleanParameter({ help: "Force redeploy of service(s)" }),
"force-build": new BooleanParameter({ help: "Force rebuild of module(s)" }),
}
Expand All @@ -39,10 +36,9 @@ export class DeployCommand extends Command<typeof deployArgs, typeof deployOpts>
arguments = deployArgs
options = deployOpts

async action(ctx: Garden, args: Args, opts: Opts): Promise<TaskResults> {
async action(ctx: PluginContext, args: Args, opts: Opts): Promise<TaskResults> {
ctx.log.header({ emoji: "rocket", command: "Deploy" })

opts.env && ctx.setEnvironment(opts.env)
const names = args.service ? args.service.split(",") : undefined
const services = await ctx.getServices(names)

Expand All @@ -56,7 +52,7 @@ export class DeployCommand extends Command<typeof deployArgs, typeof deployOpts>
}

export async function deployServices(
ctx: Garden,
ctx: PluginContext,
services: Service<any>[],
force: boolean,
forceBuild: boolean,
Expand Down
18 changes: 4 additions & 14 deletions src/commands/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import { Command, EnvironmentOption, ParameterValues } from "./base"
import { Garden } from "../garden"
import { PluginContext } from "../plugin-context"
import { Command } from "./base"
import { join } from "path"
import { STATIC_DIR } from "../constants"
import { spawnSync } from "child_process"
Expand All @@ -19,19 +19,11 @@ import { sleep } from "../util"
const imgcatPath = join(__dirname, "..", "..", "bin", "imgcat")
const bannerPath = join(STATIC_DIR, "garden-banner-1-half.png")

export const options = {
env: new EnvironmentOption(),
}

export type Opts = ParameterValues<typeof options>

export class DevCommand extends Command<Opts> {
export class DevCommand extends Command {
name = "dev"
help = "Starts the garden development console"

options = options

async action(ctx: Garden, _args, opts: Opts) {
async action(ctx: PluginContext) {
try {
spawnSync(imgcatPath, [bannerPath], {
stdio: "inherit",
Expand All @@ -44,8 +36,6 @@ export class DevCommand extends Command<Opts> {
// console.log(chalk.bold(` garden - dev\n`))
console.log(chalk.gray.italic(` Good afternoon, Jon! Let's get your environment wired up...\n`))

opts.env && ctx.setEnvironment(opts.env)

await ctx.configureEnvironment()

const services = values(await ctx.getServices())
Expand Down
20 changes: 5 additions & 15 deletions src/commands/environment/configure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,16 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import { Command, EnvironmentOption, ParameterValues } from "../base"
import { Garden } from "../../garden"
import { PluginContext } from "../../plugin-context"
import { EnvironmentStatusMap } from "../../types/plugin"
import { Command } from "../base"

export const options = {
env: new EnvironmentOption({
help: "Set the environment (and optionally namespace) to configure",
}),
}

export type Opts = ParameterValues<typeof options>

export class EnvironmentConfigureCommand extends Command<typeof options> {
export class EnvironmentConfigureCommand extends Command {
name = "configure"
alias = "config"
help = "Configures your environment"

options = options

async action(ctx: Garden, _args, opts: Opts) {
opts.env && ctx.setEnvironment(opts.env)
async action(ctx: PluginContext): Promise<EnvironmentStatusMap> {
const { name } = ctx.getEnvironment()
ctx.log.header({ emoji: "gear", command: `Configuring ${name} environment` })

Expand Down
Loading

0 comments on commit 04b5417

Please sign in to comment.