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)
}