feat: Add pre and post workflow hook status (#2441)

* Add pre and post workflow hook status

* fix missing mocks

* fix pre/post workflow hooks tests

* add cmd output to file

* fix typo

* add cmd output to file on pre workflow hooks

* Add hooks output to web UI

* Remove unnecessary dependencies

* Clean the code and make tests work again

* Make lint happy

* Small fixes, create dedicated UUID generator and docs

* Add missing commentary

* Use matchers instead of mocking for tests and fix e2e tests

* Change 'OUTPUT_FILE' to 'OUTPUT_STATUS_FILE'

* Reduce SendWorkflowHook calls on hooks

* Apply suggestions from code review

Co-authored-by: PePe Amengual <jose.amengual@gmail.com>
Co-authored-by: nitrocode <7775707+nitrocode@users.noreply.github.com>
This commit is contained in:
Fabiano Soares Honorato
2022-12-19 17:20:34 -03:00
committed by GitHub
parent 36686597b8
commit cb485f11ee
45 changed files with 1428 additions and 264 deletions

View File

@@ -6,7 +6,7 @@ workflows](custom-workflows.html#custom-run-command) in that they are run
outside of Atlantis commands. Which means they do not surface their output
back to the PR as a comment.
Post workflow hooks also only allow `run` commands.
Post workflow hooks also only allow `run` and `description` commands.
[[toc]]
@@ -40,6 +40,7 @@ repos:
workflow: myworkflow
post_workflow_hooks:
- run: infracost output --path=/tmp/$BASE_REPO_OWNER-$BASE_REPO_NAME-$PULL_NUM-*-infracost.json --format=github-comment --out-file=/tmp/infracost-comment.md
description: Running infracost
# Now report the output as desired, e.g. post to GitHub as a comment.
# ...
```
@@ -55,9 +56,10 @@ command](custom-workflows.html#custom-run-command).
- run: custom-command
```
| Key | Type | Default | Required | Description |
| --- | ------ | ------- | -------- | -------------------- |
| run | string | none | no | Run a custom command |
| Key | Type | Default | Required | Description |
| ----------- | ------ | ------- | -------- | --------------------- |
| run | string | none | no | Run a custom command |
| description | string | none | no | Post hook description |
::: tip Notes
* `run` commands are executed with the following environment variables:
@@ -74,4 +76,5 @@ command](custom-workflows.html#custom-run-command).
* `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`.
* `OUTPUT_STATUS_FILE` - An output file to customize the success or failure status. ex. `echo 'failure' > $OUTPUT_STATUS_FILE`.
:::

View File

@@ -8,7 +8,7 @@ workflows](custom-workflows.html#custom-run-command) in several ways.
present. This be utilized to [dynamically generate repo configs](pre-workflow-hooks.html#dynamic-repo-config-generation).
2. Pre workflow hooks are run outside of Atlantis commands. Which means
they do not surface their output back to the PR as a comment.
3. Pre workflow hooks only allow `run` commands.
3. Pre workflow hooks only allow `run` and `description` commands.
[[toc]]
@@ -31,6 +31,7 @@ repos:
- id: /.*/
pre_workflow_hooks:
- run: ./repo-config-generator.sh
description: Generating configs
```
## Reference
### Custom `run` Command
@@ -39,9 +40,10 @@ command](custom-workflows.html#custom-run-command).
```yaml
- run: custom-command
```
| Key | Type | Default | Required | Description |
| --- | ------ | ------- | -------- | -------------------- |
| run | string | none | no | Run a custom command |
| Key | Type | Default | Required | Description |
| ----------- | ------ | ------- | -------- | -------------------- |
| run | string | none | no | Run a custom command |
| description | string | none | no | Pre hook description |
::: tip Notes
* `run` commands are executed with the following environment variables:
@@ -58,5 +60,6 @@ command](custom-workflows.html#custom-run-command).
* `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`.
* `OUTPUT_STATUS_FILE` - An output file to customize the success or failure status. ex. `echo 'failure' > $OUTPUT_STATUS_FILE`.
:::

View File

@@ -966,22 +966,30 @@ func setupE2E(t *testing.T, repoDir, repoConfigFile string) (events_controllers.
parallelPoolSize := 1
silenceNoProjects := false
commitStatusUpdater := mocks.NewMockCommitStatusUpdater()
mockPreWorkflowHookRunner = runtimemocks.NewMockPreWorkflowHookRunner()
preWorkflowHookURLGenerator := mocks.NewMockPreWorkflowHookURLGenerator()
preWorkflowHooksCommandRunner := &events.DefaultPreWorkflowHooksCommandRunner{
VCSClient: e2eVCSClient,
GlobalCfg: globalCfg,
WorkingDirLocker: locker,
WorkingDir: workingDir,
PreWorkflowHookRunner: mockPreWorkflowHookRunner,
CommitStatusUpdater: commitStatusUpdater,
Router: preWorkflowHookURLGenerator,
}
mockPostWorkflowHookRunner = runtimemocks.NewMockPostWorkflowHookRunner()
postWorkflowHookURLGenerator := mocks.NewMockPostWorkflowHookURLGenerator()
postWorkflowHooksCommandRunner := &events.DefaultPostWorkflowHooksCommandRunner{
VCSClient: e2eVCSClient,
GlobalCfg: globalCfg,
WorkingDirLocker: locker,
WorkingDir: workingDir,
PostWorkflowHookRunner: mockPostWorkflowHookRunner,
CommitStatusUpdater: commitStatusUpdater,
Router: postWorkflowHookURLGenerator,
}
statsScope, _, _ := metrics.NewLoggingScope(logger, "atlantis")

View File

@@ -72,13 +72,10 @@ func (s WorkflowHook) Validate() error {
func (s WorkflowHook) ToValid() *valid.WorkflowHook {
// This will trigger in case #4 (see WorkflowHook docs).
if len(s.StringVal) > 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 _, v := range s.StringVal {
return &valid.WorkflowHook{
StepName: RunStepName,
RunCommand: v,
}
return &valid.WorkflowHook{
StepName: RunStepName,
RunCommand: s.StringVal["run"],
StepDescription: s.StringVal["description"],
}
}

View File

@@ -96,8 +96,9 @@ type MergedProjectCfg struct {
// WorkflowHook is a map of custom run commands to run before or after workflows.
type WorkflowHook struct {
StepName string
RunCommand string
StepName string
RunCommand string
StepDescription string
}
// DefaultApplyStage is the Atlantis default apply stage.

View File

@@ -0,0 +1,33 @@
// Code generated by pegomock. DO NOT EDIT.
package matchers
import (
"github.com/petergtz/pegomock"
"reflect"
jobs "github.com/runatlantis/atlantis/server/jobs"
)
func AnyJobsProjectCommandOutputHandler() jobs.ProjectCommandOutputHandler {
pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*(jobs.ProjectCommandOutputHandler))(nil)).Elem()))
var nullValue jobs.ProjectCommandOutputHandler
return nullValue
}
func EqJobsProjectCommandOutputHandler(value jobs.ProjectCommandOutputHandler) jobs.ProjectCommandOutputHandler {
pegomock.RegisterMatcher(&pegomock.EqMatcher{Value: value})
var nullValue jobs.ProjectCommandOutputHandler
return nullValue
}
func NotEqJobsProjectCommandOutputHandler(value jobs.ProjectCommandOutputHandler) jobs.ProjectCommandOutputHandler {
pegomock.RegisterMatcher(&pegomock.NotEqMatcher{Value: value})
var nullValue jobs.ProjectCommandOutputHandler
return nullValue
}
func JobsProjectCommandOutputHandlerThat(matcher pegomock.ArgumentMatcher) jobs.ProjectCommandOutputHandler {
pegomock.RegisterMatcher(matcher)
var nullValue jobs.ProjectCommandOutputHandler
return nullValue
}

View File

@@ -2,9 +2,8 @@
package matchers
import (
"reflect"
"github.com/petergtz/pegomock"
"reflect"
models "github.com/runatlantis/atlantis/server/events/models"
)

View File

@@ -4,11 +4,10 @@
package mocks
import (
"reflect"
"time"
pegomock "github.com/petergtz/pegomock"
models "github.com/runatlantis/atlantis/server/events/models"
"reflect"
"time"
)
type MockPostWorkflowHookRunner struct {
@@ -26,23 +25,27 @@ func NewMockPostWorkflowHookRunner(options ...pegomock.Option) *MockPostWorkflow
func (mock *MockPostWorkflowHookRunner) SetFailHandler(fh pegomock.FailHandler) { mock.fail = fh }
func (mock *MockPostWorkflowHookRunner) FailHandler() pegomock.FailHandler { return mock.fail }
func (mock *MockPostWorkflowHookRunner) Run(ctx models.WorkflowHookCommandContext, command string, path string) (string, error) {
func (mock *MockPostWorkflowHookRunner) Run(ctx models.WorkflowHookCommandContext, command string, path string) (string, string, error) {
if mock == nil {
panic("mock must not be nil. Use myMock := NewMockPostWorkflowHookRunner().")
}
params := []pegomock.Param{ctx, command, path}
result := pegomock.GetGenericMockFrom(mock).Invoke("Run", params, []reflect.Type{reflect.TypeOf((*string)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
result := pegomock.GetGenericMockFrom(mock).Invoke("Run", params, []reflect.Type{reflect.TypeOf((*string)(nil)).Elem(), reflect.TypeOf((*string)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
var ret0 string
var ret1 error
var ret1 string
var ret2 error
if len(result) != 0 {
if result[0] != nil {
ret0 = result[0].(string)
}
if result[1] != nil {
ret1 = result[1].(error)
ret1 = result[1].(string)
}
if result[2] != nil {
ret2 = result[2].(error)
}
}
return ret0, ret1
return ret0, ret1, ret2
}
func (mock *MockPostWorkflowHookRunner) VerifyWasCalledOnce() *VerifierMockPostWorkflowHookRunner {

View File

@@ -4,11 +4,10 @@
package mocks
import (
"reflect"
"time"
pegomock "github.com/petergtz/pegomock"
models "github.com/runatlantis/atlantis/server/events/models"
"reflect"
"time"
)
type MockPreWorkflowHookRunner struct {
@@ -26,23 +25,27 @@ func NewMockPreWorkflowHookRunner(options ...pegomock.Option) *MockPreWorkflowHo
func (mock *MockPreWorkflowHookRunner) SetFailHandler(fh pegomock.FailHandler) { mock.fail = fh }
func (mock *MockPreWorkflowHookRunner) FailHandler() pegomock.FailHandler { return mock.fail }
func (mock *MockPreWorkflowHookRunner) Run(ctx models.WorkflowHookCommandContext, command string, path string) (string, error) {
func (mock *MockPreWorkflowHookRunner) Run(ctx models.WorkflowHookCommandContext, command string, path string) (string, string, error) {
if mock == nil {
panic("mock must not be nil. Use myMock := NewMockPreWorkflowHookRunner().")
}
params := []pegomock.Param{ctx, command, path}
result := pegomock.GetGenericMockFrom(mock).Invoke("Run", params, []reflect.Type{reflect.TypeOf((*string)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
result := pegomock.GetGenericMockFrom(mock).Invoke("Run", params, []reflect.Type{reflect.TypeOf((*string)(nil)).Elem(), reflect.TypeOf((*string)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
var ret0 string
var ret1 error
var ret1 string
var ret2 error
if len(result) != 0 {
if result[0] != nil {
ret0 = result[0].(string)
}
if result[1] != nil {
ret1 = result[1].(error)
ret1 = result[1].(string)
}
if result[2] != nil {
ret2 = result[2].(error)
}
}
return ret0, ret1
return ret0, ret1, ret2
}
func (mock *MockPreWorkflowHookRunner) VerifyWasCalledOnce() *VerifierMockPreWorkflowHookRunner {

View File

@@ -4,36 +4,43 @@ import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/runatlantis/atlantis/server/events/models"
"github.com/runatlantis/atlantis/server/jobs"
)
//go:generate pegomock generate -m --use-experimental-model-gen --package mocks -o mocks/mock_post_workflows_hook_runner.go PostWorkflowHookRunner
type PostWorkflowHookRunner interface {
Run(ctx models.WorkflowHookCommandContext, command string, path string) (string, error)
Run(ctx models.WorkflowHookCommandContext, command string, path string) (string, string, error)
}
type DefaultPostWorkflowHookRunner struct{}
type DefaultPostWorkflowHookRunner struct {
OutputHandler jobs.ProjectCommandOutputHandler
}
func (wh DefaultPostWorkflowHookRunner) Run(ctx models.WorkflowHookCommandContext, command string, path string) (string, string, error) {
outputFilePath := filepath.Join(path, "OUTPUT_STATUS_FILE")
func (wh DefaultPostWorkflowHookRunner) Run(ctx models.WorkflowHookCommandContext, command string, path string) (string, error) {
cmd := exec.Command("sh", "-c", command) // #nosec
cmd.Dir = path
baseEnvVars := os.Environ()
customEnvVars := map[string]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,
"PULL_AUTHOR": ctx.Pull.Author,
"PULL_NUM": fmt.Sprintf("%d", ctx.Pull.Num),
"USER_NAME": ctx.User.Username,
"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,
"PULL_AUTHOR": ctx.Pull.Author,
"PULL_NUM": fmt.Sprintf("%d", ctx.Pull.Num),
"USER_NAME": ctx.User.Username,
"OUTPUT_STATUS_FILE": outputFilePath,
}
finalEnvVars := baseEnvVars
@@ -47,8 +54,24 @@ func (wh DefaultPostWorkflowHookRunner) Run(ctx models.WorkflowHookCommandContex
if err != nil {
err = fmt.Errorf("%s: running %q in %q: \n%s", err, command, path, out)
ctx.Log.Debug("error: %s", err)
return "", err
return "", "", err
}
// Read the value from the "outputFilePath" file
// to be returned as a custom description.
var customStatusOut []byte
if _, err := os.Stat(outputFilePath); err == nil {
var customStatusErr error
customStatusOut, customStatusErr = os.ReadFile(outputFilePath)
if customStatusErr != nil {
err = fmt.Errorf("%s: running %q in %q: \n%s", err, command, path, out)
ctx.Log.Debug("error: %s", err)
return "", "", err
}
}
wh.OutputHandler.SendWorkflowHook(ctx, fmt.Sprintf("%s\n", string(out)), true)
ctx.Log.Info("successfully ran %q in %q", command, path)
return string(out), nil
return string(out), strings.Trim(string(customStatusOut), "\n"), nil
}

View File

@@ -10,15 +10,17 @@ import (
matchers2 "github.com/runatlantis/atlantis/server/core/terraform/mocks/matchers"
"github.com/runatlantis/atlantis/server/events/mocks/matchers"
"github.com/runatlantis/atlantis/server/events/models"
jobmocks "github.com/runatlantis/atlantis/server/jobs/mocks"
"github.com/runatlantis/atlantis/server/logging"
. "github.com/runatlantis/atlantis/testing"
)
func TestPostWorkflowHookRunner_Run(t *testing.T) {
cases := []struct {
Command string
ExpOut string
ExpErr string
Command string
ExpOut string
ExpErr string
ExpDescription string
}{
{
Command: "",
@@ -56,6 +58,10 @@ func TestPostWorkflowHookRunner_Run(t *testing.T) {
Command: "echo user_name=$USER_NAME",
ExpOut: "user_name=acme-user\n",
},
{
Command: "echo something > $OUTPUT_STATUS_FILE",
ExpDescription: "something",
},
}
for _, c := range cases {
@@ -71,7 +77,9 @@ func TestPostWorkflowHookRunner_Run(t *testing.T) {
logger := logging.NewNoopLogger(t)
tmpDir := t.TempDir()
r := runtime.DefaultPostWorkflowHookRunner{}
r := runtime.DefaultPostWorkflowHookRunner{
OutputHandler: jobmocks.NewMockProjectCommandOutputHandler(),
}
t.Run(c.Command, func(t *testing.T) {
ctx := models.WorkflowHookCommandContext{
BaseRepo: models.Repo{
@@ -94,7 +102,7 @@ func TestPostWorkflowHookRunner_Run(t *testing.T) {
},
Log: logger,
}
out, err := r.Run(ctx, c.Command, tmpDir)
out, desc, err := r.Run(ctx, c.Command, tmpDir)
if c.ExpErr != "" {
ErrContains(t, c.ExpErr, err)
return
@@ -105,6 +113,7 @@ func TestPostWorkflowHookRunner_Run(t *testing.T) {
// temp dir.
expOut := strings.Replace(c.ExpOut, "$DIR", tmpDir, -1)
Equals(t, expOut, out)
Equals(t, c.ExpDescription, desc)
})
}
}

View File

@@ -4,36 +4,43 @@ import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/runatlantis/atlantis/server/events/models"
"github.com/runatlantis/atlantis/server/jobs"
)
//go:generate pegomock generate -m --use-experimental-model-gen --package mocks -o mocks/mock_pre_workflows_hook_runner.go PreWorkflowHookRunner
type PreWorkflowHookRunner interface {
Run(ctx models.WorkflowHookCommandContext, command string, path string) (string, error)
Run(ctx models.WorkflowHookCommandContext, command string, path string) (string, string, error)
}
type DefaultPreWorkflowHookRunner struct{}
type DefaultPreWorkflowHookRunner struct {
OutputHandler jobs.ProjectCommandOutputHandler
}
func (wh DefaultPreWorkflowHookRunner) Run(ctx models.WorkflowHookCommandContext, command string, path string) (string, string, error) {
outputFilePath := filepath.Join(path, "OUTPUT_STATUS_FILE")
func (wh DefaultPreWorkflowHookRunner) Run(ctx models.WorkflowHookCommandContext, command string, path string) (string, error) {
cmd := exec.Command("sh", "-c", command) // #nosec
cmd.Dir = path
baseEnvVars := os.Environ()
customEnvVars := map[string]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,
"PULL_AUTHOR": ctx.Pull.Author,
"PULL_NUM": fmt.Sprintf("%d", ctx.Pull.Num),
"USER_NAME": ctx.User.Username,
"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,
"PULL_AUTHOR": ctx.Pull.Author,
"PULL_NUM": fmt.Sprintf("%d", ctx.Pull.Num),
"USER_NAME": ctx.User.Username,
"OUTPUT_STATUS_FILE": outputFilePath,
}
finalEnvVars := baseEnvVars
@@ -47,8 +54,24 @@ func (wh DefaultPreWorkflowHookRunner) Run(ctx models.WorkflowHookCommandContext
if err != nil {
err = fmt.Errorf("%s: running %q in %q: \n%s", err, command, path, out)
ctx.Log.Debug("error: %s", err)
return "", err
return "", "", err
}
// Read the value from the "outputFilePath" file
// to be returned as a custom description.
var customStatusOut []byte
if _, err := os.Stat(outputFilePath); err == nil {
var customStatusErr error
customStatusOut, customStatusErr = os.ReadFile(outputFilePath)
if customStatusErr != nil {
err = fmt.Errorf("%s: running %q in %q: \n%s", err, command, path, out)
ctx.Log.Debug("error: %s", err)
return "", "", err
}
}
wh.OutputHandler.SendWorkflowHook(ctx, fmt.Sprintf("%s\n", string(out)), true)
ctx.Log.Info("successfully ran %q in %q", command, path)
return string(out), nil
return string(out), strings.Trim(string(customStatusOut), "\n"), nil
}

View File

@@ -10,15 +10,17 @@ import (
matchers2 "github.com/runatlantis/atlantis/server/core/terraform/mocks/matchers"
"github.com/runatlantis/atlantis/server/events/mocks/matchers"
"github.com/runatlantis/atlantis/server/events/models"
jobmocks "github.com/runatlantis/atlantis/server/jobs/mocks"
"github.com/runatlantis/atlantis/server/logging"
. "github.com/runatlantis/atlantis/testing"
)
func TestPreWorkflowHookRunner_Run(t *testing.T) {
cases := []struct {
Command string
ExpOut string
ExpErr string
Command string
ExpOut string
ExpErr string
ExpDescription string
}{
{
Command: "",
@@ -56,6 +58,10 @@ func TestPreWorkflowHookRunner_Run(t *testing.T) {
Command: "echo user_name=$USER_NAME",
ExpOut: "user_name=acme-user\n",
},
{
Command: "echo something > $OUTPUT_STATUS_FILE",
ExpDescription: "something",
},
}
for _, c := range cases {
@@ -71,7 +77,9 @@ func TestPreWorkflowHookRunner_Run(t *testing.T) {
logger := logging.NewNoopLogger(t)
tmpDir := t.TempDir()
r := runtime.DefaultPreWorkflowHookRunner{}
r := runtime.DefaultPreWorkflowHookRunner{
OutputHandler: jobmocks.NewMockProjectCommandOutputHandler(),
}
t.Run(c.Command, func(t *testing.T) {
ctx := models.WorkflowHookCommandContext{
BaseRepo: models.Repo{
@@ -94,7 +102,7 @@ func TestPreWorkflowHookRunner_Run(t *testing.T) {
},
Log: logger,
}
out, err := r.Run(ctx, c.Command, tmpDir)
out, desc, err := r.Run(ctx, c.Command, tmpDir)
if c.ExpErr != "" {
ErrContains(t, c.ExpErr, err)
return
@@ -105,6 +113,7 @@ func TestPreWorkflowHookRunner_Run(t *testing.T) {
// temp dir.
expOut := strings.Replace(c.ExpOut, "$DIR", tmpDir, -1)
Equals(t, expOut, out)
Equals(t, c.ExpDescription, desc)
})
}
}

View File

@@ -166,9 +166,19 @@ func (m *MockCSU) UpdateCombinedCount(repo models.Repo, pull models.PullRequest,
m.CalledNumTotal = numTotal
return nil
}
func (m *MockCSU) UpdateCombined(repo models.Repo, pull models.PullRequest, status models.CommitStatus, command command.Name) error {
return nil
}
func (m *MockCSU) UpdateProject(ctx command.ProjectContext, cmdName command.Name, status models.CommitStatus, url string) error {
return nil
}
func (m *MockCSU) UpdatePreWorkflowHook(pull models.PullRequest, status models.CommitStatus, hookDescription string, runtimeDescription string, url string) error {
return nil
}
func (m *MockCSU) UpdatePostWorkflowHook(pull models.PullRequest, status models.CommitStatus, hookDescription string, runtimeDescription string, url string) error {
return nil
}

View File

@@ -37,6 +37,9 @@ type CommitStatusUpdater interface {
// UpdateProject sets the commit status for the project represented by
// ctx.
UpdateProject(ctx command.ProjectContext, cmdName command.Name, status models.CommitStatus, url string) error
UpdatePreWorkflowHook(pull models.PullRequest, status models.CommitStatus, hookDescription string, runtimeDescription string, url string) error
UpdatePostWorkflowHook(pull models.PullRequest, status models.CommitStatus, hookDescription string, runtimeDescription string, url string) error
}
// DefaultCommitStatusUpdater implements CommitStatusUpdater.
@@ -96,3 +99,31 @@ func (d *DefaultCommitStatusUpdater) UpdateProject(ctx command.ProjectContext, c
descrip := fmt.Sprintf("%s %s", cases.Title(language.English).String(cmdName.String()), descripWords)
return d.Client.UpdateStatus(ctx.BaseRepo, ctx.Pull, status, src, descrip, url)
}
func (d *DefaultCommitStatusUpdater) UpdatePreWorkflowHook(pull models.PullRequest, status models.CommitStatus, hookDescription string, runtimeDescription string, url string) error {
return d.updateWorkflowHook(pull, status, hookDescription, runtimeDescription, "pre_workflow_hook", url)
}
func (d *DefaultCommitStatusUpdater) UpdatePostWorkflowHook(pull models.PullRequest, status models.CommitStatus, hookDescription string, runtimeDescription string, url string) error {
return d.updateWorkflowHook(pull, status, hookDescription, runtimeDescription, "post_workflow_hook", url)
}
func (d *DefaultCommitStatusUpdater) updateWorkflowHook(pull models.PullRequest, status models.CommitStatus, hookDescription string, runtimeDescription string, workflowType string, url string) error {
src := fmt.Sprintf("%s/%s: %s", d.StatusName, workflowType, hookDescription)
var descripWords string
if runtimeDescription != "" {
descripWords = runtimeDescription
} else {
switch status {
case models.PendingCommitStatus:
descripWords = "in progress..."
case models.FailedCommitStatus:
descripWords = "failed."
case models.SuccessCommitStatus:
descripWords = "succeeded."
}
}
return d.Client.UpdateStatus(pull.BaseRepo, pull, status, src, descripWords, url)
}

View File

@@ -0,0 +1,33 @@
// Code generated by pegomock. DO NOT EDIT.
package matchers
import (
"github.com/petergtz/pegomock"
"reflect"
command "github.com/runatlantis/atlantis/server/events/command"
)
func AnyCommandName() command.Name {
pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*(command.Name))(nil)).Elem()))
var nullValue command.Name
return nullValue
}
func EqCommandName(value command.Name) command.Name {
pegomock.RegisterMatcher(&pegomock.EqMatcher{Value: value})
var nullValue command.Name
return nullValue
}
func NotEqCommandName(value command.Name) command.Name {
pegomock.RegisterMatcher(&pegomock.NotEqMatcher{Value: value})
var nullValue command.Name
return nullValue
}
func CommandNameThat(matcher pegomock.ArgumentMatcher) command.Name {
pegomock.RegisterMatcher(matcher)
var nullValue command.Name
return nullValue
}

View File

@@ -0,0 +1,33 @@
// Code generated by pegomock. DO NOT EDIT.
package matchers
import (
"github.com/petergtz/pegomock"
"reflect"
command "github.com/runatlantis/atlantis/server/events/command"
)
func AnyCommandProjectContext() command.ProjectContext {
pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*(command.ProjectContext))(nil)).Elem()))
var nullValue command.ProjectContext
return nullValue
}
func EqCommandProjectContext(value command.ProjectContext) command.ProjectContext {
pegomock.RegisterMatcher(&pegomock.EqMatcher{Value: value})
var nullValue command.ProjectContext
return nullValue
}
func NotEqCommandProjectContext(value command.ProjectContext) command.ProjectContext {
pegomock.RegisterMatcher(&pegomock.NotEqMatcher{Value: value})
var nullValue command.ProjectContext
return nullValue
}
func CommandProjectContextThat(matcher pegomock.ArgumentMatcher) command.ProjectContext {
pegomock.RegisterMatcher(matcher)
var nullValue command.ProjectContext
return nullValue
}

View File

@@ -2,9 +2,8 @@
package matchers
import (
"reflect"
"github.com/petergtz/pegomock"
"reflect"
models "github.com/runatlantis/atlantis/server/events/models"
)

View File

@@ -2,9 +2,8 @@
package matchers
import (
"reflect"
"github.com/petergtz/pegomock"
"reflect"
models "github.com/runatlantis/atlantis/server/events/models"
)

View File

@@ -2,9 +2,8 @@
package matchers
import (
"reflect"
"github.com/petergtz/pegomock"
"reflect"
models "github.com/runatlantis/atlantis/server/events/models"
)

View File

@@ -0,0 +1,33 @@
// Code generated by pegomock. DO NOT EDIT.
package matchers
import (
"github.com/petergtz/pegomock"
"reflect"
models "github.com/runatlantis/atlantis/server/events/models"
)
func AnyModelsWorkflowHookCommandContext() models.WorkflowHookCommandContext {
pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*(models.WorkflowHookCommandContext))(nil)).Elem()))
var nullValue models.WorkflowHookCommandContext
return nullValue
}
func EqModelsWorkflowHookCommandContext(value models.WorkflowHookCommandContext) models.WorkflowHookCommandContext {
pegomock.RegisterMatcher(&pegomock.EqMatcher{Value: value})
var nullValue models.WorkflowHookCommandContext
return nullValue
}
func NotEqModelsWorkflowHookCommandContext(value models.WorkflowHookCommandContext) models.WorkflowHookCommandContext {
pegomock.RegisterMatcher(&pegomock.NotEqMatcher{Value: value})
var nullValue models.WorkflowHookCommandContext
return nullValue
}
func ModelsWorkflowHookCommandContextThat(matcher pegomock.ArgumentMatcher) models.WorkflowHookCommandContext {
pegomock.RegisterMatcher(matcher)
var nullValue models.WorkflowHookCommandContext
return nullValue
}

View File

@@ -0,0 +1,33 @@
// Code generated by pegomock. DO NOT EDIT.
package matchers
import (
"github.com/petergtz/pegomock"
"reflect"
command "github.com/runatlantis/atlantis/server/events/command"
)
func AnyPtrToCommandContext() *command.Context {
pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*(*command.Context))(nil)).Elem()))
var nullValue *command.Context
return nullValue
}
func EqPtrToCommandContext(value *command.Context) *command.Context {
pegomock.RegisterMatcher(&pegomock.EqMatcher{Value: value})
var nullValue *command.Context
return nullValue
}
func NotEqPtrToCommandContext(value *command.Context) *command.Context {
pegomock.RegisterMatcher(&pegomock.NotEqMatcher{Value: value})
var nullValue *command.Context
return nullValue
}
func PtrToCommandContextThat(matcher pegomock.ArgumentMatcher) *command.Context {
pegomock.RegisterMatcher(matcher)
var nullValue *command.Context
return nullValue
}

View File

@@ -2,9 +2,8 @@
package matchers
import (
"reflect"
"github.com/petergtz/pegomock"
"reflect"
events "github.com/runatlantis/atlantis/server/events"
)

View File

@@ -0,0 +1,33 @@
// Code generated by pegomock. DO NOT EDIT.
package matchers
import (
"github.com/petergtz/pegomock"
"reflect"
valid "github.com/runatlantis/atlantis/server/core/config/valid"
)
func AnySliceOfPtrToValidWorkflowHook() []*valid.WorkflowHook {
pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*([]*valid.WorkflowHook))(nil)).Elem()))
var nullValue []*valid.WorkflowHook
return nullValue
}
func EqSliceOfPtrToValidWorkflowHook(value []*valid.WorkflowHook) []*valid.WorkflowHook {
pegomock.RegisterMatcher(&pegomock.EqMatcher{Value: value})
var nullValue []*valid.WorkflowHook
return nullValue
}
func NotEqSliceOfPtrToValidWorkflowHook(value []*valid.WorkflowHook) []*valid.WorkflowHook {
pegomock.RegisterMatcher(&pegomock.NotEqMatcher{Value: value})
var nullValue []*valid.WorkflowHook
return nullValue
}
func SliceOfPtrToValidWorkflowHookThat(matcher pegomock.ArgumentMatcher) []*valid.WorkflowHook {
pegomock.RegisterMatcher(matcher)
var nullValue []*valid.WorkflowHook
return nullValue
}

View File

@@ -4,12 +4,11 @@
package mocks
import (
pegomock "github.com/petergtz/pegomock"
command "github.com/runatlantis/atlantis/server/events/command"
models "github.com/runatlantis/atlantis/server/events/models"
"reflect"
"time"
pegomock "github.com/petergtz/pegomock"
"github.com/runatlantis/atlantis/server/events/command"
models "github.com/runatlantis/atlantis/server/events/models"
)
type MockCommitStatusUpdater struct {
@@ -27,11 +26,11 @@ func NewMockCommitStatusUpdater(options ...pegomock.Option) *MockCommitStatusUpd
func (mock *MockCommitStatusUpdater) SetFailHandler(fh pegomock.FailHandler) { mock.fail = fh }
func (mock *MockCommitStatusUpdater) FailHandler() pegomock.FailHandler { return mock.fail }
func (mock *MockCommitStatusUpdater) UpdateCombined(repo models.Repo, pull models.PullRequest, status models.CommitStatus, command command.Name) error {
func (mock *MockCommitStatusUpdater) UpdateCombined(repo models.Repo, pull models.PullRequest, status models.CommitStatus, cmdName command.Name) error {
if mock == nil {
panic("mock must not be nil. Use myMock := NewMockCommitStatusUpdater().")
}
params := []pegomock.Param{repo, pull, status, command}
params := []pegomock.Param{repo, pull, status, cmdName}
result := pegomock.GetGenericMockFrom(mock).Invoke("UpdateCombined", params, []reflect.Type{reflect.TypeOf((*error)(nil)).Elem()})
var ret0 error
if len(result) != 0 {
@@ -42,11 +41,11 @@ func (mock *MockCommitStatusUpdater) UpdateCombined(repo models.Repo, pull model
return ret0
}
func (mock *MockCommitStatusUpdater) UpdateCombinedCount(repo models.Repo, pull models.PullRequest, status models.CommitStatus, command command.Name, numSuccess int, numTotal int) error {
func (mock *MockCommitStatusUpdater) UpdateCombinedCount(repo models.Repo, pull models.PullRequest, status models.CommitStatus, cmdName command.Name, numSuccess int, numTotal int) error {
if mock == nil {
panic("mock must not be nil. Use myMock := NewMockCommitStatusUpdater().")
}
params := []pegomock.Param{repo, pull, status, command, numSuccess, numTotal}
params := []pegomock.Param{repo, pull, status, cmdName, numSuccess, numTotal}
result := pegomock.GetGenericMockFrom(mock).Invoke("UpdateCombinedCount", params, []reflect.Type{reflect.TypeOf((*error)(nil)).Elem()})
var ret0 error
if len(result) != 0 {
@@ -72,6 +71,36 @@ func (mock *MockCommitStatusUpdater) UpdateProject(ctx command.ProjectContext, c
return ret0
}
func (mock *MockCommitStatusUpdater) UpdatePreWorkflowHook(pull models.PullRequest, status models.CommitStatus, hookDescription string, runtimeDescription string, url string) error {
if mock == nil {
panic("mock must not be nil. Use myMock := NewMockCommitStatusUpdater().")
}
params := []pegomock.Param{pull, status, hookDescription, runtimeDescription, url}
result := pegomock.GetGenericMockFrom(mock).Invoke("UpdatePreWorkflowHook", params, []reflect.Type{reflect.TypeOf((*error)(nil)).Elem()})
var ret0 error
if len(result) != 0 {
if result[0] != nil {
ret0 = result[0].(error)
}
}
return ret0
}
func (mock *MockCommitStatusUpdater) UpdatePostWorkflowHook(pull models.PullRequest, status models.CommitStatus, hookDescription string, runtimeDescription string, url string) error {
if mock == nil {
panic("mock must not be nil. Use myMock := NewMockCommitStatusUpdater().")
}
params := []pegomock.Param{pull, status, hookDescription, runtimeDescription, url}
result := pegomock.GetGenericMockFrom(mock).Invoke("UpdatePostWorkflowHook", params, []reflect.Type{reflect.TypeOf((*error)(nil)).Elem()})
var ret0 error
if len(result) != 0 {
if result[0] != nil {
ret0 = result[0].(error)
}
}
return ret0
}
func (mock *MockCommitStatusUpdater) VerifyWasCalledOnce() *VerifierMockCommitStatusUpdater {
return &VerifierMockCommitStatusUpdater{
mock: mock,
@@ -109,8 +138,8 @@ type VerifierMockCommitStatusUpdater struct {
timeout time.Duration
}
func (verifier *VerifierMockCommitStatusUpdater) UpdateCombined(repo models.Repo, pull models.PullRequest, status models.CommitStatus, command command.Name) *MockCommitStatusUpdater_UpdateCombined_OngoingVerification {
params := []pegomock.Param{repo, pull, status, command}
func (verifier *VerifierMockCommitStatusUpdater) UpdateCombined(repo models.Repo, pull models.PullRequest, status models.CommitStatus, cmdName command.Name) *MockCommitStatusUpdater_UpdateCombined_OngoingVerification {
params := []pegomock.Param{repo, pull, status, cmdName}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "UpdateCombined", params, verifier.timeout)
return &MockCommitStatusUpdater_UpdateCombined_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}
@@ -121,8 +150,8 @@ type MockCommitStatusUpdater_UpdateCombined_OngoingVerification struct {
}
func (c *MockCommitStatusUpdater_UpdateCombined_OngoingVerification) GetCapturedArguments() (models.Repo, models.PullRequest, models.CommitStatus, command.Name) {
repo, pull, status, command := c.GetAllCapturedArguments()
return repo[len(repo)-1], pull[len(pull)-1], status[len(status)-1], command[len(command)-1]
repo, pull, status, cmdName := c.GetAllCapturedArguments()
return repo[len(repo)-1], pull[len(pull)-1], status[len(status)-1], cmdName[len(cmdName)-1]
}
func (c *MockCommitStatusUpdater_UpdateCombined_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []models.PullRequest, _param2 []models.CommitStatus, _param3 []command.Name) {
@@ -148,8 +177,8 @@ func (c *MockCommitStatusUpdater_UpdateCombined_OngoingVerification) GetAllCaptu
return
}
func (verifier *VerifierMockCommitStatusUpdater) UpdateCombinedCount(repo models.Repo, pull models.PullRequest, status models.CommitStatus, cmd command.Name, numSuccess int, numTotal int) *MockCommitStatusUpdater_UpdateCombinedCount_OngoingVerification {
params := []pegomock.Param{repo, pull, status, cmd, numSuccess, numTotal}
func (verifier *VerifierMockCommitStatusUpdater) UpdateCombinedCount(repo models.Repo, pull models.PullRequest, status models.CommitStatus, cmdName command.Name, numSuccess int, numTotal int) *MockCommitStatusUpdater_UpdateCombinedCount_OngoingVerification {
params := []pegomock.Param{repo, pull, status, cmdName, numSuccess, numTotal}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "UpdateCombinedCount", params, verifier.timeout)
return &MockCommitStatusUpdater_UpdateCombinedCount_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}
@@ -160,8 +189,8 @@ type MockCommitStatusUpdater_UpdateCombinedCount_OngoingVerification struct {
}
func (c *MockCommitStatusUpdater_UpdateCombinedCount_OngoingVerification) GetCapturedArguments() (models.Repo, models.PullRequest, models.CommitStatus, command.Name, int, int) {
repo, pull, status, command, numSuccess, numTotal := c.GetAllCapturedArguments()
return repo[len(repo)-1], pull[len(pull)-1], status[len(status)-1], command[len(command)-1], numSuccess[len(numSuccess)-1], numTotal[len(numTotal)-1]
repo, pull, status, cmdName, numSuccess, numTotal := c.GetAllCapturedArguments()
return repo[len(repo)-1], pull[len(pull)-1], status[len(status)-1], cmdName[len(cmdName)-1], numSuccess[len(numSuccess)-1], numTotal[len(numTotal)-1]
}
func (c *MockCommitStatusUpdater_UpdateCombinedCount_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []models.PullRequest, _param2 []models.CommitStatus, _param3 []command.Name, _param4 []int, _param5 []int) {
@@ -233,3 +262,89 @@ func (c *MockCommitStatusUpdater_UpdateProject_OngoingVerification) GetAllCaptur
}
return
}
func (verifier *VerifierMockCommitStatusUpdater) UpdatePreWorkflowHook(pull models.PullRequest, status models.CommitStatus, hookDescription string, runtimeDescription string, url string) *MockCommitStatusUpdater_UpdatePreWorkflowHook_OngoingVerification {
params := []pegomock.Param{pull, status, hookDescription, runtimeDescription, url}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "UpdatePreWorkflowHook", params, verifier.timeout)
return &MockCommitStatusUpdater_UpdatePreWorkflowHook_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}
type MockCommitStatusUpdater_UpdatePreWorkflowHook_OngoingVerification struct {
mock *MockCommitStatusUpdater
methodInvocations []pegomock.MethodInvocation
}
func (c *MockCommitStatusUpdater_UpdatePreWorkflowHook_OngoingVerification) GetCapturedArguments() (models.PullRequest, models.CommitStatus, string, string, string) {
pull, status, hookDescription, runtimeDescription, url := c.GetAllCapturedArguments()
return pull[len(pull)-1], status[len(status)-1], hookDescription[len(hookDescription)-1], runtimeDescription[len(runtimeDescription)-1], url[len(url)-1]
}
func (c *MockCommitStatusUpdater_UpdatePreWorkflowHook_OngoingVerification) GetAllCapturedArguments() (_param0 []models.PullRequest, _param1 []models.CommitStatus, _param2 []string, _param3 []string, _param4 []string) {
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
if len(params) > 0 {
_param0 = make([]models.PullRequest, len(c.methodInvocations))
for u, param := range params[0] {
_param0[u] = param.(models.PullRequest)
}
_param1 = make([]models.CommitStatus, len(c.methodInvocations))
for u, param := range params[1] {
_param1[u] = param.(models.CommitStatus)
}
_param2 = make([]string, len(c.methodInvocations))
for u, param := range params[2] {
_param2[u] = param.(string)
}
_param3 = make([]string, len(c.methodInvocations))
for u, param := range params[3] {
_param3[u] = param.(string)
}
_param4 = make([]string, len(c.methodInvocations))
for u, param := range params[4] {
_param4[u] = param.(string)
}
}
return
}
func (verifier *VerifierMockCommitStatusUpdater) UpdatePostWorkflowHook(pull models.PullRequest, status models.CommitStatus, hookDescription string, runtimeDescription string, url string) *MockCommitStatusUpdater_UpdatePostWorkflowHook_OngoingVerification {
params := []pegomock.Param{pull, status, hookDescription, runtimeDescription, url}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "UpdatePostWorkflowHook", params, verifier.timeout)
return &MockCommitStatusUpdater_UpdatePostWorkflowHook_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}
type MockCommitStatusUpdater_UpdatePostWorkflowHook_OngoingVerification struct {
mock *MockCommitStatusUpdater
methodInvocations []pegomock.MethodInvocation
}
func (c *MockCommitStatusUpdater_UpdatePostWorkflowHook_OngoingVerification) GetCapturedArguments() (models.PullRequest, models.CommitStatus, string, string, string) {
pull, status, hookDescription, runtimeDescription, url := c.GetAllCapturedArguments()
return pull[len(pull)-1], status[len(status)-1], hookDescription[len(hookDescription)-1], runtimeDescription[len(runtimeDescription)-1], url[len(url)-1]
}
func (c *MockCommitStatusUpdater_UpdatePostWorkflowHook_OngoingVerification) GetAllCapturedArguments() (_param0 []models.PullRequest, _param1 []models.CommitStatus, _param2 []string, _param3 []string, _param4 []string) {
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
if len(params) > 0 {
_param0 = make([]models.PullRequest, len(c.methodInvocations))
for u, param := range params[0] {
_param0[u] = param.(models.PullRequest)
}
_param1 = make([]models.CommitStatus, len(c.methodInvocations))
for u, param := range params[1] {
_param1[u] = param.(models.CommitStatus)
}
_param2 = make([]string, len(c.methodInvocations))
for u, param := range params[2] {
_param2[u] = param.(string)
}
_param3 = make([]string, len(c.methodInvocations))
for u, param := range params[3] {
_param3[u] = param.(string)
}
_param4 = make([]string, len(c.methodInvocations))
for u, param := range params[4] {
_param4[u] = param.(string)
}
}
return
}

View File

@@ -0,0 +1,108 @@
// Code generated by pegomock. DO NOT EDIT.
// Source: github.com/runatlantis/atlantis/server/events (interfaces: PostWorkflowHookURLGenerator)
package mocks
import (
pegomock "github.com/petergtz/pegomock"
"reflect"
"time"
)
type MockPostWorkflowHookURLGenerator struct {
fail func(message string, callerSkip ...int)
}
func NewMockPostWorkflowHookURLGenerator(options ...pegomock.Option) *MockPostWorkflowHookURLGenerator {
mock := &MockPostWorkflowHookURLGenerator{}
for _, option := range options {
option.Apply(mock)
}
return mock
}
func (mock *MockPostWorkflowHookURLGenerator) SetFailHandler(fh pegomock.FailHandler) { mock.fail = fh }
func (mock *MockPostWorkflowHookURLGenerator) FailHandler() pegomock.FailHandler { return mock.fail }
func (mock *MockPostWorkflowHookURLGenerator) GenerateProjectWorkflowHookURL(hookID string) (string, error) {
if mock == nil {
panic("mock must not be nil. Use myMock := NewMockPostWorkflowHookURLGenerator().")
}
params := []pegomock.Param{hookID}
result := pegomock.GetGenericMockFrom(mock).Invoke("GenerateProjectWorkflowHookURL", params, []reflect.Type{reflect.TypeOf((*string)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
var ret0 string
var ret1 error
if len(result) != 0 {
if result[0] != nil {
ret0 = result[0].(string)
}
if result[1] != nil {
ret1 = result[1].(error)
}
}
return ret0, ret1
}
func (mock *MockPostWorkflowHookURLGenerator) VerifyWasCalledOnce() *VerifierMockPostWorkflowHookURLGenerator {
return &VerifierMockPostWorkflowHookURLGenerator{
mock: mock,
invocationCountMatcher: pegomock.Times(1),
}
}
func (mock *MockPostWorkflowHookURLGenerator) VerifyWasCalled(invocationCountMatcher pegomock.InvocationCountMatcher) *VerifierMockPostWorkflowHookURLGenerator {
return &VerifierMockPostWorkflowHookURLGenerator{
mock: mock,
invocationCountMatcher: invocationCountMatcher,
}
}
func (mock *MockPostWorkflowHookURLGenerator) VerifyWasCalledInOrder(invocationCountMatcher pegomock.InvocationCountMatcher, inOrderContext *pegomock.InOrderContext) *VerifierMockPostWorkflowHookURLGenerator {
return &VerifierMockPostWorkflowHookURLGenerator{
mock: mock,
invocationCountMatcher: invocationCountMatcher,
inOrderContext: inOrderContext,
}
}
func (mock *MockPostWorkflowHookURLGenerator) VerifyWasCalledEventually(invocationCountMatcher pegomock.InvocationCountMatcher, timeout time.Duration) *VerifierMockPostWorkflowHookURLGenerator {
return &VerifierMockPostWorkflowHookURLGenerator{
mock: mock,
invocationCountMatcher: invocationCountMatcher,
timeout: timeout,
}
}
type VerifierMockPostWorkflowHookURLGenerator struct {
mock *MockPostWorkflowHookURLGenerator
invocationCountMatcher pegomock.InvocationCountMatcher
inOrderContext *pegomock.InOrderContext
timeout time.Duration
}
func (verifier *VerifierMockPostWorkflowHookURLGenerator) GenerateProjectWorkflowHookURL(hookID string) *MockPostWorkflowHookURLGenerator_GenerateProjectWorkflowHookURL_OngoingVerification {
params := []pegomock.Param{hookID}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "GenerateProjectWorkflowHookURL", params, verifier.timeout)
return &MockPostWorkflowHookURLGenerator_GenerateProjectWorkflowHookURL_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}
type MockPostWorkflowHookURLGenerator_GenerateProjectWorkflowHookURL_OngoingVerification struct {
mock *MockPostWorkflowHookURLGenerator
methodInvocations []pegomock.MethodInvocation
}
func (c *MockPostWorkflowHookURLGenerator_GenerateProjectWorkflowHookURL_OngoingVerification) GetCapturedArguments() string {
hookID := c.GetAllCapturedArguments()
return hookID[len(hookID)-1]
}
func (c *MockPostWorkflowHookURLGenerator_GenerateProjectWorkflowHookURL_OngoingVerification) GetAllCapturedArguments() (_param0 []string) {
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
if len(params) > 0 {
_param0 = make([]string, len(c.methodInvocations))
for u, param := range params[0] {
_param0[u] = param.(string)
}
}
return
}

View File

@@ -0,0 +1,96 @@
// Code generated by pegomock. DO NOT EDIT.
// Source: github.com/runatlantis/atlantis/server/events (interfaces: PostWorkflowHookUUIDGenerator)
package mocks
import (
pegomock "github.com/petergtz/pegomock"
"reflect"
"time"
)
type MockPostWorkflowHookUUIDGenerator struct {
fail func(message string, callerSkip ...int)
}
func NewMockPostWorkflowHookUUIDGenerator(options ...pegomock.Option) *MockPostWorkflowHookUUIDGenerator {
mock := &MockPostWorkflowHookUUIDGenerator{}
for _, option := range options {
option.Apply(mock)
}
return mock
}
func (mock *MockPostWorkflowHookUUIDGenerator) SetFailHandler(fh pegomock.FailHandler) {
mock.fail = fh
}
func (mock *MockPostWorkflowHookUUIDGenerator) FailHandler() pegomock.FailHandler { return mock.fail }
func (mock *MockPostWorkflowHookUUIDGenerator) GenerateUUID() string {
if mock == nil {
panic("mock must not be nil. Use myMock := NewMockPostWorkflowHookUUIDGenerator().")
}
params := []pegomock.Param{}
result := pegomock.GetGenericMockFrom(mock).Invoke("GenerateUUID", params, []reflect.Type{reflect.TypeOf((*string)(nil)).Elem()})
var ret0 string
if len(result) != 0 {
if result[0] != nil {
ret0 = result[0].(string)
}
}
return ret0
}
func (mock *MockPostWorkflowHookUUIDGenerator) VerifyWasCalledOnce() *VerifierMockPostWorkflowHookUUIDGenerator {
return &VerifierMockPostWorkflowHookUUIDGenerator{
mock: mock,
invocationCountMatcher: pegomock.Times(1),
}
}
func (mock *MockPostWorkflowHookUUIDGenerator) VerifyWasCalled(invocationCountMatcher pegomock.InvocationCountMatcher) *VerifierMockPostWorkflowHookUUIDGenerator {
return &VerifierMockPostWorkflowHookUUIDGenerator{
mock: mock,
invocationCountMatcher: invocationCountMatcher,
}
}
func (mock *MockPostWorkflowHookUUIDGenerator) VerifyWasCalledInOrder(invocationCountMatcher pegomock.InvocationCountMatcher, inOrderContext *pegomock.InOrderContext) *VerifierMockPostWorkflowHookUUIDGenerator {
return &VerifierMockPostWorkflowHookUUIDGenerator{
mock: mock,
invocationCountMatcher: invocationCountMatcher,
inOrderContext: inOrderContext,
}
}
func (mock *MockPostWorkflowHookUUIDGenerator) VerifyWasCalledEventually(invocationCountMatcher pegomock.InvocationCountMatcher, timeout time.Duration) *VerifierMockPostWorkflowHookUUIDGenerator {
return &VerifierMockPostWorkflowHookUUIDGenerator{
mock: mock,
invocationCountMatcher: invocationCountMatcher,
timeout: timeout,
}
}
type VerifierMockPostWorkflowHookUUIDGenerator struct {
mock *MockPostWorkflowHookUUIDGenerator
invocationCountMatcher pegomock.InvocationCountMatcher
inOrderContext *pegomock.InOrderContext
timeout time.Duration
}
func (verifier *VerifierMockPostWorkflowHookUUIDGenerator) GenerateUUID() *MockPostWorkflowHookUUIDGenerator_GenerateUUID_OngoingVerification {
params := []pegomock.Param{}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "GenerateUUID", params, verifier.timeout)
return &MockPostWorkflowHookUUIDGenerator_GenerateUUID_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}
type MockPostWorkflowHookUUIDGenerator_GenerateUUID_OngoingVerification struct {
mock *MockPostWorkflowHookUUIDGenerator
methodInvocations []pegomock.MethodInvocation
}
func (c *MockPostWorkflowHookUUIDGenerator_GenerateUUID_OngoingVerification) GetCapturedArguments() {
}
func (c *MockPostWorkflowHookUUIDGenerator_GenerateUUID_OngoingVerification) GetAllCapturedArguments() {
}

View File

@@ -4,12 +4,11 @@
package mocks
import (
"reflect"
"time"
pegomock "github.com/petergtz/pegomock"
events "github.com/runatlantis/atlantis/server/events"
command "github.com/runatlantis/atlantis/server/events/command"
"reflect"
"time"
)
type MockPostWorkflowHooksCommandRunner struct {

View File

@@ -0,0 +1,108 @@
// Code generated by pegomock. DO NOT EDIT.
// Source: github.com/runatlantis/atlantis/server/events (interfaces: PreWorkflowHookURLGenerator)
package mocks
import (
pegomock "github.com/petergtz/pegomock"
"reflect"
"time"
)
type MockPreWorkflowHookURLGenerator struct {
fail func(message string, callerSkip ...int)
}
func NewMockPreWorkflowHookURLGenerator(options ...pegomock.Option) *MockPreWorkflowHookURLGenerator {
mock := &MockPreWorkflowHookURLGenerator{}
for _, option := range options {
option.Apply(mock)
}
return mock
}
func (mock *MockPreWorkflowHookURLGenerator) SetFailHandler(fh pegomock.FailHandler) { mock.fail = fh }
func (mock *MockPreWorkflowHookURLGenerator) FailHandler() pegomock.FailHandler { return mock.fail }
func (mock *MockPreWorkflowHookURLGenerator) GenerateProjectWorkflowHookURL(hookID string) (string, error) {
if mock == nil {
panic("mock must not be nil. Use myMock := NewMockPreWorkflowHookURLGenerator().")
}
params := []pegomock.Param{hookID}
result := pegomock.GetGenericMockFrom(mock).Invoke("GenerateProjectWorkflowHookURL", params, []reflect.Type{reflect.TypeOf((*string)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
var ret0 string
var ret1 error
if len(result) != 0 {
if result[0] != nil {
ret0 = result[0].(string)
}
if result[1] != nil {
ret1 = result[1].(error)
}
}
return ret0, ret1
}
func (mock *MockPreWorkflowHookURLGenerator) VerifyWasCalledOnce() *VerifierMockPreWorkflowHookURLGenerator {
return &VerifierMockPreWorkflowHookURLGenerator{
mock: mock,
invocationCountMatcher: pegomock.Times(1),
}
}
func (mock *MockPreWorkflowHookURLGenerator) VerifyWasCalled(invocationCountMatcher pegomock.InvocationCountMatcher) *VerifierMockPreWorkflowHookURLGenerator {
return &VerifierMockPreWorkflowHookURLGenerator{
mock: mock,
invocationCountMatcher: invocationCountMatcher,
}
}
func (mock *MockPreWorkflowHookURLGenerator) VerifyWasCalledInOrder(invocationCountMatcher pegomock.InvocationCountMatcher, inOrderContext *pegomock.InOrderContext) *VerifierMockPreWorkflowHookURLGenerator {
return &VerifierMockPreWorkflowHookURLGenerator{
mock: mock,
invocationCountMatcher: invocationCountMatcher,
inOrderContext: inOrderContext,
}
}
func (mock *MockPreWorkflowHookURLGenerator) VerifyWasCalledEventually(invocationCountMatcher pegomock.InvocationCountMatcher, timeout time.Duration) *VerifierMockPreWorkflowHookURLGenerator {
return &VerifierMockPreWorkflowHookURLGenerator{
mock: mock,
invocationCountMatcher: invocationCountMatcher,
timeout: timeout,
}
}
type VerifierMockPreWorkflowHookURLGenerator struct {
mock *MockPreWorkflowHookURLGenerator
invocationCountMatcher pegomock.InvocationCountMatcher
inOrderContext *pegomock.InOrderContext
timeout time.Duration
}
func (verifier *VerifierMockPreWorkflowHookURLGenerator) GenerateProjectWorkflowHookURL(hookID string) *MockPreWorkflowHookURLGenerator_GenerateProjectWorkflowHookURL_OngoingVerification {
params := []pegomock.Param{hookID}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "GenerateProjectWorkflowHookURL", params, verifier.timeout)
return &MockPreWorkflowHookURLGenerator_GenerateProjectWorkflowHookURL_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}
type MockPreWorkflowHookURLGenerator_GenerateProjectWorkflowHookURL_OngoingVerification struct {
mock *MockPreWorkflowHookURLGenerator
methodInvocations []pegomock.MethodInvocation
}
func (c *MockPreWorkflowHookURLGenerator_GenerateProjectWorkflowHookURL_OngoingVerification) GetCapturedArguments() string {
hookID := c.GetAllCapturedArguments()
return hookID[len(hookID)-1]
}
func (c *MockPreWorkflowHookURLGenerator_GenerateProjectWorkflowHookURL_OngoingVerification) GetAllCapturedArguments() (_param0 []string) {
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
if len(params) > 0 {
_param0 = make([]string, len(c.methodInvocations))
for u, param := range params[0] {
_param0[u] = param.(string)
}
}
return
}

View File

@@ -0,0 +1,94 @@
// Code generated by pegomock. DO NOT EDIT.
// Source: github.com/runatlantis/atlantis/server/events (interfaces: PreWorkflowHookUUIDGenerator)
package mocks
import (
pegomock "github.com/petergtz/pegomock"
"reflect"
"time"
)
type MockPreWorkflowHookUUIDGenerator struct {
fail func(message string, callerSkip ...int)
}
func NewMockPreWorkflowHookUUIDGenerator(options ...pegomock.Option) *MockPreWorkflowHookUUIDGenerator {
mock := &MockPreWorkflowHookUUIDGenerator{}
for _, option := range options {
option.Apply(mock)
}
return mock
}
func (mock *MockPreWorkflowHookUUIDGenerator) SetFailHandler(fh pegomock.FailHandler) { mock.fail = fh }
func (mock *MockPreWorkflowHookUUIDGenerator) FailHandler() pegomock.FailHandler { return mock.fail }
func (mock *MockPreWorkflowHookUUIDGenerator) GenerateUUID() string {
if mock == nil {
panic("mock must not be nil. Use myMock := NewMockPreWorkflowHookUUIDGenerator().")
}
params := []pegomock.Param{}
result := pegomock.GetGenericMockFrom(mock).Invoke("GenerateUUID", params, []reflect.Type{reflect.TypeOf((*string)(nil)).Elem()})
var ret0 string
if len(result) != 0 {
if result[0] != nil {
ret0 = result[0].(string)
}
}
return ret0
}
func (mock *MockPreWorkflowHookUUIDGenerator) VerifyWasCalledOnce() *VerifierMockPreWorkflowHookUUIDGenerator {
return &VerifierMockPreWorkflowHookUUIDGenerator{
mock: mock,
invocationCountMatcher: pegomock.Times(1),
}
}
func (mock *MockPreWorkflowHookUUIDGenerator) VerifyWasCalled(invocationCountMatcher pegomock.InvocationCountMatcher) *VerifierMockPreWorkflowHookUUIDGenerator {
return &VerifierMockPreWorkflowHookUUIDGenerator{
mock: mock,
invocationCountMatcher: invocationCountMatcher,
}
}
func (mock *MockPreWorkflowHookUUIDGenerator) VerifyWasCalledInOrder(invocationCountMatcher pegomock.InvocationCountMatcher, inOrderContext *pegomock.InOrderContext) *VerifierMockPreWorkflowHookUUIDGenerator {
return &VerifierMockPreWorkflowHookUUIDGenerator{
mock: mock,
invocationCountMatcher: invocationCountMatcher,
inOrderContext: inOrderContext,
}
}
func (mock *MockPreWorkflowHookUUIDGenerator) VerifyWasCalledEventually(invocationCountMatcher pegomock.InvocationCountMatcher, timeout time.Duration) *VerifierMockPreWorkflowHookUUIDGenerator {
return &VerifierMockPreWorkflowHookUUIDGenerator{
mock: mock,
invocationCountMatcher: invocationCountMatcher,
timeout: timeout,
}
}
type VerifierMockPreWorkflowHookUUIDGenerator struct {
mock *MockPreWorkflowHookUUIDGenerator
invocationCountMatcher pegomock.InvocationCountMatcher
inOrderContext *pegomock.InOrderContext
timeout time.Duration
}
func (verifier *VerifierMockPreWorkflowHookUUIDGenerator) GenerateUUID() *MockPreWorkflowHookUUIDGenerator_GenerateUUID_OngoingVerification {
params := []pegomock.Param{}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "GenerateUUID", params, verifier.timeout)
return &MockPreWorkflowHookUUIDGenerator_GenerateUUID_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}
type MockPreWorkflowHookUUIDGenerator_GenerateUUID_OngoingVerification struct {
mock *MockPreWorkflowHookUUIDGenerator
methodInvocations []pegomock.MethodInvocation
}
func (c *MockPreWorkflowHookUUIDGenerator_GenerateUUID_OngoingVerification) GetCapturedArguments() {
}
func (c *MockPreWorkflowHookUUIDGenerator_GenerateUUID_OngoingVerification) GetAllCapturedArguments() {
}

View File

@@ -4,12 +4,11 @@
package mocks
import (
"reflect"
"time"
pegomock "github.com/petergtz/pegomock"
events "github.com/runatlantis/atlantis/server/events"
command "github.com/runatlantis/atlantis/server/events/command"
"reflect"
"time"
)
type MockPreWorkflowHooksCommandRunner struct {

View File

@@ -0,0 +1,94 @@
// Code generated by pegomock. DO NOT EDIT.
// Source: github.com/runatlantis/atlantis/server/events (interfaces: UUIDGenerator)
package mocks
import (
pegomock "github.com/petergtz/pegomock"
"reflect"
"time"
)
type MockUUIDGenerator struct {
fail func(message string, callerSkip ...int)
}
func NewMockUUIDGenerator(options ...pegomock.Option) *MockUUIDGenerator {
mock := &MockUUIDGenerator{}
for _, option := range options {
option.Apply(mock)
}
return mock
}
func (mock *MockUUIDGenerator) SetFailHandler(fh pegomock.FailHandler) { mock.fail = fh }
func (mock *MockUUIDGenerator) FailHandler() pegomock.FailHandler { return mock.fail }
func (mock *MockUUIDGenerator) GenerateUUID() string {
if mock == nil {
panic("mock must not be nil. Use myMock := NewMockUUIDGenerator().")
}
params := []pegomock.Param{}
result := pegomock.GetGenericMockFrom(mock).Invoke("GenerateUUID", params, []reflect.Type{reflect.TypeOf((*string)(nil)).Elem()})
var ret0 string
if len(result) != 0 {
if result[0] != nil {
ret0 = result[0].(string)
}
}
return ret0
}
func (mock *MockUUIDGenerator) VerifyWasCalledOnce() *VerifierMockUUIDGenerator {
return &VerifierMockUUIDGenerator{
mock: mock,
invocationCountMatcher: pegomock.Times(1),
}
}
func (mock *MockUUIDGenerator) VerifyWasCalled(invocationCountMatcher pegomock.InvocationCountMatcher) *VerifierMockUUIDGenerator {
return &VerifierMockUUIDGenerator{
mock: mock,
invocationCountMatcher: invocationCountMatcher,
}
}
func (mock *MockUUIDGenerator) VerifyWasCalledInOrder(invocationCountMatcher pegomock.InvocationCountMatcher, inOrderContext *pegomock.InOrderContext) *VerifierMockUUIDGenerator {
return &VerifierMockUUIDGenerator{
mock: mock,
invocationCountMatcher: invocationCountMatcher,
inOrderContext: inOrderContext,
}
}
func (mock *MockUUIDGenerator) VerifyWasCalledEventually(invocationCountMatcher pegomock.InvocationCountMatcher, timeout time.Duration) *VerifierMockUUIDGenerator {
return &VerifierMockUUIDGenerator{
mock: mock,
invocationCountMatcher: invocationCountMatcher,
timeout: timeout,
}
}
type VerifierMockUUIDGenerator struct {
mock *MockUUIDGenerator
invocationCountMatcher pegomock.InvocationCountMatcher
inOrderContext *pegomock.InOrderContext
timeout time.Duration
}
func (verifier *VerifierMockUUIDGenerator) GenerateUUID() *MockUUIDGenerator_GenerateUUID_OngoingVerification {
params := []pegomock.Param{}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "GenerateUUID", params, verifier.timeout)
return &MockUUIDGenerator_GenerateUUID_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}
type MockUUIDGenerator_GenerateUUID_OngoingVerification struct {
mock *MockUUIDGenerator
methodInvocations []pegomock.MethodInvocation
}
func (c *MockUUIDGenerator_GenerateUUID_OngoingVerification) GetCapturedArguments() {
}
func (c *MockUUIDGenerator_GenerateUUID_OngoingVerification) GetAllCapturedArguments() {
}

View File

@@ -526,4 +526,6 @@ type WorkflowHookCommandContext struct {
// 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
// UUID for reference
HookID string
}

View File

@@ -1,6 +1,9 @@
package events
import (
"fmt"
"github.com/google/uuid"
"github.com/runatlantis/atlantis/server/core/config/valid"
"github.com/runatlantis/atlantis/server/core/runtime"
"github.com/runatlantis/atlantis/server/events/command"
@@ -8,6 +11,13 @@ import (
"github.com/runatlantis/atlantis/server/events/vcs"
)
//go:generate pegomock generate -m --use-experimental-model-gen --package mocks -o mocks/mock_post_workflow_hook_url_generator.go PostWorkflowHookURLGenerator
// PostWorkflowHookURLGenerator generates urls to view the post workflow progress.
type PostWorkflowHookURLGenerator interface {
GenerateProjectWorkflowHookURL(hookID string) (string, error)
}
//go:generate pegomock generate -m --use-experimental-model-gen --package mocks -o mocks/mock_post_workflows_hooks_command_runner.go PostWorkflowHooksCommandRunner
type PostWorkflowHooksCommandRunner interface {
@@ -21,6 +31,8 @@ type DefaultPostWorkflowHooksCommandRunner struct {
WorkingDir WorkingDir
GlobalCfg valid.GlobalCfg
PostWorkflowHookRunner runtime.PostWorkflowHookRunner
CommitStatusUpdater CommitStatusUpdater
Router PostWorkflowHookURLGenerator
}
// RunPostHooks runs post_workflow_hooks after a plan/apply has completed
@@ -73,6 +85,7 @@ func (w *DefaultPostWorkflowHooksCommandRunner) RunPostHooks(
User: user,
Verbose: false,
EscapedCommentArgs: escapedArgs,
HookID: uuid.NewString(),
},
postWorkflowHooks, repoDir)
@@ -89,13 +102,33 @@ func (w *DefaultPostWorkflowHooksCommandRunner) runHooks(
repoDir string,
) error {
for _, hook := range postWorkflowHooks {
_, err := w.PostWorkflowHookRunner.Run(ctx, hook.RunCommand, repoDir)
for i, hook := range postWorkflowHooks {
hookDescription := hook.StepDescription
if hookDescription == "" {
hookDescription = fmt.Sprintf("Post workflow hook #%d", i)
}
url, err := w.Router.GenerateProjectWorkflowHookURL(ctx.HookID)
if err != nil {
return err
}
}
if err := w.CommitStatusUpdater.UpdatePostWorkflowHook(ctx.Pull, models.PendingCommitStatus, hookDescription, "", url); err != nil {
ctx.Log.Warn("unable to update post workflow hook status: %s", err)
}
_, runtimeDesc, err := w.PostWorkflowHookRunner.Run(ctx, hook.RunCommand, repoDir)
if err != nil {
if err := w.CommitStatusUpdater.UpdatePostWorkflowHook(ctx.Pull, models.FailedCommitStatus, hookDescription, runtimeDesc, url); err != nil {
ctx.Log.Warn("unable to update post workflow hook status: %s", err)
}
return err
}
if err := w.CommitStatusUpdater.UpdatePostWorkflowHook(ctx.Pull, models.SuccessCommitStatus, hookDescription, runtimeDesc, url); err != nil {
ctx.Log.Warn("unable to update post workflow hook status: %s", err)
}
}
return nil
}

View File

@@ -4,7 +4,9 @@ import (
"errors"
"testing"
"github.com/google/uuid"
runtime_mocks "github.com/runatlantis/atlantis/server/core/runtime/mocks"
runtimematchers "github.com/runatlantis/atlantis/server/core/runtime/mocks/matchers"
. "github.com/petergtz/pegomock"
"github.com/runatlantis/atlantis/server/core/config/valid"
@@ -22,6 +24,7 @@ var postWh events.DefaultPostWorkflowHooksCommandRunner
var postWhWorkingDir *mocks.MockWorkingDir
var postWhWorkingDirLocker *mocks.MockWorkingDirLocker
var whPostWorkflowHookRunner *runtime_mocks.MockPostWorkflowHookRunner
var postCommitStatusUpdater *mocks.MockCommitStatusUpdater
func postWorkflowHooksSetup(t *testing.T) {
RegisterMockTestingT(t)
@@ -29,12 +32,16 @@ func postWorkflowHooksSetup(t *testing.T) {
postWhWorkingDir = mocks.NewMockWorkingDir()
postWhWorkingDirLocker = mocks.NewMockWorkingDirLocker()
whPostWorkflowHookRunner = runtime_mocks.NewMockPostWorkflowHookRunner()
postCommitStatusUpdater = mocks.NewMockCommitStatusUpdater()
postWorkflowHookURLGenerator := mocks.NewMockPostWorkflowHookURLGenerator()
postWh = events.DefaultPostWorkflowHooksCommandRunner{
VCSClient: vcsClient,
WorkingDirLocker: postWhWorkingDirLocker,
WorkingDir: postWhWorkingDir,
PostWorkflowHookRunner: whPostWorkflowHookRunner,
CommitStatusUpdater: postCommitStatusUpdater,
Router: postWorkflowHookURLGenerator,
}
}
@@ -57,6 +64,10 @@ func TestRunPostHooks_Clone(t *testing.T) {
RunCommand: "some command",
}
repoDir := "path/to/repo"
result := "some result"
runtimeDesc := ""
pCtx := models.WorkflowHookCommandContext{
BaseRepo: fixtures.GithubRepo,
HeadRepo: fixtures.GithubRepo,
@@ -64,11 +75,9 @@ func TestRunPostHooks_Clone(t *testing.T) {
Log: log,
User: fixtures.User,
Verbose: false,
HookID: uuid.NewString(),
}
repoDir := "path/to/repo"
result := "some result"
t.Run("success hooks in cfg", func(t *testing.T) {
postWorkflowHooksSetup(t)
@@ -92,12 +101,12 @@ 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, nil)
When(whPostWorkflowHookRunner.Run(pCtx, testHook.RunCommand, repoDir)).ThenReturn(result, nil)
When(whPostWorkflowHookRunner.Run(pCtx, testHook.RunCommand, repoDir)).ThenReturn(result, runtimeDesc, nil)
err := postWh.RunPostHooks(ctx, nil)
Ok(t, err)
whPostWorkflowHookRunner.VerifyWasCalledOnce().Run(pCtx, testHook.RunCommand, repoDir)
whPostWorkflowHookRunner.VerifyWasCalledOnce().Run(runtimematchers.AnyModelsWorkflowHookCommandContext(), EqString(testHook.RunCommand), EqString(repoDir))
Assert(t, *unlockCalled == true, "unlock function called")
})
t.Run("success hooks not in cfg", func(t *testing.T) {
@@ -209,7 +218,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, nil)
When(whPostWorkflowHookRunner.Run(pCtx, testHook.RunCommand, repoDir)).ThenReturn(result, errors.New("some error"))
When(whPostWorkflowHookRunner.Run(runtimematchers.AnyModelsWorkflowHookCommandContext(), EqString(testHook.RunCommand), EqString(repoDir))).ThenReturn(result, runtimeDesc, errors.New("some error"))
err := postWh.RunPostHooks(ctx, nil)
@@ -247,12 +256,12 @@ 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, nil)
When(whPostWorkflowHookRunner.Run(pCtx, testHook.RunCommand, repoDir)).ThenReturn(result, nil)
When(whPostWorkflowHookRunner.Run(runtimematchers.AnyModelsWorkflowHookCommandContext(), EqString(testHook.RunCommand), EqString(repoDir))).ThenReturn(result, runtimeDesc, nil)
err := postWh.RunPostHooks(ctx, cmd)
Ok(t, err)
whPostWorkflowHookRunner.VerifyWasCalledOnce().Run(expectedCtx, testHook.RunCommand, repoDir)
whPostWorkflowHookRunner.VerifyWasCalledOnce().Run(runtimematchers.AnyModelsWorkflowHookCommandContext(), EqString(testHook.RunCommand), EqString(repoDir))
Assert(t, *unlockCalled == true, "unlock function called")
})
}

View File

@@ -1,6 +1,9 @@
package events
import (
"fmt"
"github.com/google/uuid"
"github.com/runatlantis/atlantis/server/core/config/valid"
"github.com/runatlantis/atlantis/server/core/runtime"
"github.com/runatlantis/atlantis/server/events/command"
@@ -8,6 +11,13 @@ import (
"github.com/runatlantis/atlantis/server/events/vcs"
)
//go:generate pegomock generate -m --use-experimental-model-gen --package mocks -o mocks/mock_pre_workflow_hook_url_generator.go PreWorkflowHookURLGenerator
// PreWorkflowHookURLGenerator generates urls to view the pre workflow progress.
type PreWorkflowHookURLGenerator interface {
GenerateProjectWorkflowHookURL(hookID string) (string, error)
}
//go:generate pegomock generate -m --use-experimental-model-gen --package mocks -o mocks/mock_pre_workflows_hooks_command_runner.go PreWorkflowHooksCommandRunner
type PreWorkflowHooksCommandRunner interface {
@@ -21,6 +31,8 @@ type DefaultPreWorkflowHooksCommandRunner struct {
WorkingDir WorkingDir
GlobalCfg valid.GlobalCfg
PreWorkflowHookRunner runtime.PreWorkflowHookRunner
CommitStatusUpdater CommitStatusUpdater
Router PreWorkflowHookURLGenerator
}
// RunPreHooks runs pre_workflow_hooks when PR is opened or updated.
@@ -71,6 +83,7 @@ func (w *DefaultPreWorkflowHooksCommandRunner) RunPreHooks(ctx *command.Context,
User: user,
Verbose: false,
EscapedCommentArgs: escapedArgs,
HookID: uuid.NewString(),
},
preWorkflowHooks, repoDir)
@@ -86,11 +99,33 @@ func (w *DefaultPreWorkflowHooksCommandRunner) runHooks(
preWorkflowHooks []*valid.WorkflowHook,
repoDir string,
) error {
for i, hook := range preWorkflowHooks {
hookDescription := hook.StepDescription
if hookDescription == "" {
hookDescription = fmt.Sprintf("Pre workflow hook #%d", i)
}
for _, hook := range preWorkflowHooks {
_, err := w.PreWorkflowHookRunner.Run(ctx, hook.RunCommand, repoDir)
url, err := w.Router.GenerateProjectWorkflowHookURL(ctx.HookID)
if err != nil {
return err
}
if err := w.CommitStatusUpdater.UpdatePreWorkflowHook(ctx.Pull, models.PendingCommitStatus, hookDescription, "", url); err != nil {
ctx.Log.Warn("unable to pre workflow hook status: %s", err)
return err
}
_, runtimeDesc, err := w.PreWorkflowHookRunner.Run(ctx, hook.RunCommand, repoDir)
if err != nil {
if err := w.CommitStatusUpdater.UpdatePreWorkflowHook(ctx.Pull, models.FailedCommitStatus, hookDescription, runtimeDesc, url); err != nil {
ctx.Log.Warn("unable to pre workflow hook status: %s", err)
}
return err
}
if err := w.CommitStatusUpdater.UpdatePreWorkflowHook(ctx.Pull, models.SuccessCommitStatus, hookDescription, runtimeDesc, url); err != nil {
ctx.Log.Warn("unable to pre workflow hook status: %s", err)
return err
}
}

View File

@@ -7,6 +7,7 @@ import (
. "github.com/petergtz/pegomock"
"github.com/runatlantis/atlantis/server/core/config/valid"
runtime_mocks "github.com/runatlantis/atlantis/server/core/runtime/mocks"
runtimematchers "github.com/runatlantis/atlantis/server/core/runtime/mocks/matchers"
"github.com/runatlantis/atlantis/server/events"
"github.com/runatlantis/atlantis/server/events/command"
"github.com/runatlantis/atlantis/server/events/mocks"
@@ -21,6 +22,7 @@ var preWh events.DefaultPreWorkflowHooksCommandRunner
var preWhWorkingDir *mocks.MockWorkingDir
var preWhWorkingDirLocker *mocks.MockWorkingDirLocker
var whPreWorkflowHookRunner *runtime_mocks.MockPreWorkflowHookRunner
var preCommitStatusUpdater *mocks.MockCommitStatusUpdater
func preWorkflowHooksSetup(t *testing.T) {
RegisterMockTestingT(t)
@@ -28,12 +30,16 @@ func preWorkflowHooksSetup(t *testing.T) {
preWhWorkingDir = mocks.NewMockWorkingDir()
preWhWorkingDirLocker = mocks.NewMockWorkingDirLocker()
whPreWorkflowHookRunner = runtime_mocks.NewMockPreWorkflowHookRunner()
preCommitStatusUpdater = mocks.NewMockCommitStatusUpdater()
preWorkflowHookURLGenerator := mocks.NewMockPreWorkflowHookURLGenerator()
preWh = events.DefaultPreWorkflowHooksCommandRunner{
VCSClient: vcsClient,
WorkingDirLocker: preWhWorkingDirLocker,
WorkingDir: preWhWorkingDir,
PreWorkflowHookRunner: whPreWorkflowHookRunner,
CommitStatusUpdater: preCommitStatusUpdater,
Router: preWorkflowHookURLGenerator,
}
}
@@ -60,6 +66,10 @@ func TestRunPreHooks_Clone(t *testing.T) {
RunCommand: "some command",
}
repoDir := "path/to/repo"
result := "some result"
runtimeDesc := ""
pCtx := models.WorkflowHookCommandContext{
BaseRepo: fixtures.GithubRepo,
HeadRepo: fixtures.GithubRepo,
@@ -69,9 +79,6 @@ func TestRunPreHooks_Clone(t *testing.T) {
Verbose: false,
}
repoDir := "path/to/repo"
result := "some result"
t.Run("success hooks in cfg", func(t *testing.T) {
preWorkflowHooksSetup(t)
@@ -95,14 +102,15 @@ func TestRunPreHooks_Clone(t *testing.T) {
When(preWhWorkingDirLocker.TryLock(fixtures.GithubRepo.FullName, newPull.Num, events.DefaultWorkspace, events.DefaultRepoRelDir)).ThenReturn(unlockFn, nil)
When(preWhWorkingDir.Clone(log, fixtures.GithubRepo, newPull, events.DefaultWorkspace)).ThenReturn(repoDir, false, nil)
When(whPreWorkflowHookRunner.Run(pCtx, testHook.RunCommand, repoDir)).ThenReturn(result, nil)
When(whPreWorkflowHookRunner.Run(runtimematchers.AnyModelsWorkflowHookCommandContext(), EqString(testHook.RunCommand), EqString(repoDir))).ThenReturn(result, runtimeDesc, nil)
err := preWh.RunPreHooks(ctx, nil)
Ok(t, err)
whPreWorkflowHookRunner.VerifyWasCalledOnce().Run(pCtx, testHook.RunCommand, repoDir)
whPreWorkflowHookRunner.VerifyWasCalledOnce().Run(runtimematchers.AnyModelsWorkflowHookCommandContext(), EqString(testHook.RunCommand), EqString(repoDir))
Assert(t, *unlockCalled == true, "unlock function called")
})
t.Run("success hooks not in cfg", func(t *testing.T) {
preWorkflowHooksSetup(t)
globalCfg := valid.GlobalCfg{
@@ -128,10 +136,11 @@ func TestRunPreHooks_Clone(t *testing.T) {
Ok(t, err)
whPreWorkflowHookRunner.VerifyWasCalled(Never()).Run(pCtx, testHook.RunCommand, repoDir)
whPreWorkflowHookRunner.VerifyWasCalled(Never()).Run(runtimematchers.AnyModelsWorkflowHookCommandContext(), EqString(testHook.RunCommand), EqString(repoDir))
preWhWorkingDirLocker.VerifyWasCalled(Never()).TryLock(fixtures.GithubRepo.FullName, newPull.Num, events.DefaultWorkspace)
preWhWorkingDir.VerifyWasCalled(Never()).Clone(log, fixtures.GithubRepo, newPull, events.DefaultWorkspace)
})
t.Run("error locking work dir", func(t *testing.T) {
preWorkflowHooksSetup(t)
@@ -154,7 +163,7 @@ func TestRunPreHooks_Clone(t *testing.T) {
Assert(t, err != nil, "error not nil")
preWhWorkingDir.VerifyWasCalled(Never()).Clone(log, fixtures.GithubRepo, newPull, events.DefaultWorkspace)
whPreWorkflowHookRunner.VerifyWasCalled(Never()).Run(pCtx, testHook.RunCommand, repoDir)
whPreWorkflowHookRunner.VerifyWasCalled(Never()).Run(runtimematchers.AnyModelsWorkflowHookCommandContext(), EqString(testHook.RunCommand), EqString(repoDir))
})
t.Run("error cloning", func(t *testing.T) {
@@ -185,7 +194,7 @@ func TestRunPreHooks_Clone(t *testing.T) {
Assert(t, err != nil, "error not nil")
whPreWorkflowHookRunner.VerifyWasCalled(Never()).Run(pCtx, testHook.RunCommand, repoDir)
whPreWorkflowHookRunner.VerifyWasCalled(Never()).Run(runtimematchers.AnyModelsWorkflowHookCommandContext(), EqString(testHook.RunCommand), EqString(repoDir))
Assert(t, *unlockCalled == true, "unlock function called")
})
@@ -212,7 +221,7 @@ func TestRunPreHooks_Clone(t *testing.T) {
When(preWhWorkingDirLocker.TryLock(fixtures.GithubRepo.FullName, newPull.Num, events.DefaultWorkspace, events.DefaultRepoRelDir)).ThenReturn(unlockFn, nil)
When(preWhWorkingDir.Clone(log, fixtures.GithubRepo, newPull, events.DefaultWorkspace)).ThenReturn(repoDir, false, nil)
When(whPreWorkflowHookRunner.Run(pCtx, testHook.RunCommand, repoDir)).ThenReturn(result, errors.New("some error"))
When(whPreWorkflowHookRunner.Run(runtimematchers.AnyModelsWorkflowHookCommandContext(), EqString(testHook.RunCommand), EqString(repoDir))).ThenReturn(result, runtimeDesc, errors.New("some error"))
err := preWh.RunPreHooks(ctx, nil)
@@ -250,12 +259,12 @@ func TestRunPreHooks_Clone(t *testing.T) {
When(preWhWorkingDirLocker.TryLock(fixtures.GithubRepo.FullName, newPull.Num, events.DefaultWorkspace, events.DefaultRepoRelDir)).ThenReturn(unlockFn, nil)
When(preWhWorkingDir.Clone(log, fixtures.GithubRepo, newPull, events.DefaultWorkspace)).ThenReturn(repoDir, false, nil)
When(whPreWorkflowHookRunner.Run(pCtx, testHook.RunCommand, repoDir)).ThenReturn(result, nil)
When(whPreWorkflowHookRunner.Run(runtimematchers.AnyModelsWorkflowHookCommandContext(), EqString(testHook.RunCommand), EqString(repoDir))).ThenReturn(result, runtimeDesc, nil)
err := preWh.RunPreHooks(ctx, cmd)
Ok(t, err)
whPreWorkflowHookRunner.VerifyWasCalledOnce().Run(expectedCtx, testHook.RunCommand, repoDir)
whPreWorkflowHookRunner.VerifyWasCalledOnce().Run(runtimematchers.AnyModelsWorkflowHookCommandContext(), EqString(testHook.RunCommand), EqString(repoDir))
Assert(t, *unlockCalled == true, "unlock function called")
})
}

View File

@@ -2,9 +2,8 @@
package matchers
import (
"reflect"
"github.com/petergtz/pegomock"
"reflect"
)
func AnyChanOfString() chan string {

View File

@@ -0,0 +1,33 @@
// Code generated by pegomock. DO NOT EDIT.
package matchers
import (
"github.com/petergtz/pegomock"
"reflect"
command "github.com/runatlantis/atlantis/server/events/command"
)
func AnyCommandProjectContext() command.ProjectContext {
pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*(command.ProjectContext))(nil)).Elem()))
var nullValue command.ProjectContext
return nullValue
}
func EqCommandProjectContext(value command.ProjectContext) command.ProjectContext {
pegomock.RegisterMatcher(&pegomock.EqMatcher{Value: value})
var nullValue command.ProjectContext
return nullValue
}
func NotEqCommandProjectContext(value command.ProjectContext) command.ProjectContext {
pegomock.RegisterMatcher(&pegomock.NotEqMatcher{Value: value})
var nullValue command.ProjectContext
return nullValue
}
func CommandProjectContextThat(matcher pegomock.ArgumentMatcher) command.ProjectContext {
pegomock.RegisterMatcher(matcher)
var nullValue command.ProjectContext
return nullValue
}

View File

@@ -2,9 +2,8 @@
package matchers
import (
"reflect"
"github.com/petergtz/pegomock"
"reflect"
jobs "github.com/runatlantis/atlantis/server/jobs"
)

View File

@@ -0,0 +1,33 @@
// Code generated by pegomock. DO NOT EDIT.
package matchers
import (
"github.com/petergtz/pegomock"
"reflect"
models "github.com/runatlantis/atlantis/server/events/models"
)
func AnyModelsWorkflowHookCommandContext() models.WorkflowHookCommandContext {
pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*(models.WorkflowHookCommandContext))(nil)).Elem()))
var nullValue models.WorkflowHookCommandContext
return nullValue
}
func EqModelsWorkflowHookCommandContext(value models.WorkflowHookCommandContext) models.WorkflowHookCommandContext {
pegomock.RegisterMatcher(&pegomock.EqMatcher{Value: value})
var nullValue models.WorkflowHookCommandContext
return nullValue
}
func NotEqModelsWorkflowHookCommandContext(value models.WorkflowHookCommandContext) models.WorkflowHookCommandContext {
pegomock.RegisterMatcher(&pegomock.NotEqMatcher{Value: value})
var nullValue models.WorkflowHookCommandContext
return nullValue
}
func ModelsWorkflowHookCommandContextThat(matcher pegomock.ArgumentMatcher) models.WorkflowHookCommandContext {
pegomock.RegisterMatcher(matcher)
var nullValue models.WorkflowHookCommandContext
return nullValue
}

View File

@@ -4,12 +4,12 @@
package mocks
import (
pegomock "github.com/petergtz/pegomock"
command "github.com/runatlantis/atlantis/server/events/command"
models "github.com/runatlantis/atlantis/server/events/models"
jobs "github.com/runatlantis/atlantis/server/jobs"
"reflect"
"time"
pegomock "github.com/petergtz/pegomock"
"github.com/runatlantis/atlantis/server/events/command"
jobs "github.com/runatlantis/atlantis/server/jobs"
)
type MockProjectCommandOutputHandler struct {
@@ -27,35 +27,43 @@ func NewMockProjectCommandOutputHandler(options ...pegomock.Option) *MockProject
func (mock *MockProjectCommandOutputHandler) SetFailHandler(fh pegomock.FailHandler) { mock.fail = fh }
func (mock *MockProjectCommandOutputHandler) FailHandler() pegomock.FailHandler { return mock.fail }
func (mock *MockProjectCommandOutputHandler) CleanUp(_param0 jobs.PullInfo) {
func (mock *MockProjectCommandOutputHandler) Send(ctx command.ProjectContext, msg string, operationComplete bool) {
if mock == nil {
panic("mock must not be nil. Use myMock := NewMockProjectCommandOutputHandler().")
}
params := []pegomock.Param{_param0}
pegomock.GetGenericMockFrom(mock).Invoke("CleanUp", params, []reflect.Type{})
params := []pegomock.Param{ctx, msg, operationComplete}
pegomock.GetGenericMockFrom(mock).Invoke("Send", params, []reflect.Type{})
}
func (mock *MockProjectCommandOutputHandler) Deregister(_param0 string, _param1 chan string) {
func (mock *MockProjectCommandOutputHandler) SendWorkflowHook(ctx models.WorkflowHookCommandContext, msg string, operationComplete bool) {
if mock == nil {
panic("mock must not be nil. Use myMock := NewMockProjectCommandOutputHandler().")
}
params := []pegomock.Param{_param0, _param1}
params := []pegomock.Param{ctx, msg, operationComplete}
pegomock.GetGenericMockFrom(mock).Invoke("SendWorkflowHook", params, []reflect.Type{})
}
func (mock *MockProjectCommandOutputHandler) Register(jobID string, receiver chan string) {
if mock == nil {
panic("mock must not be nil. Use myMock := NewMockProjectCommandOutputHandler().")
}
params := []pegomock.Param{jobID, receiver}
pegomock.GetGenericMockFrom(mock).Invoke("Register", params, []reflect.Type{})
}
func (mock *MockProjectCommandOutputHandler) Deregister(jobID string, receiver chan string) {
if mock == nil {
panic("mock must not be nil. Use myMock := NewMockProjectCommandOutputHandler().")
}
params := []pegomock.Param{jobID, receiver}
pegomock.GetGenericMockFrom(mock).Invoke("Deregister", params, []reflect.Type{})
}
func (mock *MockProjectCommandOutputHandler) Handle() {
func (mock *MockProjectCommandOutputHandler) IsKeyExists(key string) bool {
if mock == nil {
panic("mock must not be nil. Use myMock := NewMockProjectCommandOutputHandler().")
}
params := []pegomock.Param{}
pegomock.GetGenericMockFrom(mock).Invoke("Handle", params, []reflect.Type{})
}
func (mock *MockProjectCommandOutputHandler) IsKeyExists(_param0 string) bool {
if mock == nil {
panic("mock must not be nil. Use myMock := NewMockProjectCommandOutputHandler().")
}
params := []pegomock.Param{_param0}
params := []pegomock.Param{key}
result := pegomock.GetGenericMockFrom(mock).Invoke("IsKeyExists", params, []reflect.Type{reflect.TypeOf((*bool)(nil)).Elem()})
var ret0 bool
if len(result) != 0 {
@@ -66,20 +74,20 @@ func (mock *MockProjectCommandOutputHandler) IsKeyExists(_param0 string) bool {
return ret0
}
func (mock *MockProjectCommandOutputHandler) Register(_param0 string, _param1 chan string) {
func (mock *MockProjectCommandOutputHandler) Handle() {
if mock == nil {
panic("mock must not be nil. Use myMock := NewMockProjectCommandOutputHandler().")
}
params := []pegomock.Param{_param0, _param1}
pegomock.GetGenericMockFrom(mock).Invoke("Register", params, []reflect.Type{})
params := []pegomock.Param{}
pegomock.GetGenericMockFrom(mock).Invoke("Handle", params, []reflect.Type{})
}
func (mock *MockProjectCommandOutputHandler) Send(_param0 command.ProjectContext, _param1 string, _param2 bool) {
func (mock *MockProjectCommandOutputHandler) CleanUp(pullInfo jobs.PullInfo) {
if mock == nil {
panic("mock must not be nil. Use myMock := NewMockProjectCommandOutputHandler().")
}
params := []pegomock.Param{_param0, _param1, _param2}
pegomock.GetGenericMockFrom(mock).Invoke("Send", params, []reflect.Type{})
params := []pegomock.Param{pullInfo}
pegomock.GetGenericMockFrom(mock).Invoke("CleanUp", params, []reflect.Type{})
}
func (mock *MockProjectCommandOutputHandler) VerifyWasCalledOnce() *VerifierMockProjectCommandOutputHandler {
@@ -119,35 +127,109 @@ type VerifierMockProjectCommandOutputHandler struct {
timeout time.Duration
}
func (verifier *VerifierMockProjectCommandOutputHandler) CleanUp(_param0 jobs.PullInfo) *MockProjectCommandOutputHandler_CleanUp_OngoingVerification {
params := []pegomock.Param{_param0}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "CleanUp", params, verifier.timeout)
return &MockProjectCommandOutputHandler_CleanUp_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
func (verifier *VerifierMockProjectCommandOutputHandler) Send(ctx command.ProjectContext, msg string, operationComplete bool) *MockProjectCommandOutputHandler_Send_OngoingVerification {
params := []pegomock.Param{ctx, msg, operationComplete}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Send", params, verifier.timeout)
return &MockProjectCommandOutputHandler_Send_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}
type MockProjectCommandOutputHandler_CleanUp_OngoingVerification struct {
type MockProjectCommandOutputHandler_Send_OngoingVerification struct {
mock *MockProjectCommandOutputHandler
methodInvocations []pegomock.MethodInvocation
}
func (c *MockProjectCommandOutputHandler_CleanUp_OngoingVerification) GetCapturedArguments() jobs.PullInfo {
_param0 := c.GetAllCapturedArguments()
return _param0[len(_param0)-1]
func (c *MockProjectCommandOutputHandler_Send_OngoingVerification) GetCapturedArguments() (command.ProjectContext, string, bool) {
ctx, msg, operationComplete := c.GetAllCapturedArguments()
return ctx[len(ctx)-1], msg[len(msg)-1], operationComplete[len(operationComplete)-1]
}
func (c *MockProjectCommandOutputHandler_CleanUp_OngoingVerification) GetAllCapturedArguments() (_param0 []jobs.PullInfo) {
func (c *MockProjectCommandOutputHandler_Send_OngoingVerification) GetAllCapturedArguments() (_param0 []command.ProjectContext, _param1 []string, _param2 []bool) {
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
if len(params) > 0 {
_param0 = make([]jobs.PullInfo, len(c.methodInvocations))
_param0 = make([]command.ProjectContext, len(c.methodInvocations))
for u, param := range params[0] {
_param0[u] = param.(jobs.PullInfo)
_param0[u] = param.(command.ProjectContext)
}
_param1 = make([]string, len(c.methodInvocations))
for u, param := range params[1] {
_param1[u] = param.(string)
}
_param2 = make([]bool, len(c.methodInvocations))
for u, param := range params[2] {
_param2[u] = param.(bool)
}
}
return
}
func (verifier *VerifierMockProjectCommandOutputHandler) Deregister(_param0 string, _param1 chan string) *MockProjectCommandOutputHandler_Deregister_OngoingVerification {
params := []pegomock.Param{_param0, _param1}
func (verifier *VerifierMockProjectCommandOutputHandler) SendWorkflowHook(ctx models.WorkflowHookCommandContext, msg string, operationComplete bool) *MockProjectCommandOutputHandler_SendWorkflowHook_OngoingVerification {
params := []pegomock.Param{ctx, msg, operationComplete}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "SendWorkflowHook", params, verifier.timeout)
return &MockProjectCommandOutputHandler_SendWorkflowHook_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}
type MockProjectCommandOutputHandler_SendWorkflowHook_OngoingVerification struct {
mock *MockProjectCommandOutputHandler
methodInvocations []pegomock.MethodInvocation
}
func (c *MockProjectCommandOutputHandler_SendWorkflowHook_OngoingVerification) GetCapturedArguments() (models.WorkflowHookCommandContext, string, bool) {
ctx, msg, operationComplete := c.GetAllCapturedArguments()
return ctx[len(ctx)-1], msg[len(msg)-1], operationComplete[len(operationComplete)-1]
}
func (c *MockProjectCommandOutputHandler_SendWorkflowHook_OngoingVerification) GetAllCapturedArguments() (_param0 []models.WorkflowHookCommandContext, _param1 []string, _param2 []bool) {
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
if len(params) > 0 {
_param0 = make([]models.WorkflowHookCommandContext, len(c.methodInvocations))
for u, param := range params[0] {
_param0[u] = param.(models.WorkflowHookCommandContext)
}
_param1 = make([]string, len(c.methodInvocations))
for u, param := range params[1] {
_param1[u] = param.(string)
}
_param2 = make([]bool, len(c.methodInvocations))
for u, param := range params[2] {
_param2[u] = param.(bool)
}
}
return
}
func (verifier *VerifierMockProjectCommandOutputHandler) Register(jobID string, receiver chan string) *MockProjectCommandOutputHandler_Register_OngoingVerification {
params := []pegomock.Param{jobID, receiver}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Register", params, verifier.timeout)
return &MockProjectCommandOutputHandler_Register_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}
type MockProjectCommandOutputHandler_Register_OngoingVerification struct {
mock *MockProjectCommandOutputHandler
methodInvocations []pegomock.MethodInvocation
}
func (c *MockProjectCommandOutputHandler_Register_OngoingVerification) GetCapturedArguments() (string, chan string) {
jobID, receiver := c.GetAllCapturedArguments()
return jobID[len(jobID)-1], receiver[len(receiver)-1]
}
func (c *MockProjectCommandOutputHandler_Register_OngoingVerification) GetAllCapturedArguments() (_param0 []string, _param1 []chan string) {
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
if len(params) > 0 {
_param0 = make([]string, len(c.methodInvocations))
for u, param := range params[0] {
_param0[u] = param.(string)
}
_param1 = make([]chan string, len(c.methodInvocations))
for u, param := range params[1] {
_param1[u] = param.(chan string)
}
}
return
}
func (verifier *VerifierMockProjectCommandOutputHandler) Deregister(jobID string, receiver chan string) *MockProjectCommandOutputHandler_Deregister_OngoingVerification {
params := []pegomock.Param{jobID, receiver}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Deregister", params, verifier.timeout)
return &MockProjectCommandOutputHandler_Deregister_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}
@@ -158,8 +240,8 @@ type MockProjectCommandOutputHandler_Deregister_OngoingVerification struct {
}
func (c *MockProjectCommandOutputHandler_Deregister_OngoingVerification) GetCapturedArguments() (string, chan string) {
_param0, _param1 := c.GetAllCapturedArguments()
return _param0[len(_param0)-1], _param1[len(_param1)-1]
jobID, receiver := c.GetAllCapturedArguments()
return jobID[len(jobID)-1], receiver[len(receiver)-1]
}
func (c *MockProjectCommandOutputHandler_Deregister_OngoingVerification) GetAllCapturedArguments() (_param0 []string, _param1 []chan string) {
@@ -177,6 +259,33 @@ func (c *MockProjectCommandOutputHandler_Deregister_OngoingVerification) GetAllC
return
}
func (verifier *VerifierMockProjectCommandOutputHandler) IsKeyExists(key string) *MockProjectCommandOutputHandler_IsKeyExists_OngoingVerification {
params := []pegomock.Param{key}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "IsKeyExists", params, verifier.timeout)
return &MockProjectCommandOutputHandler_IsKeyExists_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}
type MockProjectCommandOutputHandler_IsKeyExists_OngoingVerification struct {
mock *MockProjectCommandOutputHandler
methodInvocations []pegomock.MethodInvocation
}
func (c *MockProjectCommandOutputHandler_IsKeyExists_OngoingVerification) GetCapturedArguments() string {
key := c.GetAllCapturedArguments()
return key[len(key)-1]
}
func (c *MockProjectCommandOutputHandler_IsKeyExists_OngoingVerification) GetAllCapturedArguments() (_param0 []string) {
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
if len(params) > 0 {
_param0 = make([]string, len(c.methodInvocations))
for u, param := range params[0] {
_param0[u] = param.(string)
}
}
return
}
func (verifier *VerifierMockProjectCommandOutputHandler) Handle() *MockProjectCommandOutputHandler_Handle_OngoingVerification {
params := []pegomock.Param{}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Handle", params, verifier.timeout)
@@ -194,94 +303,28 @@ func (c *MockProjectCommandOutputHandler_Handle_OngoingVerification) GetCaptured
func (c *MockProjectCommandOutputHandler_Handle_OngoingVerification) GetAllCapturedArguments() {
}
func (verifier *VerifierMockProjectCommandOutputHandler) IsKeyExists(_param0 string) *MockProjectCommandOutputHandler_IsKeyExists_OngoingVerification {
params := []pegomock.Param{_param0}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "IsKeyExists", params, verifier.timeout)
return &MockProjectCommandOutputHandler_IsKeyExists_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
func (verifier *VerifierMockProjectCommandOutputHandler) CleanUp(pullInfo jobs.PullInfo) *MockProjectCommandOutputHandler_CleanUp_OngoingVerification {
params := []pegomock.Param{pullInfo}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "CleanUp", params, verifier.timeout)
return &MockProjectCommandOutputHandler_CleanUp_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}
type MockProjectCommandOutputHandler_IsKeyExists_OngoingVerification struct {
type MockProjectCommandOutputHandler_CleanUp_OngoingVerification struct {
mock *MockProjectCommandOutputHandler
methodInvocations []pegomock.MethodInvocation
}
func (c *MockProjectCommandOutputHandler_IsKeyExists_OngoingVerification) GetCapturedArguments() string {
_param0 := c.GetAllCapturedArguments()
return _param0[len(_param0)-1]
func (c *MockProjectCommandOutputHandler_CleanUp_OngoingVerification) GetCapturedArguments() jobs.PullInfo {
pullInfo := c.GetAllCapturedArguments()
return pullInfo[len(pullInfo)-1]
}
func (c *MockProjectCommandOutputHandler_IsKeyExists_OngoingVerification) GetAllCapturedArguments() (_param0 []string) {
func (c *MockProjectCommandOutputHandler_CleanUp_OngoingVerification) GetAllCapturedArguments() (_param0 []jobs.PullInfo) {
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
if len(params) > 0 {
_param0 = make([]string, len(c.methodInvocations))
_param0 = make([]jobs.PullInfo, len(c.methodInvocations))
for u, param := range params[0] {
_param0[u] = param.(string)
}
}
return
}
func (verifier *VerifierMockProjectCommandOutputHandler) Register(_param0 string, _param1 chan string) *MockProjectCommandOutputHandler_Register_OngoingVerification {
params := []pegomock.Param{_param0, _param1}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Register", params, verifier.timeout)
return &MockProjectCommandOutputHandler_Register_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}
type MockProjectCommandOutputHandler_Register_OngoingVerification struct {
mock *MockProjectCommandOutputHandler
methodInvocations []pegomock.MethodInvocation
}
func (c *MockProjectCommandOutputHandler_Register_OngoingVerification) GetCapturedArguments() (string, chan string) {
_param0, _param1 := c.GetAllCapturedArguments()
return _param0[len(_param0)-1], _param1[len(_param1)-1]
}
func (c *MockProjectCommandOutputHandler_Register_OngoingVerification) GetAllCapturedArguments() (_param0 []string, _param1 []chan string) {
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
if len(params) > 0 {
_param0 = make([]string, len(c.methodInvocations))
for u, param := range params[0] {
_param0[u] = param.(string)
}
_param1 = make([]chan string, len(c.methodInvocations))
for u, param := range params[1] {
_param1[u] = param.(chan string)
}
}
return
}
func (verifier *VerifierMockProjectCommandOutputHandler) Send(_param0 command.ProjectContext, _param1 string, _param2 bool) *MockProjectCommandOutputHandler_Send_OngoingVerification {
params := []pegomock.Param{_param0, _param1, _param2}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Send", params, verifier.timeout)
return &MockProjectCommandOutputHandler_Send_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}
type MockProjectCommandOutputHandler_Send_OngoingVerification struct {
mock *MockProjectCommandOutputHandler
methodInvocations []pegomock.MethodInvocation
}
func (c *MockProjectCommandOutputHandler_Send_OngoingVerification) GetCapturedArguments() (command.ProjectContext, string, bool) {
_param0, _param1, _param2 := c.GetAllCapturedArguments()
return _param0[len(_param0)-1], _param1[len(_param1)-1], _param2[len(_param2)-1]
}
func (c *MockProjectCommandOutputHandler_Send_OngoingVerification) GetAllCapturedArguments() (_param0 []command.ProjectContext, _param1 []string, _param2 []bool) {
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
if len(params) > 0 {
_param0 = make([]command.ProjectContext, len(c.methodInvocations))
for u, param := range params[0] {
_param0[u] = param.(command.ProjectContext)
}
_param1 = make([]string, len(c.methodInvocations))
for u, param := range params[1] {
_param1[u] = param.(string)
}
_param2 = make([]bool, len(c.methodInvocations))
for u, param := range params[2] {
_param2[u] = param.(bool)
_param0[u] = param.(jobs.PullInfo)
}
}
return

View File

@@ -4,6 +4,7 @@ import (
"sync"
"github.com/runatlantis/atlantis/server/events/command"
"github.com/runatlantis/atlantis/server/events/models"
"github.com/runatlantis/atlantis/server/logging"
)
@@ -54,6 +55,8 @@ type ProjectCommandOutputHandler interface {
// Send will enqueue the msg and wait for Handle() to receive the message.
Send(ctx command.ProjectContext, msg string, operationComplete bool)
SendWorkflowHook(ctx models.WorkflowHookCommandContext, msg string, operationComplete bool)
// Register registers a channel and blocks until it is caught up. Callers should call this asynchronously when attempting
// to read the channel in the same goroutine
Register(jobID string, receiver chan string)
@@ -107,6 +110,21 @@ func (p *AsyncProjectCommandOutputHandler) Send(ctx command.ProjectContext, msg
}
}
func (p *AsyncProjectCommandOutputHandler) SendWorkflowHook(ctx models.WorkflowHookCommandContext, msg string, operationComplete bool) {
p.projectCmdOutput <- &ProjectCmdOutputLine{
JobID: ctx.HookID,
JobInfo: JobInfo{
HeadCommit: ctx.Pull.HeadCommit,
PullInfo: PullInfo{
PullNum: ctx.Pull.Num,
Repo: ctx.BaseRepo.Name,
},
},
Line: msg,
OperationComplete: operationComplete,
}
}
func (p *AsyncProjectCommandOutputHandler) Register(jobID string, receiver chan string) {
p.addChan(receiver, jobID)
}
@@ -252,6 +270,9 @@ type NoopProjectOutputHandler struct{}
func (p *NoopProjectOutputHandler) Send(ctx command.ProjectContext, msg string, isOperationComplete bool) {
}
func (p *NoopProjectOutputHandler) SendWorkflowHook(ctx models.WorkflowHookCommandContext, msg string, operationComplete bool) {
}
func (p *NoopProjectOutputHandler) Register(jobID string, receiver chan string) {}
func (p *NoopProjectOutputHandler) Deregister(jobID string, receiver chan string) {}

View File

@@ -52,3 +52,14 @@ func (r *Router) GenerateProjectJobURL(ctx command.ProjectContext) (string, erro
return r.AtlantisURL.String() + jobURL.String(), nil
}
func (r *Router) GenerateProjectWorkflowHookURL(hookID string) (string, error) {
jobURL, err := r.Underlying.Get((r.ProjectJobsViewRouteName)).URL(
"job-id", hookID,
)
if err != nil {
return "", errors.Wrapf(err, "creating workflow hook url for %s", hookID)
}
return r.AtlantisURL.String() + jobURL.String(), nil
}

View File

@@ -519,18 +519,26 @@ func NewServer(userConfig UserConfig, config Config) (*Server, error) {
AtlantisVersion: config.AtlantisVersion,
}
preWorkflowHooksCommandRunner := &events.DefaultPreWorkflowHooksCommandRunner{
VCSClient: vcsClient,
GlobalCfg: globalCfg,
WorkingDirLocker: workingDirLocker,
WorkingDir: workingDir,
PreWorkflowHookRunner: runtime.DefaultPreWorkflowHookRunner{},
VCSClient: vcsClient,
GlobalCfg: globalCfg,
WorkingDirLocker: workingDirLocker,
WorkingDir: workingDir,
PreWorkflowHookRunner: runtime.DefaultPreWorkflowHookRunner{
OutputHandler: projectCmdOutputHandler,
},
CommitStatusUpdater: commitStatusUpdater,
Router: router,
}
postWorkflowHooksCommandRunner := &events.DefaultPostWorkflowHooksCommandRunner{
VCSClient: vcsClient,
GlobalCfg: globalCfg,
WorkingDirLocker: workingDirLocker,
WorkingDir: workingDir,
PostWorkflowHookRunner: runtime.DefaultPostWorkflowHookRunner{},
VCSClient: vcsClient,
GlobalCfg: globalCfg,
WorkingDirLocker: workingDirLocker,
WorkingDir: workingDir,
PostWorkflowHookRunner: runtime.DefaultPostWorkflowHookRunner{
OutputHandler: projectCmdOutputHandler,
},
CommitStatusUpdater: commitStatusUpdater,
Router: router,
}
projectCommandBuilder := events.NewInstrumentedProjectCommandBuilder(
policyChecksEnabled,