Files
atlantis/server/core/runtime/run_step_runner.go
Aiden Scandella ff1094fa04 feat: stream output for custom workflows (#2261)
* Start threading job output to RunStepRunner

* Strip ANSI

* Fix lint

* Use waitgroup to avoid test flakiness

* Move waitgroup higher

* Add ANSI test and use strings.Builder

* Fix lint

* Use errors.Wrap per style guide

* Create ShellCommandRunner to encapsulate streaming

* WIP: shell command runner

* Update signatures to propagate error finding version

* Fix log output

* Fix error checking

* Fix accidental whitespace stripping

* Remove unused struct field

* Fix error checking in terraform client

* Add unit tests to verify command output handler was called

* Remove err from async interface

* Remove duplicative log now that shell command runner does it

* Hide output in stream for env/multienv

* Add comment explaining goroutines

* Use printf for better macOS compatibility
2022-06-22 09:29:41 -07:00

78 lines
2.7 KiB
Go

package runtime
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/hashicorp/go-version"
"github.com/runatlantis/atlantis/server/core/runtime/models"
"github.com/runatlantis/atlantis/server/events/command"
"github.com/runatlantis/atlantis/server/jobs"
)
// RunStepRunner runs custom commands.
type RunStepRunner struct {
TerraformExecutor TerraformExec
DefaultTFVersion *version.Version
// TerraformBinDir is the directory where Atlantis downloads Terraform binaries.
TerraformBinDir string
ProjectCmdOutputHandler jobs.ProjectCommandOutputHandler
}
func (r *RunStepRunner) Run(ctx command.ProjectContext, command string, path string, envs map[string]string, streamOutput bool) (string, error) {
tfVersion := r.DefaultTFVersion
if ctx.TerraformVersion != nil {
tfVersion = ctx.TerraformVersion
}
err := r.TerraformExecutor.EnsureVersion(ctx.Log, tfVersion)
if err != nil {
err = fmt.Errorf("%s: Downloading terraform Version %s", err, tfVersion.String())
ctx.Log.Debug("error: %s", err)
return "", err
}
baseEnvVars := os.Environ()
customEnvVars := map[string]string{
"ATLANTIS_TERRAFORM_VERSION": tfVersion.String(),
"BASE_BRANCH_NAME": ctx.Pull.BaseBranch,
"BASE_REPO_NAME": ctx.BaseRepo.Name,
"BASE_REPO_OWNER": ctx.BaseRepo.Owner,
"COMMENT_ARGS": strings.Join(ctx.EscapedCommentArgs, ","),
"DIR": path,
"HEAD_BRANCH_NAME": ctx.Pull.HeadBranch,
"HEAD_COMMIT": ctx.Pull.HeadCommit,
"HEAD_REPO_NAME": ctx.HeadRepo.Name,
"HEAD_REPO_OWNER": ctx.HeadRepo.Owner,
"PATH": fmt.Sprintf("%s:%s", os.Getenv("PATH"), r.TerraformBinDir),
"PLANFILE": filepath.Join(path, GetPlanFilename(ctx.Workspace, ctx.ProjectName)),
"SHOWFILE": filepath.Join(path, ctx.GetShowResultFileName()),
"PROJECT_NAME": ctx.ProjectName,
"PULL_AUTHOR": ctx.Pull.Author,
"PULL_NUM": fmt.Sprintf("%d", ctx.Pull.Num),
"REPO_REL_DIR": ctx.RepoRelDir,
"USER_NAME": ctx.User.Username,
"WORKSPACE": ctx.Workspace,
}
finalEnvVars := baseEnvVars
for key, val := range customEnvVars {
finalEnvVars = append(finalEnvVars, fmt.Sprintf("%s=%s", key, val))
}
for key, val := range envs {
finalEnvVars = append(finalEnvVars, fmt.Sprintf("%s=%s", key, val))
}
runner := models.NewShellCommandRunner(command, finalEnvVars, path, streamOutput, r.ProjectCmdOutputHandler)
output, err := runner.Run(ctx)
if err != nil {
err = fmt.Errorf("%s: running %q in %q: \n%s", err, command, path, output)
ctx.Log.Debug("error: %s", err)
return "", err
}
return output, nil
}