Skip to content

Commit

Permalink
feat(workflows): add envVars field for script steps
Browse files Browse the repository at this point in the history
Nice and simple, what it says on the tin.
  • Loading branch information
edvald authored and thsig committed Feb 5, 2021
1 parent bea46ed commit 857e845
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 8 deletions.
2 changes: 1 addition & 1 deletion core/src/commands/run/workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ export async function runStepCommand({

export async function runStepScript({ garden, bodyLog, step }: RunStepParams): Promise<CommandResult<any>> {
try {
await runScript(bodyLog, garden.projectRoot, step.script!)
await runScript({ log: bodyLog, cwd: garden.projectRoot, script: step.script!, envVars: step.envVars })
return { result: {} }
} catch (_err) {
const error = _err as ExecaError
Expand Down
6 changes: 5 additions & 1 deletion core/src/config/workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import { isEqual, merge, omit, take } from "lodash"
import { joi, joiUserIdentifier, joiVariableName, joiIdentifier } from "./common"
import { joi, joiUserIdentifier, joiVariableName, joiIdentifier, joiEnvVars, PrimitiveMap } from "./common"
import { DEFAULT_API_VERSION } from "../constants"
import { deline, dedent } from "../util/string"
import { defaultContainerLimits, ServiceLimitSpec } from "../plugins/container/config"
Expand Down Expand Up @@ -142,6 +142,7 @@ export interface WorkflowStepSpec {
name?: string
command?: string[]
description?: string
envVars?: PrimitiveMap
script?: string
skip?: boolean
when?: workflowStepModifier
Expand Down Expand Up @@ -183,6 +184,9 @@ export const workflowStepSchema = () => {
)
.example(["run", "task", "my-task"]),
description: joi.string().description("A description of the workflow step."),
envVars: joiEnvVars().description(
"A map of environment variables to use when running script steps. Ignored for `command` steps."
),
script: joi.string().description(
dedent`
A bash script to run. Note that the host running the workflow must have bash installed and on path.
Expand Down
2 changes: 1 addition & 1 deletion core/src/plugins/exec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ export const execPlugin = () =>
if (ctx.provider.config.initScript) {
try {
log.info({ section: "exec", msg: "Running init script" })
await runScript(log, ctx.projectRoot, ctx.provider.config.initScript)
await runScript({ log, cwd: ctx.projectRoot, script: ctx.provider.config.initScript })
} catch (_err) {
const error = _err as ExecaError

Expand Down
14 changes: 13 additions & 1 deletion core/src/util/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { tailString, dedent } from "./string"
import { Writable, Readable } from "stream"
import { LogEntry } from "../logger/log-entry"
import execa = require("execa")
import { PrimitiveMap } from "../config/common"
export { v4 as uuidv4 } from "uuid"

export type HookCallback = (callback?: () => void) => void
Expand Down Expand Up @@ -637,7 +638,17 @@ export function getDurationMsec(start: Date, end: Date): number {
return Math.round(end.getTime() - start.getTime())
}

export async function runScript(log: LogEntry, cwd: string, script: string) {
export async function runScript({
log,
cwd,
script,
envVars,
}: {
log: LogEntry
cwd: string
script: string
envVars?: PrimitiveMap
}) {
// Run the script, capturing any errors
const proc = execa("bash", ["-s"], {
all: true,
Expand All @@ -647,6 +658,7 @@ export async function runScript(log: LogEntry, cwd: string, script: string) {
// Set a very large max buffer (we only hold one of these at a time, and want to avoid overflow errors)
buffer: true,
maxBuffer: 100 * 1024 * 1024,
env: mapValues(envVars, (v) => (v === undefined ? undefined : "" + v)),
})

// Stream output to `log`, splitting by line
Expand Down
21 changes: 21 additions & 0 deletions core/test/unit/src/commands/run/workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,27 @@ describe("RunWorkflowCommand", () => {
expect(result?.steps["step-1"].log).to.equal(garden.projectRoot)
})

it("should apply configured envVars when running script steps", async () => {
garden.setWorkflowConfigs([
{
apiVersion: DEFAULT_API_VERSION,
name: "workflow-a",
kind: "Workflow",
path: garden.projectRoot,
files: [],
steps: [{ script: "echo $FOO $BAR", envVars: { FOO: "foo", BAR: 123 } }],
},
])

await cmd.action({ ...defaultParams, args: { workflow: "workflow-a" } })

const { result, errors } = await cmd.action({ ...defaultParams, args: { workflow: "workflow-a" } })

expect(result).to.exist
expect(errors).to.not.exist
expect(result?.steps["step-1"].log).to.equal("foo 123")
})

it("should skip disabled steps", async () => {
garden.setWorkflowConfigs([
{
Expand Down
9 changes: 5 additions & 4 deletions core/test/unit/src/config/workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ describe("resolveWorkflowConfig", () => {
path: "/tmp/foo",
description: "Sample workflow",
steps: [
{ description: "Deploy the stack", command: ["deploy"], skip: false, when: "onSuccess" },
{ command: ["test"], skip: false, when: "onSuccess" },
{ description: "Deploy the stack", command: ["deploy"], skip: false, when: "onSuccess", envVars: {} },
{ command: ["test"], skip: false, when: "onSuccess", envVars: {} },
],
triggers: [
{
Expand Down Expand Up @@ -77,6 +77,7 @@ describe("resolveWorkflowConfig", () => {
command: ["deploy"],
skip: ("${var.skip}" as unknown) as boolean,
when: "onSuccess",
envVars: {},
},
],
}
Expand Down Expand Up @@ -170,8 +171,8 @@ describe("resolveWorkflowConfig", () => {
...config,
...defaults,
steps: [
{ description: "Deploy the stack", command: ["deploy"], skip: false, when: "onSuccess" },
{ command: ["test"], skip: false, when: "onSuccess" },
{ description: "Deploy the stack", command: ["deploy"], skip: false, when: "onSuccess", envVars: {} },
{ command: ["test"], skip: false, when: "onSuccess", envVars: {} },
],
})
})
Expand Down
5 changes: 5 additions & 0 deletions docs/reference/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -1227,6 +1227,11 @@ workflowConfigs:
# A description of the workflow step.
description:

# A map of environment variables to use when running script steps. Ignored for `command` steps.
envVars:
# Number, string or boolean
<name>:

# A bash script to run. Note that the host running the workflow must have bash installed and on path.
# It is considered to have run successfully if it returns an exit code of 0. Any other exit code signals an
# error,
Expand Down
13 changes: 13 additions & 0 deletions docs/reference/workflow-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ steps:
# A description of the workflow step.
description:

# A map of environment variables to use when running script steps. Ignored for `command` steps.
envVars: {}

# A bash script to run. Note that the host running the workflow must have bash installed and on path.
# It is considered to have run successfully if it returns an exit code of 0. Any other exit code signals an error,
# and the remainder of the workflow is aborted.
Expand Down Expand Up @@ -368,6 +371,16 @@ A description of the workflow step.
| -------- | -------- |
| `string` | No |

### `steps[].envVars`

[steps](#steps) > envVars

A map of environment variables to use when running script steps. Ignored for `command` steps.

| Type | Default | Required |
| -------- | ------- | -------- |
| `object` | `{}` | No |

### `steps[].script`

[steps](#steps) > script
Expand Down

0 comments on commit 857e845

Please sign in to comment.