Skip to content

Commit

Permalink
feat(config): add environments field on actions
Browse files Browse the repository at this point in the history
This allows setting e.g. `environments: [dev]` on actions instead of the
more verbose `disabled: ${environment.name != "dev"}`.
  • Loading branch information
edvald authored and vvagaytsev committed Feb 1, 2024
1 parent 4de3cc2 commit cc61603
Show file tree
Hide file tree
Showing 38 changed files with 364 additions and 44 deletions.
16 changes: 11 additions & 5 deletions core/src/actions/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,14 @@ export const baseActionConfigSchema = createSchema({
`
)
.meta({ templateContext: ActionConfigContext }),
environments: joi
.sparseArray()
.items(joi.string())
.description(
dedent`
If set, the action is only enabled for the listed environment types. This is effectively a cleaner shorthand for the \`disabled\` field with an expression for environments. For example, \`environments: ["prod"]\` is equivalent to \`disabled: \${environment.name != "prod"}\`.
`
),

// Version/file handling (Note: Descriptions and behaviors are different on Build actions!)
include: includeExcludeSchema()
Expand Down Expand Up @@ -411,8 +419,7 @@ export abstract class BaseAction<

isDisabled(): boolean {
// TODO: return true if group is disabled
// TODO: implement environments field on action config
return actionIsDisabled(this._config, "TODO")
return actionIsDisabled(this._config, this.graph.environmentName)
}

/**
Expand Down Expand Up @@ -888,9 +895,8 @@ export function addActionDependency(dep: ActionDependency, dependencies: ActionD
dependencies.push(dep)
}

export function actionIsDisabled(config: ActionConfig, _environmentName: string): boolean {
// TODO: implement environment fields and check if environment is disabled
return config.disabled === true
export function actionIsDisabled(config: ActionConfig, environmentName: string): boolean {
return config.disabled === true || (!!config.environments && !config.environments.includes(environmentName))
}

/**
Expand Down
1 change: 1 addition & 0 deletions core/src/actions/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export interface BaseActionConfig<K extends ActionKind = ActionKind, T = string,
// -> Templating with ActionConfigContext allowed
dependencies?: ActionReference[]
disabled?: boolean
environments?: string[]

// Version/file handling
// -> Templating with ActionConfigContext allowed
Expand Down
7 changes: 6 additions & 1 deletion core/src/commands/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,12 @@ export class PluginsCommand extends Command<Args> {
const provider = await garden.resolveProvider(log, args.plugin)
const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined })

let graph = new ConfigGraph({ actions: [], moduleGraph: new ModuleGraph([], {}), groups: [] })
let graph = new ConfigGraph({
environmentName: garden.environmentName,
actions: [],
moduleGraph: new ModuleGraph([], {}),
groups: [],
})

// Commands can optionally ask for all the modules in the project/environment
if (command.resolveGraph) {
Expand Down
2 changes: 1 addition & 1 deletion core/src/garden.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1063,7 +1063,6 @@ export class Garden {
moduleGraph,
actionModes,
linkedSources,
environmentName: this.environmentName,
})

// TODO-0.13.1: detect overlap on Build actions
Expand Down Expand Up @@ -1190,6 +1189,7 @@ export class Garden {
const graph = await this.getConfigGraph(params)
const resolved = await this.resolveActions({ graph, actions: graph.getActions(), log: params.log })
return new ResolvedConfigGraph({
environmentName: this.environmentName,
actions: Object.values(resolved),
moduleGraph: graph.moduleGraph,
// TODO: perhaps groups should be resolved here
Expand Down
13 changes: 8 additions & 5 deletions core/src/graph/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ export const actionConfigsToGraph = profileAsync(async function actionConfigsToG
moduleGraph,
actionModes,
linkedSources,
environmentName,
}: {
garden: Garden
log: Log
Expand All @@ -87,7 +86,6 @@ export const actionConfigsToGraph = profileAsync(async function actionConfigsToG
moduleGraph: ModuleGraph
actionModes: ActionModeMap
linkedSources: LinkedSourceMap
environmentName: string
}): Promise<MutableConfigGraph> {
const configsByKey: ActionConfigsByKey = {}

Expand All @@ -100,10 +98,10 @@ export const actionConfigsToGraph = profileAsync(async function actionConfigsToG
const existing = configsByKey[key]

if (existing) {
if (actionIsDisabled(config, environmentName)) {
if (actionIsDisabled(config, garden.environmentName)) {
log.silly(() => `Skipping disabled action ${key} in favor of other action with same key`)
return
} else if (actionIsDisabled(existing, environmentName)) {
} else if (actionIsDisabled(existing, garden.environmentName)) {
log.silly(() => `Skipping disabled action ${key} in favor of other action with same key`)
configsByKey[key] = config
return
Expand Down Expand Up @@ -205,7 +203,12 @@ export const actionConfigsToGraph = profileAsync(async function actionConfigsToG
const minimalRoots = await garden.vcs.getMinimalRoots(log, allPaths)

// TODO: Maybe we could optimize resolving tree versions, avoid parallel scanning of the same directory etc.
const graph = new MutableConfigGraph({ actions: [], moduleGraph, groups: groupConfigs })
const graph = new MutableConfigGraph({
environmentName: garden.environmentName,
actions: [],
moduleGraph,
groups: groupConfigs,
})

await Promise.all(
Object.entries(preprocessResults).map(async ([key, res]) => {
Expand Down
12 changes: 11 additions & 1 deletion core/src/graph/config-graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,16 +91,20 @@ export abstract class BaseConfigGraph<
}

readonly moduleGraph: ModuleGraph
readonly environmentName: string

constructor({
environmentName,
actions,
moduleGraph,
groups,
}: {
environmentName: string
actions: Action[]
moduleGraph: ModuleGraph
groups: GroupConfig[]
}) {
this.environmentName = environmentName
this.dependencyGraph = {}
this.actions = {
Build: {},
Expand Down Expand Up @@ -132,7 +136,12 @@ export abstract class BaseConfigGraph<
}

clone() {
const clone = new ConfigGraph({ actions: [], moduleGraph: this.moduleGraph, groups: Object.values(this.groups) })
const clone = new ConfigGraph({
environmentName: this.environmentName,
actions: [],
moduleGraph: this.moduleGraph,
groups: Object.values(this.groups),
})
for (const key of Object.getOwnPropertyNames(this)) {
clone[key] = cloneDeep(this[key])
}
Expand Down Expand Up @@ -455,6 +464,7 @@ export abstract class BaseConfigGraph<

toMutableGraph() {
return new MutableConfigGraph({
environmentName: this.environmentName,
actions: this.getActions(),
moduleGraph: this.moduleGraph,
groups: Object.values(this.groups),
Expand Down
1 change: 1 addition & 0 deletions core/src/tasks/resolve-action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ export class ResolveActionTask<T extends Action> extends BaseActionTask<T, Resol

// Resolve action without outputs
const resolvedGraph = new ResolvedConfigGraph({
environmentName: this.graph.environmentName,
actions: [...resolvedDependencies, ...executedDependencies],
moduleGraph: this.graph.moduleGraph,
groups: this.graph.getGroups(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
kind: Project
apiVersion: garden.io/v1
name: config-action-environments
environments:
- name: local
- name: remote
providers:
- name: test-plugin
---
kind: Build
type: test
name: a
---
kind: Build
type: test
name: b
environments: [local]
Loading

0 comments on commit cc61603

Please sign in to comment.