Skip to content

Commit

Permalink
Add COMMENT_ARGS to pre/post-workflow hook execution environment (run…
Browse files Browse the repository at this point in the history
  • Loading branch information
adam-verigin authored and krrrr38 committed Dec 16, 2022
1 parent 66db70e commit c968ed5
Show file tree
Hide file tree
Showing 13 changed files with 162 additions and 51 deletions.
2 changes: 2 additions & 0 deletions runatlantis.io/docs/post-workflow-hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,6 @@ command](custom-workflows.html#custom-run-command).
* `PULL_AUTHOR` - Username of the pull request author, ex. `acme-user`.
* `DIR` - The absolute path to the root of the cloned repository.
* `USER_NAME` - Username of the VCS user running command, ex. `acme-user`. During an autoplan, the user will be the Atlantis API user, ex. `atlantis`.
* `COMMENT_ARGS` - Any additional flags passed in the comment on the pull request. Flags are separated by commas and
every character is escaped, ex. `atlantis plan -- arg1 arg2` will result in `COMMENT_ARGS=\a\r\g\1,\a\r\g\2`.
:::
2 changes: 2 additions & 0 deletions runatlantis.io/docs/pre-workflow-hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,7 @@ command](custom-workflows.html#custom-run-command).
* `PULL_AUTHOR` - Username of the pull request author, ex. `acme-user`.
* `DIR` - The absolute path to the root of the cloned repository.
* `USER_NAME` - Username of the VCS user running command, ex. `acme-user`. During an autoplan, the user will be the Atlantis API user, ex. `atlantis`.
* `COMMENT_ARGS` - Any additional flags passed in the comment on the pull request. Flags are separated by commas and
every character is escaped, ex. `atlantis plan -- arg1 arg2` will result in `COMMENT_ARGS=\a\r\g\1,\a\r\g\2`.
:::

2 changes: 2 additions & 0 deletions server/core/runtime/post_workflow_hook_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"os"
"os/exec"
"strings"

"github.com/runatlantis/atlantis/server/events/models"
)
Expand All @@ -24,6 +25,7 @@ func (wh DefaultPostWorkflowHookRunner) Run(ctx models.WorkflowHookCommandContex
"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,
Expand Down
2 changes: 2 additions & 0 deletions server/core/runtime/pre_workflow_hook_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"os"
"os/exec"
"strings"

"github.com/runatlantis/atlantis/server/events/models"
)
Expand All @@ -24,6 +25,7 @@ func (wh DefaultPreWorkflowHookRunner) Run(ctx models.WorkflowHookCommandContext
"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,
Expand Down
8 changes: 4 additions & 4 deletions server/events/command_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ func (c *DefaultCommandRunner) RunAutoplanCommand(baseRepo models.Repo, headRepo
return
}

err = c.PreWorkflowHooksCommandRunner.RunPreHooks(ctx)
err = c.PreWorkflowHooksCommandRunner.RunPreHooks(ctx, nil)

if err != nil {
ctx.Log.Err("Error running pre-workflow hooks %s. Proceeding with %s command.", err, command.Plan)
Expand All @@ -173,7 +173,7 @@ func (c *DefaultCommandRunner) RunAutoplanCommand(baseRepo models.Repo, headRepo

autoPlanRunner.Run(ctx, nil)

err = c.PostWorkflowHooksCommandRunner.RunPostHooks(ctx)
err = c.PostWorkflowHooksCommandRunner.RunPostHooks(ctx, nil)

if err != nil {
ctx.Log.Err("Error running post-workflow hooks %s.", err)
Expand Down Expand Up @@ -285,7 +285,7 @@ func (c *DefaultCommandRunner) RunCommentCommand(baseRepo models.Repo, maybeHead
return
}

err = c.PreWorkflowHooksCommandRunner.RunPreHooks(ctx)
err = c.PreWorkflowHooksCommandRunner.RunPreHooks(ctx, cmd)

if err != nil {
ctx.Log.Err("Error running pre-workflow hooks %s. Proceeding with %s command.", err, cmd.Name.String())
Expand All @@ -295,7 +295,7 @@ func (c *DefaultCommandRunner) RunCommentCommand(baseRepo models.Repo, maybeHead

cmdRunner.Run(ctx, cmd)

err = c.PostWorkflowHooksCommandRunner.RunPostHooks(ctx)
err = c.PostWorkflowHooksCommandRunner.RunPostHooks(ctx, cmd)

if err != nil {
ctx.Log.Err("Error running post-workflow hooks %s.", err)
Expand Down
4 changes: 2 additions & 2 deletions server/events/command_runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,11 +193,11 @@ func setup(t *testing.T) *vcsmocks.MockClient {

preWorkflowHooksCommandRunner = mocks.NewMockPreWorkflowHooksCommandRunner()

When(preWorkflowHooksCommandRunner.RunPreHooks(matchers.AnyPtrToEventsCommandContext())).ThenReturn(nil)
When(preWorkflowHooksCommandRunner.RunPreHooks(matchers.AnyPtrToEventsCommandContext(), matchers.AnyPtrToEventsCommentCommand())).ThenReturn(nil)

postWorkflowHooksCommandRunner = mocks.NewMockPostWorkflowHooksCommandRunner()

When(postWorkflowHooksCommandRunner.RunPostHooks(matchers.AnyPtrToEventsCommandContext())).ThenReturn(nil)
When(postWorkflowHooksCommandRunner.RunPostHooks(matchers.AnyPtrToEventsCommandContext(), matchers.AnyPtrToEventsCommentCommand())).ThenReturn(nil)

globalCfg := valid.NewGlobalCfgFromArgs(valid.GlobalCfgArgs{})
scope, _, _ := metrics.NewLoggingScope(logger, "atlantis")
Expand Down
23 changes: 14 additions & 9 deletions server/events/mocks/mock_post_workflows_hooks_command_runner.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 13 additions & 8 deletions server/events/mocks/mock_pre_workflows_hooks_command_runner.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions server/events/models/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -510,4 +510,9 @@ type WorkflowHookCommandContext struct {
User User
// Verbose is true when the user would like verbose output.
Verbose bool
// EscapedCommentArgs are the extra arguments that were added to the atlantis
// command, ex. atlantis plan -- -target=resource. We then escape them
// by adding a \ before each character so that they can be used within
// sh -c safely, i.e. sh -c "terraform plan $(touch bad)".
EscapedCommentArgs []string
}
22 changes: 14 additions & 8 deletions server/events/post_workflow_hooks_command_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
//go:generate pegomock generate -m --use-experimental-model-gen --package mocks -o mocks/mock_post_workflows_hooks_command_runner.go PostWorkflowHooksCommandRunner

type PostWorkflowHooksCommandRunner interface {
RunPostHooks(ctx *command.Context) error
RunPostHooks(ctx *command.Context, cmd *CommentCommand) error
}

// DefaultPostWorkflowHooksCommandRunner is the first step when processing a workflow hook commands.
Expand All @@ -25,7 +25,7 @@ type DefaultPostWorkflowHooksCommandRunner struct {

// RunPostHooks runs post_workflow_hooks after a plan/apply has completed
func (w *DefaultPostWorkflowHooksCommandRunner) RunPostHooks(
ctx *command.Context,
ctx *command.Context, cmd *CommentCommand,
) error {
pull := ctx.Pull
baseRepo := pull.BaseRepo
Expand Down Expand Up @@ -59,14 +59,20 @@ func (w *DefaultPostWorkflowHooksCommandRunner) RunPostHooks(
return err
}

var escapedArgs []string
if cmd != nil {
escapedArgs = escapeArgs(cmd.Flags)
}

err = w.runHooks(
models.WorkflowHookCommandContext{
BaseRepo: baseRepo,
HeadRepo: headRepo,
Log: log,
Pull: pull,
User: user,
Verbose: false,
BaseRepo: baseRepo,
HeadRepo: headRepo,
Log: log,
Pull: pull,
User: user,
Verbose: false,
EscapedCommentArgs: escapedArgs,
},
postWorkflowHooks, repoDir)

Expand Down
49 changes: 44 additions & 5 deletions server/events/post_workflow_hooks_command_runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func TestRunPostHooks_Clone(t *testing.T) {
When(postWhWorkingDir.Clone(log, fixtures.GithubRepo, newPull, events.DefaultWorkspace)).ThenReturn(repoDir, false, nil)
When(whPostWorkflowHookRunner.Run(pCtx, testHook.RunCommand, repoDir)).ThenReturn(result, nil)

err := postWh.RunPostHooks(ctx)
err := postWh.RunPostHooks(ctx, nil)

Ok(t, err)
whPostWorkflowHookRunner.VerifyWasCalledOnce().Run(pCtx, testHook.RunCommand, repoDir)
Expand All @@ -121,7 +121,7 @@ func TestRunPostHooks_Clone(t *testing.T) {

postWh.GlobalCfg = globalCfg

err := postWh.RunPostHooks(ctx)
err := postWh.RunPostHooks(ctx, nil)

Ok(t, err)

Expand All @@ -147,7 +147,7 @@ func TestRunPostHooks_Clone(t *testing.T) {

When(postWhWorkingDirLocker.TryLock(fixtures.GithubRepo.FullName, newPull.Num, events.DefaultWorkspace, events.DefaultRepoRelDir)).ThenReturn(func() {}, errors.New("some error"))

err := postWh.RunPostHooks(ctx)
err := postWh.RunPostHooks(ctx, nil)

Assert(t, err != nil, "error not nil")
postWhWorkingDir.VerifyWasCalled(Never()).Clone(log, fixtures.GithubRepo, newPull, events.DefaultWorkspace)
Expand Down Expand Up @@ -178,7 +178,7 @@ func TestRunPostHooks_Clone(t *testing.T) {
When(postWhWorkingDirLocker.TryLock(fixtures.GithubRepo.FullName, newPull.Num, events.DefaultWorkspace, events.DefaultRepoRelDir)).ThenReturn(unlockFn, nil)
When(postWhWorkingDir.Clone(log, fixtures.GithubRepo, newPull, events.DefaultWorkspace)).ThenReturn(repoDir, false, errors.New("some error"))

err := postWh.RunPostHooks(ctx)
err := postWh.RunPostHooks(ctx, nil)

Assert(t, err != nil, "error not nil")

Expand Down Expand Up @@ -211,9 +211,48 @@ func TestRunPostHooks_Clone(t *testing.T) {
When(postWhWorkingDir.Clone(log, fixtures.GithubRepo, newPull, events.DefaultWorkspace)).ThenReturn(repoDir, false, nil)
When(whPostWorkflowHookRunner.Run(pCtx, testHook.RunCommand, repoDir)).ThenReturn(result, errors.New("some error"))

err := postWh.RunPostHooks(ctx)
err := postWh.RunPostHooks(ctx, nil)

Assert(t, err != nil, "error not nil")
Assert(t, *unlockCalled == true, "unlock function called")
})

t.Run("comment args passed to webhooks", func(t *testing.T) {
postWorkflowHooksSetup(t)

unlockCalled := newBool(false)
unlockFn := func() {
unlockCalled = newBool(true)
}

globalCfg := valid.GlobalCfg{
Repos: []valid.Repo{
{
ID: fixtures.GithubRepo.ID(),
PostWorkflowHooks: []*valid.WorkflowHook{
&testHook,
},
},
},
}

cmd := &events.CommentCommand{
Flags: []string{"comment", "args"},
}

expectedCtx := pCtx
expectedCtx.EscapedCommentArgs = []string{"\\c\\o\\m\\m\\e\\n\\t", "\\a\\r\\g\\s"}

postWh.GlobalCfg = globalCfg

When(postWhWorkingDirLocker.TryLock(fixtures.GithubRepo.FullName, newPull.Num, events.DefaultWorkspace, events.DefaultRepoRelDir)).ThenReturn(unlockFn, nil)
When(postWhWorkingDir.Clone(log, fixtures.GithubRepo, newPull, events.DefaultWorkspace)).ThenReturn(repoDir, false, nil)
When(whPostWorkflowHookRunner.Run(pCtx, testHook.RunCommand, repoDir)).ThenReturn(result, nil)

err := postWh.RunPostHooks(ctx, cmd)

Ok(t, err)
whPostWorkflowHookRunner.VerifyWasCalledOnce().Run(expectedCtx, testHook.RunCommand, repoDir)
Assert(t, *unlockCalled == true, "unlock function called")
})
}
Loading

0 comments on commit c968ed5

Please sign in to comment.