diff --git a/runatlantis.io/docs/custom-workflows.md b/runatlantis.io/docs/custom-workflows.md index d94e74984e..3ba12e1325 100644 --- a/runatlantis.io/docs/custom-workflows.md +++ b/runatlantis.io/docs/custom-workflows.md @@ -142,7 +142,11 @@ workflows: myworkflow: plan: steps: - - run: terraform init -input=false + # If you want to hide command output from Atlantis's PR comment, use + # the output option on the run step's expanded form. + - run: + command: terraform init -input=false + output: hide # If you're using workspaces you need to select the workspace using the # $WORKSPACE environment variable. @@ -264,7 +268,9 @@ workflows: # Reduce Terraform suggestion output name: TF_IN_AUTOMATION value: 'true' - - run: terragrunt plan -input=false -out=$PLANFILE + - run: + command: terragrunt plan -input=false -out=$PLANFILE + output: strip_refreshing - run: terragrunt show -json $PLANFILE > $SHOWFILE apply: steps: @@ -297,7 +303,9 @@ workflows: # Reduce Terraform suggestion output name: TF_IN_AUTOMATION value: 'true' - - run: terragrunt plan -out $PLANFILE + - run: + command: terragrunt plan -input=false -out=$PLANFILE + output: strip_refreshing apply: steps: - env: @@ -451,14 +459,28 @@ A map from string to `extra_args` for a built-in command with extra arguments. | init/plan/apply/import/state_rm | map[`extra_args` -> array[string]] | none | no | Use a built-in command and append `extra_args`. Only `init`, `plan`, `apply`, `import` and `state_rm` are supported as keys and only `extra_args` is supported as a value | #### Custom `run` Command -Or a custom command +A custom command can be written in 2 ways + +Compact: ```yaml -- run: custom-command +- run: custom-command arg1 arg2 ``` | Key | Type | Default | Required | Description | |-----|--------|---------|----------|----------------------| | run | string | none | no | Run a custom command | +Full +```yaml +- run: + command: custom-command arg1 arg2 + output: show +``` +| Key | Type | Default | Required | Description | +|-----|--------------------------------------------------------------|---------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| run | map[string -> string] | none | no | Run a custom command | +| run.command | string | none | yes | Shell command to run | +| run.output | string | "show" | no | How to post-process the output of this command when posted in the PR comment. The options are
* `show` - preserve the full output
* `hide` - hide output from comment (still visible in the real-time streaming output)
* `strip_refreshing` - hide all output up until and including the last line containing "Refreshing...". This matches the behavior of the built-in `plan` command | + ::: tip Notes * `run` steps in the main `workflow` are executed with the following environment variables: note: these variables are not available to `pre` or `post` workflows @@ -513,9 +535,12 @@ as the environment variable value. name: ENV_NAME_2 command: 'echo "dynamic-value-$(date)"' ``` -| Key | Type | Default | Required | Description | -|-----------------|------------------------------------|---------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------| -| env | map[`name` -> string, `value` -> string, `command` -> string] | none | no | Set environment variables for subsequent steps | +| Key | Type | Default | Required | Description | +|-----------------|-----------------------|---------|----------|-----------------------------------------------------------------------------------------------------------------| +| env | map[string -> string] | none | no | Set environment variables for subsequent steps | +| env.name | string | none | yes | Name of the environment variable | +| env.value | string | none | no | Set the value of the environment variable to a hard-coded string. Cannot be set at the same time as `command` | +| env.command | string | none | no | Set the value of the environment variable to the output of a command. Cannot be set at the same time as `value` | ::: tip Notes * `env` `command`'s can use any of the built-in environment variables available diff --git a/runatlantis.io/docs/repo-level-atlantis-yaml.md b/runatlantis.io/docs/repo-level-atlantis-yaml.md index 9a946f6e25..f4c1db0d23 100644 --- a/runatlantis.io/docs/repo-level-atlantis-yaml.md +++ b/runatlantis.io/docs/repo-level-atlantis-yaml.md @@ -72,6 +72,9 @@ workflows: plan: steps: - run: my-custom-command arg1 arg2 + - run: + command: my-custom-command arg1 arg2 + output: hide - init - plan: extra_args: ["-lock", "false"] diff --git a/server/core/config/raw/step.go b/server/core/config/raw/step.go index d0ad7f92ce..de69abc3dc 100644 --- a/server/core/config/raw/step.go +++ b/server/core/config/raw/step.go @@ -16,6 +16,7 @@ const ( NameArgKey = "name" CommandArgKey = "command" ValueArgKey = "value" + OutputArgKey = "output" RunStepName = "run" PlanStepName = "plan" ShowStepName = "show" @@ -34,15 +35,18 @@ const ( // - plan // - policy_check // -// 2. A map for an env step with name and command or value +// 2. A map for an env step with name and command or value, or a run step with a command and output config // - env: -// name: test -// command: echo 312 -// value: value +// name: test +// command: echo 312 +// value: value +// - run: +// command: my custom command +// output: hide // // 3. A map for a built-in command and extra_args: // - plan: -// extra_args: [-var-file=staging.tfvars] +// extra_args: [-var-file=staging.tfvars] // // 4. A map for a custom run command: // - run: my custom command @@ -53,8 +57,8 @@ type Step struct { // Key will be set in case #1 and #3 above to the key. In case #2, there // could be multiple keys (since the element is a map) so we don't set Key. Key *string - // Env will be set in case #2 above. - Env map[string]map[string]string + // EnvOrRun will be set in case #2 above. + EnvOrRun map[string]map[string]string // Map will be set in case #3 above. Map map[string]map[string][]string // StringVal will be set in case #4 above. @@ -142,7 +146,7 @@ func (s Step) Validate() error { return nil } - envStep := func(value interface{}) error { + envOrRunStep := func(value interface{}) error { elem := value.(map[string]map[string]string) var keys []string for k := range elem { @@ -155,10 +159,15 @@ func (s Step) Validate() error { return fmt.Errorf("step element can only contain a single key, found %d: %s", len(keys), strings.Join(keys, ",")) } - for stepName, args := range elem { - if stepName != EnvStepName { - return fmt.Errorf("%q is not a valid step type", stepName) - } + if len(keys) == 0 { + return fmt.Errorf("step element must contain at least 1 key") + } + + stepName := keys[0] + args := elem[keys[0]] + + switch stepName { + case EnvStepName: var argKeys []string for k := range args { argKeys = append(argKeys, k) @@ -183,7 +192,35 @@ func (s Step) Validate() error { return fmt.Errorf("env steps only support one of the %q or %q keys, found both", ValueArgKey, CommandArgKey) } + case RunStepName: + argsCopy := make(map[string]string) + for k, v := range args { + argsCopy[k] = v + } + args = argsCopy + if _, ok := args[CommandArgKey]; !ok { + return fmt.Errorf("run step must have a %q key set", CommandArgKey) + } + delete(args, CommandArgKey) + if v, ok := args[OutputArgKey]; ok { + if !(v == valid.PostProcessRunOutputShow || v == valid.PostProcessRunOutputHide || v == valid.PostProcessRunOutputStripRefreshing) { + return fmt.Errorf("run step %q option must be one of %q, %q, or %q", OutputArgKey, valid.PostProcessRunOutputShow, valid.PostProcessRunOutputHide, valid.PostProcessRunOutputStripRefreshing) + } + } + delete(args, OutputArgKey) + if len(args) > 0 { + var argKeys []string + for k := range args { + argKeys = append(argKeys, k) + } + // Sort so tests can be deterministic. + sort.Strings(argKeys) + return fmt.Errorf("run steps only support keys %q, %q and %q, found extra keys %q", RunStepName, CommandArgKey, OutputArgKey, strings.Join(argKeys, ",")) + } + default: + return fmt.Errorf("%q is not a valid step type", stepName) } + return nil } @@ -214,8 +251,8 @@ func (s Step) Validate() error { if len(s.Map) > 0 { return validation.Validate(s.Map, validation.By(extraArgs)) } - if len(s.Env) > 0 { - return validation.Validate(s.Env, validation.By(envStep)) + if len(s.EnvOrRun) > 0 { + return validation.Validate(s.EnvOrRun, validation.By(envOrRunStep)) } if len(s.StringVal) > 0 { return validation.Validate(s.StringVal, validation.By(runStep)) @@ -232,16 +269,21 @@ func (s Step) ToValid() valid.Step { } // This will trigger in case #2 (see Step docs). - if len(s.Env) > 0 { + if len(s.EnvOrRun) > 0 { // After validation we assume there's only one key and it's a valid // step name so we just use the first one. - for stepName, stepArgs := range s.Env { - return valid.Step{ + for stepName, stepArgs := range s.EnvOrRun { + step := valid.Step{ StepName: stepName, EnvVarName: stepArgs[NameArgKey], RunCommand: stepArgs[CommandArgKey], EnvVarValue: stepArgs[ValueArgKey], + Output: valid.PostProcessRunOutputOption(stepArgs[OutputArgKey]), + } + if step.StepName == RunStepName && step.Output == "" { + step.Output = valid.PostProcessRunOutputShow } + return step } } @@ -314,7 +356,7 @@ func (s *Step) unmarshalGeneric(unmarshal func(interface{}) error) error { var envStep map[string]map[string]string err = unmarshal(&envStep) if err == nil { - s.Env = envStep + s.EnvOrRun = envStep return nil } @@ -337,8 +379,8 @@ func (s Step) marshalGeneric() (interface{}, error) { return s.StringVal, nil } else if len(s.Map) != 0 { return s.Map, nil - } else if len(s.Env) != 0 { - return s.Env, nil + } else if len(s.EnvOrRun) != 0 { + return s.EnvOrRun, nil } else if s.Key != nil { return s.Key, nil } diff --git a/server/core/config/raw/step_test.go b/server/core/config/raw/step_test.go index 3321dce360..215169d68c 100644 --- a/server/core/config/raw/step_test.go +++ b/server/core/config/raw/step_test.go @@ -81,7 +81,7 @@ env: value: direct_value name: test`, exp: raw.Step{ - Env: EnvType{ + EnvOrRun: EnvOrRunType{ "env": { "value": "direct_value", "name": "test", @@ -96,7 +96,7 @@ env: command: echo 123 name: test`, exp: raw.Step{ - Env: EnvType{ + EnvOrRun: EnvOrRunType{ "env": { "command": "echo 123", "name": "test", @@ -137,7 +137,7 @@ key: value`, Key: nil, Map: nil, StringVal: nil, - Env: nil, + EnvOrRun: nil, }, }, @@ -227,7 +227,7 @@ func TestStep_Validate(t *testing.T) { { description: "env", input: raw.Step{ - Env: EnvType{ + EnvOrRun: EnvOrRunType{ "env": { "name": "test", "command": "echo 123", @@ -283,7 +283,7 @@ func TestStep_Validate(t *testing.T) { { description: "multiple keys in env", input: raw.Step{ - Env: EnvType{ + EnvOrRun: EnvOrRunType{ "key1": nil, "key2": nil, }, @@ -312,7 +312,7 @@ func TestStep_Validate(t *testing.T) { { description: "invalid key in env", input: raw.Step{ - Env: EnvType{ + EnvOrRun: EnvOrRunType{ "invalid": nil, }, }, @@ -353,7 +353,7 @@ func TestStep_Validate(t *testing.T) { { description: "env step with no name key set", input: raw.Step{ - Env: EnvType{ + EnvOrRun: EnvOrRunType{ "env": { "value": "value", }, @@ -364,7 +364,7 @@ func TestStep_Validate(t *testing.T) { { description: "env step with invalid key", input: raw.Step{ - Env: EnvType{ + EnvOrRun: EnvOrRunType{ "env": { "abc": "", "invalid2": "", @@ -376,7 +376,7 @@ func TestStep_Validate(t *testing.T) { { description: "env step with both command and value set", input: raw.Step{ - Env: EnvType{ + EnvOrRun: EnvOrRunType{ "env": { "name": "name", "command": "command", @@ -454,7 +454,7 @@ func TestStep_ToValid(t *testing.T) { { description: "env step", input: raw.Step{ - Env: EnvType{ + EnvOrRun: EnvOrRunType{ "env": { "name": "test", "command": "echo 123", @@ -558,6 +558,22 @@ func TestStep_ToValid(t *testing.T) { RunCommand: "my 'run command'", }, }, + { + description: "run step with output", + input: raw.Step{ + EnvOrRun: EnvOrRunType{ + "run": { + "command": "my 'run command'", + "output": "hide", + }, + }, + }, + exp: valid.Step{ + StepName: "run", + RunCommand: "my 'run command'", + Output: "hide", + }, + }, } for _, c := range cases { t.Run(c.description, func(t *testing.T) { @@ -567,4 +583,4 @@ func TestStep_ToValid(t *testing.T) { } type MapType map[string]map[string][]string -type EnvType map[string]map[string]string +type EnvOrRunType map[string]map[string]string diff --git a/server/core/config/valid/repo_cfg.go b/server/core/config/valid/repo_cfg.go index 608a92e910..ec55773646 100644 --- a/server/core/config/valid/repo_cfg.go +++ b/server/core/config/valid/repo_cfg.go @@ -150,6 +150,15 @@ type Autoplan struct { Enabled bool } +// PostProcessRunOutputOption is an enum of options for post-processing RunCommand output +type PostProcessRunOutputOption string + +const ( + PostProcessRunOutputShow = "show" + PostProcessRunOutputHide = "hide" + PostProcessRunOutputStripRefreshing = "strip_refreshing" +) + type Stage struct { Steps []Step } @@ -160,6 +169,8 @@ type Step struct { // RunCommand is either a custom run step or the command to run // during an env step to populate the environment variable dynamically. RunCommand string + // Output is option for post-processing a RunCommand output + Output PostProcessRunOutputOption // EnvVarName is the name of the // environment variable that should be set by this step. EnvVarName string diff --git a/server/core/runtime/env_step_runner.go b/server/core/runtime/env_step_runner.go index 6eced91ad1..eb6556c182 100644 --- a/server/core/runtime/env_step_runner.go +++ b/server/core/runtime/env_step_runner.go @@ -3,6 +3,7 @@ package runtime import ( "strings" + "github.com/runatlantis/atlantis/server/core/config/valid" "github.com/runatlantis/atlantis/server/events/command" ) @@ -20,7 +21,7 @@ func (r *EnvStepRunner) Run(ctx command.ProjectContext, command string, value st } // Pass `false` for streamOutput because this isn't interesting to the user reading the build logs // in the web UI. - res, err := r.RunStepRunner.Run(ctx, command, path, envs, false) + res, err := r.RunStepRunner.Run(ctx, command, path, envs, false, valid.PostProcessRunOutputShow) // Trim newline from res to support running `echo env_value` which has // a newline. We don't recommend users run echo -n env_value to remove the // newline because -n doesn't work in the sh shell which is what we use diff --git a/server/core/runtime/multienv_step_runner.go b/server/core/runtime/multienv_step_runner.go index 774d047512..be4ac7ee43 100644 --- a/server/core/runtime/multienv_step_runner.go +++ b/server/core/runtime/multienv_step_runner.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + "github.com/runatlantis/atlantis/server/core/config/valid" "github.com/runatlantis/atlantis/server/events/command" ) @@ -15,7 +16,7 @@ type MultiEnvStepRunner struct { // Run runs the multienv step command. // The command must return a json string containing the array of name-value pairs that are being added as extra environment variables func (r *MultiEnvStepRunner) Run(ctx command.ProjectContext, command string, path string, envs map[string]string) (string, error) { - res, err := r.RunStepRunner.Run(ctx, command, path, envs, false) + res, err := r.RunStepRunner.Run(ctx, command, path, envs, false, valid.PostProcessRunOutputShow) if err == nil { if len(res) > 0 { var sb strings.Builder diff --git a/server/core/runtime/run_step_runner.go b/server/core/runtime/run_step_runner.go index 6d40050429..32b62f2cc4 100644 --- a/server/core/runtime/run_step_runner.go +++ b/server/core/runtime/run_step_runner.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/hashicorp/go-version" + "github.com/runatlantis/atlantis/server/core/config/valid" "github.com/runatlantis/atlantis/server/core/runtime/models" "github.com/runatlantis/atlantis/server/events/command" "github.com/runatlantis/atlantis/server/jobs" @@ -21,7 +22,7 @@ type RunStepRunner struct { ProjectCmdOutputHandler jobs.ProjectCommandOutputHandler } -func (r *RunStepRunner) Run(ctx command.ProjectContext, command string, path string, envs map[string]string, streamOutput bool) (string, error) { +func (r *RunStepRunner) Run(ctx command.ProjectContext, command string, path string, envs map[string]string, streamOutput bool, postProcessOutput valid.PostProcessRunOutputOption) (string, error) { tfVersion := r.DefaultTFVersion if ctx.TerraformVersion != nil { tfVersion = ctx.TerraformVersion @@ -75,5 +76,15 @@ func (r *RunStepRunner) Run(ctx command.ProjectContext, command string, path str ctx.Log.Debug("error: %s", err) return "", err } - return output, nil + + switch postProcessOutput { + case valid.PostProcessRunOutputHide: + return "", nil + case valid.PostProcessRunOutputStripRefreshing: + return StripRefreshingFromPlanOutput(output, tfVersion), nil + case valid.PostProcessRunOutputShow: + return output, nil + default: + return output, nil + } } diff --git a/server/core/runtime/run_step_runner_test.go b/server/core/runtime/run_step_runner_test.go index 54774c91a0..d011254a09 100644 --- a/server/core/runtime/run_step_runner_test.go +++ b/server/core/runtime/run_step_runner_test.go @@ -8,6 +8,7 @@ import ( "github.com/hashicorp/go-version" . "github.com/petergtz/pegomock/v4" + "github.com/runatlantis/atlantis/server/core/config/valid" "github.com/runatlantis/atlantis/server/core/runtime" "github.com/runatlantis/atlantis/server/core/terraform/mocks" "github.com/runatlantis/atlantis/server/events/command" @@ -144,7 +145,7 @@ func TestRunStepRunner_Run(t *testing.T) { ProjectName: c.ProjectName, EscapedCommentArgs: []string{"-target=resource1", "-target=resource2"}, } - out, err := r.Run(ctx, c.Command, tmpDir, map[string]string{"test": "var"}, true) + out, err := r.Run(ctx, c.Command, tmpDir, map[string]string{"test": "var"}, true, valid.PostProcessRunOutputShow) if c.ExpErr != "" { ErrContains(t, c.ExpErr, err) return diff --git a/server/events/mocks/mock_custom_step_runner.go b/server/events/mocks/mock_custom_step_runner.go index 02a5a04fc8..8805706322 100644 --- a/server/events/mocks/mock_custom_step_runner.go +++ b/server/events/mocks/mock_custom_step_runner.go @@ -5,6 +5,7 @@ package mocks import ( pegomock "github.com/petergtz/pegomock/v4" + valid "github.com/runatlantis/atlantis/server/core/config/valid" command "github.com/runatlantis/atlantis/server/events/command" "reflect" "time" @@ -25,11 +26,11 @@ func NewMockCustomStepRunner(options ...pegomock.Option) *MockCustomStepRunner { func (mock *MockCustomStepRunner) SetFailHandler(fh pegomock.FailHandler) { mock.fail = fh } func (mock *MockCustomStepRunner) FailHandler() pegomock.FailHandler { return mock.fail } -func (mock *MockCustomStepRunner) Run(ctx command.ProjectContext, cmd string, path string, envs map[string]string, streamOutput bool) (string, error) { +func (mock *MockCustomStepRunner) Run(ctx command.ProjectContext, cmd string, path string, envs map[string]string, streamOutput bool, postProcessOutput valid.PostProcessRunOutputOption) (string, error) { if mock == nil { panic("mock must not be nil. Use myMock := NewMockCustomStepRunner().") } - params := []pegomock.Param{ctx, cmd, path, envs, streamOutput} + params := []pegomock.Param{ctx, cmd, path, envs, streamOutput, postProcessOutput} result := pegomock.GetGenericMockFrom(mock).Invoke("Run", params, []reflect.Type{reflect.TypeOf((*string)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()}) var ret0 string var ret1 error @@ -81,8 +82,8 @@ type VerifierMockCustomStepRunner struct { timeout time.Duration } -func (verifier *VerifierMockCustomStepRunner) Run(ctx command.ProjectContext, cmd string, path string, envs map[string]string, streamOutput bool) *MockCustomStepRunner_Run_OngoingVerification { - params := []pegomock.Param{ctx, cmd, path, envs, streamOutput} +func (verifier *VerifierMockCustomStepRunner) Run(ctx command.ProjectContext, cmd string, path string, envs map[string]string, streamOutput bool, postProcessOutput valid.PostProcessRunOutputOption) *MockCustomStepRunner_Run_OngoingVerification { + params := []pegomock.Param{ctx, cmd, path, envs, streamOutput, postProcessOutput} methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Run", params, verifier.timeout) return &MockCustomStepRunner_Run_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } @@ -92,12 +93,12 @@ type MockCustomStepRunner_Run_OngoingVerification struct { methodInvocations []pegomock.MethodInvocation } -func (c *MockCustomStepRunner_Run_OngoingVerification) GetCapturedArguments() (command.ProjectContext, string, string, map[string]string, bool) { - ctx, cmd, path, envs, streamOutput := c.GetAllCapturedArguments() - return ctx[len(ctx)-1], cmd[len(cmd)-1], path[len(path)-1], envs[len(envs)-1], streamOutput[len(streamOutput)-1] +func (c *MockCustomStepRunner_Run_OngoingVerification) GetCapturedArguments() (command.ProjectContext, string, string, map[string]string, bool, valid.PostProcessRunOutputOption) { + ctx, cmd, path, envs, streamOutput, postProcessOutput := c.GetAllCapturedArguments() + return ctx[len(ctx)-1], cmd[len(cmd)-1], path[len(path)-1], envs[len(envs)-1], streamOutput[len(streamOutput)-1], postProcessOutput[len(postProcessOutput)-1] } -func (c *MockCustomStepRunner_Run_OngoingVerification) GetAllCapturedArguments() (_param0 []command.ProjectContext, _param1 []string, _param2 []string, _param3 []map[string]string, _param4 []bool) { +func (c *MockCustomStepRunner_Run_OngoingVerification) GetAllCapturedArguments() (_param0 []command.ProjectContext, _param1 []string, _param2 []string, _param3 []map[string]string, _param4 []bool, _param5 []valid.PostProcessRunOutputOption) { params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) if len(params) > 0 { _param0 = make([]command.ProjectContext, len(c.methodInvocations)) @@ -120,6 +121,10 @@ func (c *MockCustomStepRunner_Run_OngoingVerification) GetAllCapturedArguments() for u, param := range params[4] { _param4[u] = param.(bool) } + _param5 = make([]valid.PostProcessRunOutputOption, len(c.methodInvocations)) + for u, param := range params[5] { + _param5[u] = param.(valid.PostProcessRunOutputOption) + } } return } diff --git a/server/events/project_command_runner.go b/server/events/project_command_runner.go index 9e74427b63..acd859f735 100644 --- a/server/events/project_command_runner.go +++ b/server/events/project_command_runner.go @@ -14,13 +14,12 @@ package events import ( + "encoding/json" "fmt" "os" "path/filepath" "strings" - "encoding/json" - "github.com/hashicorp/go-multierror" "github.com/pkg/errors" "github.com/runatlantis/atlantis/server/core/config/valid" @@ -66,7 +65,7 @@ type StepRunner interface { // CustomStepRunner runs custom run steps. type CustomStepRunner interface { // Run cmd in path. - Run(ctx command.ProjectContext, cmd string, path string, envs map[string]string, streamOutput bool) (string, error) + Run(ctx command.ProjectContext, cmd string, path string, envs map[string]string, streamOutput bool, postProcessOutput valid.PostProcessRunOutputOption) (string, error) } //go:generate pegomock generate --package mocks -o mocks/mock_env_step_runner.go EnvStepRunner @@ -764,7 +763,7 @@ func (p *DefaultProjectCommandRunner) runSteps(steps []valid.Step, ctx command.P case "state_rm": out, err = p.StateRmStepRunner.Run(ctx, step.ExtraArgs, absPath, envs) case "run": - out, err = p.RunStepRunner.Run(ctx, step.RunCommand, absPath, envs, true) + out, err = p.RunStepRunner.Run(ctx, step.RunCommand, absPath, envs, true, step.Output) case "env": out, err = p.EnvStepRunner.Run(ctx, step.RunCommand, step.EnvVarValue, absPath, envs) envs[step.EnvVarName] = out diff --git a/server/events/project_command_runner_test.go b/server/events/project_command_runner_test.go index 1d2224c50a..88aa4df14c 100644 --- a/server/events/project_command_runner_test.go +++ b/server/events/project_command_runner_test.go @@ -112,7 +112,7 @@ func TestDefaultProjectCommandRunner_Plan(t *testing.T) { When(mockInit.Run(ctx, nil, repoDir, expEnvs)).ThenReturn("init", nil) When(mockPlan.Run(ctx, nil, repoDir, expEnvs)).ThenReturn("plan", nil) When(mockApply.Run(ctx, nil, repoDir, expEnvs)).ThenReturn("apply", nil) - When(mockRun.Run(ctx, "", repoDir, expEnvs, true)).ThenReturn("run", nil) + When(mockRun.Run(ctx, "", repoDir, expEnvs, true, "")).ThenReturn("run", nil) res := runner.Plan(ctx) Assert(t, res.PlanSuccess != nil, "exp plan success") @@ -128,7 +128,7 @@ func TestDefaultProjectCommandRunner_Plan(t *testing.T) { case "apply": mockApply.VerifyWasCalledOnce().Run(ctx, nil, repoDir, expEnvs) case "run": - mockRun.VerifyWasCalledOnce().Run(ctx, "", repoDir, expEnvs, true) + mockRun.VerifyWasCalledOnce().Run(ctx, "", repoDir, expEnvs, true, "") } } } @@ -457,7 +457,7 @@ func TestDefaultProjectCommandRunner_Apply(t *testing.T) { When(mockInit.Run(ctx, nil, repoDir, expEnvs)).ThenReturn("init", nil) When(mockPlan.Run(ctx, nil, repoDir, expEnvs)).ThenReturn("plan", nil) When(mockApply.Run(ctx, nil, repoDir, expEnvs)).ThenReturn("apply", nil) - When(mockRun.Run(ctx, "", repoDir, expEnvs, true)).ThenReturn("run", nil) + When(mockRun.Run(ctx, "", repoDir, expEnvs, true, "")).ThenReturn("run", nil) When(mockEnv.Run(ctx, "", "value", repoDir, make(map[string]string))).ThenReturn("value", nil) res := runner.Apply(ctx) @@ -473,7 +473,7 @@ func TestDefaultProjectCommandRunner_Apply(t *testing.T) { case "apply": mockApply.VerifyWasCalledOnce().Run(ctx, nil, repoDir, expEnvs) case "run": - mockRun.VerifyWasCalledOnce().Run(ctx, "", repoDir, expEnvs, true) + mockRun.VerifyWasCalledOnce().Run(ctx, "", repoDir, expEnvs, true, "") case "env": mockEnv.VerifyWasCalledOnce().Run(ctx, "", "value", repoDir, expEnvs) }