diff --git a/server/events/command_handler_test.go b/server/events/command_handler_test.go
index 598ed6e23..65bcf3c6f 100644
--- a/server/events/command_handler_test.go
+++ b/server/events/command_handler_test.go
@@ -33,8 +33,7 @@ import (
. "github.com/runatlantis/atlantis/testing"
)
-var applier *mocks.MockExecutor
-var planner *mocks.MockExecutor
+var operator *mocks.MockPullRequestOperator
var eventParsing *mocks.MockEventParsing
var vcsClient *vcsmocks.MockClientProxy
var ghStatus *mocks.MockCommitStatusUpdater
@@ -46,8 +45,7 @@ var logBytes *bytes.Buffer
func setup(t *testing.T) {
RegisterMockTestingT(t)
- applier = mocks.NewMockExecutor()
- planner = mocks.NewMockExecutor()
+ operator = mocks.NewMockPullRequestOperator()
eventParsing = mocks.NewMockEventParsing()
ghStatus = mocks.NewMockCommitStatusUpdater()
workspaceLocker = mocks.NewMockAtlantisWorkspaceLocker()
@@ -58,8 +56,6 @@ func setup(t *testing.T) {
logBytes = new(bytes.Buffer)
When(logger.Underlying()).ThenReturn(log.New(logBytes, "", 0))
ch = events.CommandHandler{
- PlanExecutor: planner,
- ApplyExecutor: applier,
VCSClient: vcsClient,
CommitStatusUpdater: ghStatus,
EventParser: eventParsing,
@@ -67,9 +63,10 @@ func setup(t *testing.T) {
MarkdownRenderer: &events.MarkdownRenderer{},
GithubPullGetter: githubGetter,
GitlabMergeRequestGetter: gitlabGetter,
- Logger: logger,
- AllowForkPRs: false,
- AllowForkPRsFlag: "allow-fork-prs-flag",
+ Logger: logger,
+ AllowForkPRs: false,
+ AllowForkPRsFlag: "allow-fork-prs-flag",
+ PullRequestOperator: operator,
}
}
@@ -203,9 +200,9 @@ func TestExecuteCommand_FullRun(t *testing.T) {
When(workspaceLocker.TryLock(fixtures.GithubRepo.FullName, cmd.Workspace, fixtures.Pull.Num)).ThenReturn(true)
switch c {
case events.Plan:
- When(planner.Execute(matchers.AnyPtrToEventsCommandContext())).ThenReturn(cmdResponse)
+ When(operator.PlanViaComment(matchers.AnyPtrToEventsCommandContext())).ThenReturn(cmdResponse)
case events.Apply:
- When(applier.Execute(matchers.AnyPtrToEventsCommandContext())).ThenReturn(cmdResponse)
+ When(operator.ApplyViaComment(matchers.AnyPtrToEventsCommandContext())).ThenReturn(cmdResponse)
}
ch.ExecuteCommand(fixtures.GithubRepo, fixtures.GithubRepo, fixtures.User, fixtures.Pull.Num, &cmd)
@@ -238,7 +235,7 @@ func TestExecuteCommand_ForkPREnabled(t *testing.T) {
headRepo.Owner = "forkrepo"
When(eventParsing.ParseGithubPull(&pull)).ThenReturn(fixtures.Pull, headRepo, nil)
When(workspaceLocker.TryLock(fixtures.GithubRepo.FullName, cmd.Workspace, fixtures.Pull.Num)).ThenReturn(true)
- When(planner.Execute(matchers.AnyPtrToEventsCommandContext())).ThenReturn(cmdResponse)
+ When(operator.PlanViaComment(matchers.AnyPtrToEventsCommandContext())).ThenReturn(cmdResponse)
ch.ExecuteCommand(fixtures.GithubRepo, models.Repo{} /* this isn't used */, fixtures.User, fixtures.Pull.Num, &cmd)
diff --git a/server/events/markdown_renderer_test.go b/server/events/markdown_renderer_test.go
index 287996ea4..414d30081 100644
--- a/server/events/markdown_renderer_test.go
+++ b/server/events/markdown_renderer_test.go
@@ -125,9 +125,11 @@ func TestRenderProjectResults(t *testing.T) {
TerraformOutput: "terraform-output",
LockURL: "lock-url",
},
+ Workspace: "workspace",
+ Path: "path",
},
},
- "```diff\nterraform-output\n```\n\n* To **discard** this plan click [here](lock-url).\n\n",
+ "Ran Plan in dir: `path` workspace: `workspace`\n```diff\nterraform-output\n```\n\n* To **discard** this plan click [here](lock-url).\n\n",
},
{
"single successful apply",
@@ -135,30 +137,34 @@ func TestRenderProjectResults(t *testing.T) {
[]events.ProjectResult{
{
ApplySuccess: "success",
+ Workspace: "workspace",
+ Path: "path",
},
},
- "```diff\nsuccess\n```\n\n",
+ "Ran Apply in dir: `path` workspace: `workspace`\n```diff\nsuccess\n```\n\n",
},
{
"multiple successful plans",
events.Plan,
[]events.ProjectResult{
{
- Path: "path",
+ Workspace: "workspace",
+ Path: "path",
PlanSuccess: &events.PlanSuccess{
TerraformOutput: "terraform-output",
LockURL: "lock-url",
},
},
{
- Path: "path2",
+ Workspace: "workspace",
+ Path: "path2",
PlanSuccess: &events.PlanSuccess{
TerraformOutput: "terraform-output2",
LockURL: "lock-url2",
},
},
},
- "Ran Plan in 2 directories:\n * `path`\n * `path2`\n\n## path/\n```diff\nterraform-output\n```\n\n* To **discard** this plan click [here](lock-url).\n---\n## path2/\n```diff\nterraform-output2\n```\n\n* To **discard** this plan click [here](lock-url2).\n---\n\n",
+ "Ran Plan for 2 projects:\n1. workspace: `workspace` path: `path`\n1. workspace: `workspace` path: `path2`\n\n### 1. workspace: `workspace` path: `path`\n```diff\nterraform-output\n```\n\n* To **discard** this plan click [here](lock-url).\n---\n### 2. workspace: `workspace` path: `path2`\n```diff\nterraform-output2\n```\n\n* To **discard** this plan click [here](lock-url2).\n---\n\n",
},
{
"multiple successful applies",
@@ -166,75 +172,87 @@ func TestRenderProjectResults(t *testing.T) {
[]events.ProjectResult{
{
Path: "path",
+ Workspace: "workspace",
ApplySuccess: "success",
},
{
Path: "path2",
+ Workspace: "workspace",
ApplySuccess: "success2",
},
},
- "Ran Apply in 2 directories:\n * `path`\n * `path2`\n\n## path/\n```diff\nsuccess\n```\n---\n## path2/\n```diff\nsuccess2\n```\n---\n\n",
+ "Ran Apply for 2 projects:\n1. workspace: `workspace` path: `path`\n1. workspace: `workspace` path: `path2`\n\n### 1. workspace: `workspace` path: `path`\n```diff\nsuccess\n```\n---\n### 2. workspace: `workspace` path: `path2`\n```diff\nsuccess2\n```\n---\n\n",
},
{
"single errored plan",
events.Plan,
[]events.ProjectResult{
{
- Error: errors.New("error"),
+ Error: errors.New("error"),
+ Path: "path",
+ Workspace: "workspace",
},
},
- "**Plan Error**\n```\nerror\n```\n\n\n",
+ "Ran Plan in dir: `path` workspace: `workspace`\n**Plan Error**\n```\nerror\n```\n\n\n",
},
{
"single failed plan",
events.Plan,
[]events.ProjectResult{
{
- Failure: "failure",
+ Path: "path",
+ Workspace: "workspace",
+ Failure: "failure",
},
},
- "**Plan Failed**: failure\n\n\n",
+ "Ran Plan in dir: `path` workspace: `workspace`\n**Plan Failed**: failure\n\n\n",
},
{
"successful, failed, and errored plan",
events.Plan,
[]events.ProjectResult{
{
- Path: "path",
+ Workspace: "workspace",
+ Path: "path",
PlanSuccess: &events.PlanSuccess{
TerraformOutput: "terraform-output",
LockURL: "lock-url",
},
},
{
- Path: "path2",
- Failure: "failure",
+ Workspace: "workspace",
+ Path: "path2",
+ Failure: "failure",
},
{
- Path: "path3",
- Error: errors.New("error"),
+ Workspace: "workspace",
+ Path: "path3",
+ Error: errors.New("error"),
},
},
- "Ran Plan in 3 directories:\n * `path`\n * `path2`\n * `path3`\n\n## path/\n```diff\nterraform-output\n```\n\n* To **discard** this plan click [here](lock-url).\n---\n## path2/\n**Plan Failed**: failure\n\n---\n## path3/\n**Plan Error**\n```\nerror\n```\n\n---\n\n",
+ "Ran Plan for 3 projects:\n1. workspace: `workspace` path: `path`\n1. workspace: `workspace` path: `path2`\n1. workspace: `workspace` path: `path3`\n\n### 1. workspace: `workspace` path: `path`\n```diff\nterraform-output\n```\n\n* To **discard** this plan click [here](lock-url).\n---\n### 2. workspace: `workspace` path: `path2`\n**Plan Failed**: failure\n\n---\n### 3. workspace: `workspace` path: `path3`\n**Plan Error**\n```\nerror\n```\n\n---\n\n",
},
{
"successful, failed, and errored apply",
events.Apply,
[]events.ProjectResult{
{
+ Workspace: "workspace",
Path: "path",
ApplySuccess: "success",
},
{
- Path: "path2",
- Failure: "failure",
+ Workspace: "workspace",
+ Path: "path2",
+ Failure: "failure",
},
{
- Path: "path3",
- Error: errors.New("error"),
+ Workspace: "workspace",
+ Path: "path3",
+ Error: errors.New("error"),
},
},
- "Ran Apply in 3 directories:\n * `path`\n * `path2`\n * `path3`\n\n## path/\n```diff\nsuccess\n```\n---\n## path2/\n**Apply Failed**: failure\n\n---\n## path3/\n**Apply Error**\n```\nerror\n```\n\n---\n\n",
+ "Ran Apply for 3 projects:\n1. workspace: `workspace` path: `path`\n1. workspace: `workspace` path: `path2`\n1. workspace: `workspace` path: `path3`\n\n### 1. workspace: `workspace` path: `path`\n```diff\nsuccess\n```\n---\n### 2. workspace: `workspace` path: `path2`\n**Apply Failed**: failure\n\n---\n### 3. workspace: `workspace` path: `path3`\n**Apply Error**\n```\nerror\n```\n\n---\n\n",
},
}
@@ -244,13 +262,14 @@ func TestRenderProjectResults(t *testing.T) {
ProjectResults: c.ProjectResults,
}
for _, verbose := range []bool{true, false} {
- t.Log("testing " + c.Description)
- s := r.Render(res, c.Command, "log", verbose)
- if !verbose {
- Equals(t, c.Expected, s)
- } else {
- Equals(t, c.Expected+"Log
\n \n\n```\nlog```\n
\n", s)
- }
+ t.Run(c.Description, func(t *testing.T) {
+ s := r.Render(res, c.Command, "log", verbose)
+ if !verbose {
+ Equals(t, c.Expected, s)
+ } else {
+ Equals(t, c.Expected+"Log
\n \n\n```\nlog```\n
\n", s)
+ }
+ })
}
}
}
diff --git a/server/events/mocks/mock_pull_request_operator.go b/server/events/mocks/mock_pull_request_operator.go
new file mode 100644
index 000000000..443636863
--- /dev/null
+++ b/server/events/mocks/mock_pull_request_operator.go
@@ -0,0 +1,154 @@
+// Automatically generated by pegomock. DO NOT EDIT!
+// Source: github.com/runatlantis/atlantis/server/events (interfaces: PullRequestOperator)
+
+package mocks
+
+import (
+ "reflect"
+
+ pegomock "github.com/petergtz/pegomock"
+ events "github.com/runatlantis/atlantis/server/events"
+)
+
+type MockPullRequestOperator struct {
+ fail func(message string, callerSkip ...int)
+}
+
+func NewMockPullRequestOperator() *MockPullRequestOperator {
+ return &MockPullRequestOperator{fail: pegomock.GlobalFailHandler}
+}
+
+func (mock *MockPullRequestOperator) Autoplan(ctx *events.CommandContext) events.CommandResponse {
+ params := []pegomock.Param{ctx}
+ result := pegomock.GetGenericMockFrom(mock).Invoke("Autoplan", params, []reflect.Type{reflect.TypeOf((*events.CommandResponse)(nil)).Elem()})
+ var ret0 events.CommandResponse
+ if len(result) != 0 {
+ if result[0] != nil {
+ ret0 = result[0].(events.CommandResponse)
+ }
+ }
+ return ret0
+}
+
+func (mock *MockPullRequestOperator) PlanViaComment(ctx *events.CommandContext) events.CommandResponse {
+ params := []pegomock.Param{ctx}
+ result := pegomock.GetGenericMockFrom(mock).Invoke("PlanViaComment", params, []reflect.Type{reflect.TypeOf((*events.CommandResponse)(nil)).Elem()})
+ var ret0 events.CommandResponse
+ if len(result) != 0 {
+ if result[0] != nil {
+ ret0 = result[0].(events.CommandResponse)
+ }
+ }
+ return ret0
+}
+
+func (mock *MockPullRequestOperator) ApplyViaComment(ctx *events.CommandContext) events.CommandResponse {
+ params := []pegomock.Param{ctx}
+ result := pegomock.GetGenericMockFrom(mock).Invoke("ApplyViaComment", params, []reflect.Type{reflect.TypeOf((*events.CommandResponse)(nil)).Elem()})
+ var ret0 events.CommandResponse
+ if len(result) != 0 {
+ if result[0] != nil {
+ ret0 = result[0].(events.CommandResponse)
+ }
+ }
+ return ret0
+}
+
+func (mock *MockPullRequestOperator) VerifyWasCalledOnce() *VerifierPullRequestOperator {
+ return &VerifierPullRequestOperator{mock, pegomock.Times(1), nil}
+}
+
+func (mock *MockPullRequestOperator) VerifyWasCalled(invocationCountMatcher pegomock.Matcher) *VerifierPullRequestOperator {
+ return &VerifierPullRequestOperator{mock, invocationCountMatcher, nil}
+}
+
+func (mock *MockPullRequestOperator) VerifyWasCalledInOrder(invocationCountMatcher pegomock.Matcher, inOrderContext *pegomock.InOrderContext) *VerifierPullRequestOperator {
+ return &VerifierPullRequestOperator{mock, invocationCountMatcher, inOrderContext}
+}
+
+type VerifierPullRequestOperator struct {
+ mock *MockPullRequestOperator
+ invocationCountMatcher pegomock.Matcher
+ inOrderContext *pegomock.InOrderContext
+}
+
+func (verifier *VerifierPullRequestOperator) Autoplan(ctx *events.CommandContext) *PullRequestOperator_Autoplan_OngoingVerification {
+ params := []pegomock.Param{ctx}
+ methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Autoplan", params)
+ return &PullRequestOperator_Autoplan_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
+}
+
+type PullRequestOperator_Autoplan_OngoingVerification struct {
+ mock *MockPullRequestOperator
+ methodInvocations []pegomock.MethodInvocation
+}
+
+func (c *PullRequestOperator_Autoplan_OngoingVerification) GetCapturedArguments() *events.CommandContext {
+ ctx := c.GetAllCapturedArguments()
+ return ctx[len(ctx)-1]
+}
+
+func (c *PullRequestOperator_Autoplan_OngoingVerification) GetAllCapturedArguments() (_param0 []*events.CommandContext) {
+ params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
+ if len(params) > 0 {
+ _param0 = make([]*events.CommandContext, len(params[0]))
+ for u, param := range params[0] {
+ _param0[u] = param.(*events.CommandContext)
+ }
+ }
+ return
+}
+
+func (verifier *VerifierPullRequestOperator) PlanViaComment(ctx *events.CommandContext) *PullRequestOperator_PlanViaComment_OngoingVerification {
+ params := []pegomock.Param{ctx}
+ methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "PlanViaComment", params)
+ return &PullRequestOperator_PlanViaComment_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
+}
+
+type PullRequestOperator_PlanViaComment_OngoingVerification struct {
+ mock *MockPullRequestOperator
+ methodInvocations []pegomock.MethodInvocation
+}
+
+func (c *PullRequestOperator_PlanViaComment_OngoingVerification) GetCapturedArguments() *events.CommandContext {
+ ctx := c.GetAllCapturedArguments()
+ return ctx[len(ctx)-1]
+}
+
+func (c *PullRequestOperator_PlanViaComment_OngoingVerification) GetAllCapturedArguments() (_param0 []*events.CommandContext) {
+ params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
+ if len(params) > 0 {
+ _param0 = make([]*events.CommandContext, len(params[0]))
+ for u, param := range params[0] {
+ _param0[u] = param.(*events.CommandContext)
+ }
+ }
+ return
+}
+
+func (verifier *VerifierPullRequestOperator) ApplyViaComment(ctx *events.CommandContext) *PullRequestOperator_ApplyViaComment_OngoingVerification {
+ params := []pegomock.Param{ctx}
+ methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "ApplyViaComment", params)
+ return &PullRequestOperator_ApplyViaComment_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
+}
+
+type PullRequestOperator_ApplyViaComment_OngoingVerification struct {
+ mock *MockPullRequestOperator
+ methodInvocations []pegomock.MethodInvocation
+}
+
+func (c *PullRequestOperator_ApplyViaComment_OngoingVerification) GetCapturedArguments() *events.CommandContext {
+ ctx := c.GetAllCapturedArguments()
+ return ctx[len(ctx)-1]
+}
+
+func (c *PullRequestOperator_ApplyViaComment_OngoingVerification) GetAllCapturedArguments() (_param0 []*events.CommandContext) {
+ params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
+ if len(params) > 0 {
+ _param0 = make([]*events.CommandContext, len(params[0]))
+ for u, param := range params[0] {
+ _param0[u] = param.(*events.CommandContext)
+ }
+ }
+ return
+}
diff --git a/server/events/pull_request_operator.go b/server/events/pull_request_operator.go
index 61218e902..b393fb5b7 100644
--- a/server/events/pull_request_operator.go
+++ b/server/events/pull_request_operator.go
@@ -12,7 +12,15 @@ import (
"github.com/runatlantis/atlantis/server/logging"
)
-type PullRequestOperator struct {
+//go:generate pegomock generate -m --use-experimental-model-gen --package mocks -o mocks/mock_pull_request_operator.go PullRequestOperator
+
+type PullRequestOperator interface {
+ Autoplan(ctx *CommandContext) CommandResponse
+ PlanViaComment(ctx *CommandContext) CommandResponse
+ ApplyViaComment(ctx *CommandContext) CommandResponse
+}
+
+type DefaultPullRequestOperator struct {
TerraformExecutor TerraformExec
DefaultTFVersion *version.Version
ParserValidator *yaml.ParserValidator
@@ -26,7 +34,7 @@ type TerraformExec interface {
RunCommandWithVersion(log *logging.SimpleLogger, path string, args []string, v *version.Version, workspace string) (string, error)
}
-func (p *PullRequestOperator) Autoplan(ctx *CommandContext) CommandResponse {
+func (p *DefaultPullRequestOperator) Autoplan(ctx *CommandContext) CommandResponse {
// check out repo to parse atlantis.yaml
// this will check out the repo to a * dir
repoDir, err := p.Workspace.Clone(ctx.Log, ctx.BaseRepo, ctx.HeadRepo, ctx.Pull, ctx.Command.Workspace)
@@ -99,7 +107,7 @@ func (p *PullRequestOperator) Autoplan(ctx *CommandContext) CommandResponse {
return CommandResponse{ProjectResults: results}
}
-func (p *PullRequestOperator) PlanViaComment(ctx *CommandContext) CommandResponse {
+func (p *DefaultPullRequestOperator) PlanViaComment(ctx *CommandContext) CommandResponse {
repoDir, err := p.Workspace.Clone(ctx.Log, ctx.BaseRepo, ctx.HeadRepo, ctx.Pull, ctx.Command.Workspace)
if err != nil {
return CommandResponse{Error: err}
@@ -141,7 +149,7 @@ func (p *PullRequestOperator) PlanViaComment(ctx *CommandContext) CommandRespons
}
}
-func (p *PullRequestOperator) ApplyViaComment(ctx *CommandContext) CommandResponse {
+func (p *DefaultPullRequestOperator) ApplyViaComment(ctx *CommandContext) CommandResponse {
repoDir, err := p.Workspace.GetWorkspace(ctx.BaseRepo, ctx.Pull, ctx.Command.Workspace)
if err != nil {
return CommandResponse{Failure: "No workspace found. Did you run plan?"}
@@ -185,7 +193,7 @@ func (p *PullRequestOperator) ApplyViaComment(ctx *CommandContext) CommandRespon
// matchingProjects returns the list of projects whose WhenModified fields match
// any of the modifiedFiles.
-func (p *PullRequestOperator) matchingProjects(modifiedFiles []string, config valid.Spec) []valid.Project {
+func (p *DefaultPullRequestOperator) matchingProjects(modifiedFiles []string, config valid.Spec) []valid.Project {
//todo
// match the modified files against the config
// remember the modified_files paths are relative to the project paths
diff --git a/server/events/pull_request_operator_test.go b/server/events/pull_request_operator_test.go
index 4bbdfd14b..79457f0dd 100644
--- a/server/events/pull_request_operator_test.go
+++ b/server/events/pull_request_operator_test.go
@@ -1,199 +1 @@
package events_test
-
-import (
- "io/ioutil"
- "path/filepath"
- "testing"
-
- "github.com/hashicorp/go-version"
- "github.com/runatlantis/atlantis/server/events"
- "github.com/runatlantis/atlantis/server/events/runtime"
- "github.com/runatlantis/atlantis/server/logging"
- . "github.com/runatlantis/atlantis/testing"
-)
-
-// When there is no config file, should use the defaults.
-func TestBuildStage_NoConfigFile(t *testing.T) {
- var defaultTFVersion *version.Version
- var terraformExecutor runtime.TerraformExec
- e := events.PullRequestOperator{
- DefaultTFVersion: defaultTFVersion,
- TerraformExecutor: terraformExecutor,
- }
-
- log := logging.NewNoopLogger()
- repoDir := "/willnotexist"
- workspace := "myworkspace"
- relProjectPath := "mydir"
- var extraCommentArgs []string
- username := "myuser"
- meta := runtime.StepMeta{
- Log: log,
- Workspace: workspace,
- AbsolutePath: filepath.Join(repoDir, relProjectPath),
- DirRelativeToRepoRoot: relProjectPath,
- TerraformVersion: defaultTFVersion,
- TerraformExecutor: terraformExecutor,
- ExtraCommentArgs: extraCommentArgs,
- Username: username,
- }
-
- // Test the plan stage first.
- t.Run("plan stage", func(t *testing.T) {
- planStage, err := e.BuildPlanStage(log, repoDir, workspace, relProjectPath, extraCommentArgs, username)
- Ok(t, err)
- Equals(t, runtime.PlanStage{
- Steps: []runtime.Step{
- &runtime.InitStep{
- Meta: meta,
- },
- &runtime.PlanStep{
- Meta: meta,
- },
- },
- }, planStage)
- })
-
- // Then the apply stage.
- t.Run("apply stage", func(t *testing.T) {
- applyStage, err := e.BuildApplyStage(log, repoDir, workspace, relProjectPath, extraCommentArgs, username)
- Ok(t, err)
- Equals(t, runtime.ApplyStage{
- Steps: []runtime.Step{
- &runtime.ApplyStep{
- Meta: meta,
- },
- },
- }, *applyStage)
- })
-}
-
-func TestBuildStage(t *testing.T) {
- var defaultTFVersion *version.Version
- var terraformExecutor runtime.TerraformExec
- e := events.PullRequestOperator{
- DefaultTFVersion: defaultTFVersion,
- TerraformExecutor: terraformExecutor,
- }
-
- // Write atlantis.yaml config.
- tmpDir, cleanup := TempDir(t)
- defer cleanup()
- err := ioutil.WriteFile(filepath.Join(tmpDir, "atlantis.yaml"), []byte(`
-version: 2
-projects:
-- dir: "."
- workflow: custom
-workflows:
- custom:
- plan:
- steps:
- - init:
- extra_args: [arg1, arg2]
- - plan
- - run: echo hi
- apply:
- steps:
- - run: prerun
- - apply:
- extra_args: [arg3, arg4]
- - run: postrun
-`), 0644)
- Ok(t, err)
-
- repoDir := tmpDir
- log := logging.NewNoopLogger()
- workspace := "myworkspace"
- // Our config is for '.' so there will be no config for this project.
- relProjectPath := "mydir"
- var extraCommentArgs []string
- username := "myuser"
- meta := runtime.StepMeta{
- Log: log,
- Workspace: workspace,
- AbsolutePath: filepath.Join(repoDir, relProjectPath),
- DirRelativeToRepoRoot: relProjectPath,
- TerraformVersion: defaultTFVersion,
- TerraformExecutor: terraformExecutor,
- ExtraCommentArgs: extraCommentArgs,
- Username: username,
- }
-
- t.Run("plan stage for project without config", func(t *testing.T) {
- // This project isn't listed so it should get the defaults.
- planStage, err := e.BuildPlanStage(log, repoDir, workspace, relProjectPath, extraCommentArgs, username)
- Ok(t, err)
- Equals(t, runtime.PlanStage{
- Steps: []runtime.Step{
- &runtime.InitStep{
- Meta: meta,
- },
- &runtime.PlanStep{
- Meta: meta,
- },
- },
- }, planStage)
- })
-
- t.Run("apply stage for project without config", func(t *testing.T) {
- // This project isn't listed so it should get the defaults.
- applyStage, err := e.BuildApplyStage(log, repoDir, workspace, relProjectPath, extraCommentArgs, username)
- Ok(t, err)
- Equals(t, runtime.ApplyStage{
- Steps: []runtime.Step{
- &runtime.ApplyStep{
- Meta: meta,
- },
- },
- }, *applyStage)
- })
-
- // Create the meta for the custom project.
- customMeta := meta
- customMeta.Workspace = "default"
- customMeta.DirRelativeToRepoRoot = "."
- customMeta.AbsolutePath = tmpDir
-
- t.Run("plan stage for custom config", func(t *testing.T) {
- planStage, err := e.BuildPlanStage(log, repoDir, "default", ".", extraCommentArgs, username)
- Ok(t, err)
-
- Equals(t, runtime.PlanStage{
- Steps: []runtime.Step{
- &runtime.InitStep{
- Meta: customMeta,
- ExtraArgs: []string{"arg1", "arg2"},
- },
- &runtime.PlanStep{
- Meta: customMeta,
- },
- &runtime.RunStep{
- Meta: customMeta,
- Commands: []string{"echo", "hi"},
- },
- },
- }, planStage)
- })
-
- t.Run("apply stage for custom config", func(t *testing.T) {
- planStage, err := e.BuildApplyStage(log, repoDir, "default", ".", extraCommentArgs, username)
- Ok(t, err)
-
- Equals(t, runtime.ApplyStage{
- Steps: []runtime.Step{
- &runtime.RunStep{
- Meta: customMeta,
- Commands: []string{"prerun"},
- },
- &runtime.ApplyStep{
- Meta: customMeta,
- ExtraArgs: []string{"arg3", "arg4"},
- },
- &runtime.RunStep{
- Meta: customMeta,
- Commands: []string{"postrun"},
- },
- },
- }, *planStage)
- })
-}
diff --git a/server/events/runtime/apply_step_operator_test.go b/server/events/runtime/apply_step_operator_test.go
index 862f5e10e..1aad3c9e2 100644
--- a/server/events/runtime/apply_step_operator_test.go
+++ b/server/events/runtime/apply_step_operator_test.go
@@ -8,42 +8,35 @@ import (
"github.com/hashicorp/go-version"
. "github.com/petergtz/pegomock"
"github.com/runatlantis/atlantis/server/events/mocks/matchers"
+ "github.com/runatlantis/atlantis/server/events/models"
matchers2 "github.com/runatlantis/atlantis/server/events/run/mocks/matchers"
"github.com/runatlantis/atlantis/server/events/runtime"
"github.com/runatlantis/atlantis/server/events/terraform/mocks"
+ "github.com/runatlantis/atlantis/server/events/yaml/valid"
. "github.com/runatlantis/atlantis/testing"
)
func TestRun_NoDir(t *testing.T) {
- s := runtime.ApplyStep{
- Meta: runtime.StepMeta{
- Workspace: "workspace",
- AbsolutePath: "nonexistent/path",
- DirRelativeToRepoRoot: ".",
- TerraformVersion: nil,
- ExtraCommentArgs: nil,
- Username: "username",
- },
+ o := runtime.ApplyStepOperator{
+ TerraformExecutor: nil,
}
- _, err := s.Run()
+ _, err := o.Run(models.ProjectCommandContext{
+ RepoRelPath: ".",
+ Workspace: "workspace",
+ }, nil, "/nonexistent/path")
ErrEquals(t, "no plan found at path \".\" and workspace \"workspace\"–did you run plan?", err)
}
func TestRun_NoPlanFile(t *testing.T) {
tmpDir, cleanup := TempDir(t)
defer cleanup()
-
- s := runtime.ApplyStep{
- Meta: runtime.StepMeta{
- Workspace: "workspace",
- AbsolutePath: tmpDir,
- DirRelativeToRepoRoot: ".",
- TerraformVersion: nil,
- ExtraCommentArgs: nil,
- Username: "username",
- },
+ o := runtime.ApplyStepOperator{
+ TerraformExecutor: nil,
}
- _, err := s.Run()
+ _, err := o.Run(models.ProjectCommandContext{
+ RepoRelPath: ".",
+ Workspace: "workspace",
+ }, nil, tmpDir)
ErrEquals(t, "no plan found at path \".\" and workspace \"workspace\"–did you run plan?", err)
}
@@ -56,24 +49,46 @@ func TestRun_Success(t *testing.T) {
RegisterMockTestingT(t)
terraform := mocks.NewMockClient()
-
- tfVersion, _ := version.NewVersion("0.11.4")
- s := runtime.ApplyStep{
- Meta: runtime.StepMeta{
- Workspace: "workspace",
- AbsolutePath: tmpDir,
- DirRelativeToRepoRoot: ".",
- TerraformExecutor: terraform,
- TerraformVersion: tfVersion,
- ExtraCommentArgs: []string{"comment", "args"},
- Username: "username",
- },
- ExtraArgs: []string{"extra", "args"},
+ o := runtime.ApplyStepOperator{
+ TerraformExecutor: terraform,
}
When(terraform.RunCommandWithVersion(matchers.AnyPtrToLoggingSimpleLogger(), AnyString(), AnyStringSlice(), matchers2.AnyPtrToGoVersionVersion(), AnyString())).
ThenReturn("output", nil)
- output, err := s.Run()
+ output, err := o.Run(models.ProjectCommandContext{
+ Workspace: "workspace",
+ RepoRelPath: ".",
+ CommentArgs: []string{"comment", "args"},
+ }, []string{"extra", "args"}, tmpDir)
+ Ok(t, err)
+ Equals(t, "output", output)
+ terraform.VerifyWasCalledOnce().RunCommandWithVersion(nil, tmpDir, []string{"apply", "-no-color", "extra", "args", "comment", "args", planPath}, nil, "workspace")
+}
+
+func TestRun_UsesConfiguredTFVersion(t *testing.T) {
+ tmpDir, cleanup := TempDir(t)
+ defer cleanup()
+ planPath := filepath.Join(tmpDir, "workspace.tfplan")
+ err := ioutil.WriteFile(planPath, nil, 0644)
+ Ok(t, err)
+
+ RegisterMockTestingT(t)
+ terraform := mocks.NewMockClient()
+ o := runtime.ApplyStepOperator{
+ TerraformExecutor: terraform,
+ }
+ tfVersion, _ := version.NewVersion("0.11.0")
+
+ When(terraform.RunCommandWithVersion(matchers.AnyPtrToLoggingSimpleLogger(), AnyString(), AnyStringSlice(), matchers2.AnyPtrToGoVersionVersion(), AnyString())).
+ ThenReturn("output", nil)
+ output, err := o.Run(models.ProjectCommandContext{
+ Workspace: "workspace",
+ RepoRelPath: ".",
+ CommentArgs: []string{"comment", "args"},
+ ProjectConfig: &valid.Project{
+ TerraformVersion: tfVersion,
+ },
+ }, []string{"extra", "args"}, tmpDir)
Ok(t, err)
Equals(t, "output", output)
terraform.VerifyWasCalledOnce().RunCommandWithVersion(nil, tmpDir, []string{"apply", "-no-color", "extra", "args", "comment", "args", planPath}, tfVersion, "workspace")
diff --git a/server/events/runtime/init_step_operator_test.go b/server/events/runtime/init_step_operator_test.go
index 829639497..efbf4ca28 100644
--- a/server/events/runtime/init_step_operator_test.go
+++ b/server/events/runtime/init_step_operator_test.go
@@ -3,9 +3,10 @@ package runtime_test
import (
"testing"
- "github.com/hashicorp/go-version"
+ version "github.com/hashicorp/go-version"
. "github.com/petergtz/pegomock"
"github.com/runatlantis/atlantis/server/events/mocks/matchers"
+ "github.com/runatlantis/atlantis/server/events/models"
matchers2 "github.com/runatlantis/atlantis/server/events/run/mocks/matchers"
"github.com/runatlantis/atlantis/server/events/runtime"
"github.com/runatlantis/atlantis/server/events/terraform/mocks"
@@ -45,15 +46,16 @@ func TestRun_UsesGetOrInitForRightVersion(t *testing.T) {
logger := logging.NewNoopLogger()
iso := runtime.InitStepOperator{
TerraformExecutor: terraform,
+ DefaultTFVersion: tfVersion,
}
When(terraform.RunCommandWithVersion(matchers.AnyPtrToLoggingSimpleLogger(), AnyString(), AnyStringSlice(), matchers2.AnyPtrToGoVersionVersion(), AnyString())).
ThenReturn("output", nil)
- output, err := iso.Run(runtime.ProjectCommandContext{
+
+ output, err := iso.Run(models.ProjectCommandContext{
Log: logger,
Workspace: "workspace",
- AbsPath: "/path",
RepoRelPath: ".",
- }, []string{"extra", "args"})
+ }, []string{"extra", "args"}, "/path")
Ok(t, err)
// Shouldn't return output since we don't print init output to PR.
Equals(t, "", output)
diff --git a/server/events/runtime/plan_step_operater_test.go b/server/events/runtime/plan_step_operater_test.go
index 53b45c2e6..bf80927b6 100644
--- a/server/events/runtime/plan_step_operater_test.go
+++ b/server/events/runtime/plan_step_operater_test.go
@@ -1,7 +1,6 @@
package runtime_test
import (
- "errors"
"io/ioutil"
"os"
"path/filepath"
@@ -9,7 +8,9 @@ import (
"github.com/hashicorp/go-version"
. "github.com/petergtz/pegomock"
+ "github.com/pkg/errors"
"github.com/runatlantis/atlantis/server/events/mocks/matchers"
+ "github.com/runatlantis/atlantis/server/events/models"
matchers2 "github.com/runatlantis/atlantis/server/events/run/mocks/matchers"
"github.com/runatlantis/atlantis/server/events/runtime"
"github.com/runatlantis/atlantis/server/events/terraform/mocks"
@@ -25,23 +26,20 @@ func TestRun_NoWorkspaceIn08(t *testing.T) {
tfVersion, _ := version.NewVersion("0.8")
logger := logging.NewNoopLogger()
workspace := "default"
- s := runtime.PlanStep{
- Meta: runtime.StepMeta{
- Log: logger,
- Workspace: workspace,
- AbsolutePath: "/path",
- DirRelativeToRepoRoot: ".",
- TerraformExecutor: terraform,
- TerraformVersion: tfVersion,
- ExtraCommentArgs: []string{"comment", "args"},
- Username: "username",
- },
- ExtraArgs: []string{"extra", "args"},
+ s := runtime.PlanStepOperator{
+ DefaultTFVersion: tfVersion,
+ TerraformExecutor: terraform,
}
When(terraform.RunCommandWithVersion(matchers.AnyPtrToLoggingSimpleLogger(), AnyString(), AnyStringSlice(), matchers2.AnyPtrToGoVersionVersion(), AnyString())).
ThenReturn("output", nil)
- output, err := s.Run()
+ output, err := s.Run(models.ProjectCommandContext{
+ Log: logger,
+ CommentArgs: []string{"comment", "args"},
+ Workspace: workspace,
+ RepoRelPath: ".",
+ User: models.User{Username: "username"},
+ }, []string{"extra", "args"}, "/path")
Ok(t, err)
Equals(t, "output", output)
@@ -61,23 +59,19 @@ func TestRun_ErrWorkspaceIn08(t *testing.T) {
tfVersion, _ := version.NewVersion("0.8")
logger := logging.NewNoopLogger()
workspace := "notdefault"
- s := runtime.PlanStep{
- Meta: runtime.StepMeta{
- Log: logger,
- Workspace: workspace,
- AbsolutePath: "/path",
- DirRelativeToRepoRoot: ".",
- TerraformExecutor: terraform,
- TerraformVersion: tfVersion,
- ExtraCommentArgs: []string{"comment", "args"},
- Username: "username",
- },
- ExtraArgs: []string{"extra", "args"},
+ s := runtime.PlanStepOperator{
+ TerraformExecutor: terraform,
+ DefaultTFVersion: tfVersion,
}
When(terraform.RunCommandWithVersion(matchers.AnyPtrToLoggingSimpleLogger(), AnyString(), AnyStringSlice(), matchers2.AnyPtrToGoVersionVersion(), AnyString())).
ThenReturn("output", nil)
- _, err := s.Run()
+ _, err := s.Run(models.ProjectCommandContext{
+ Log: logger,
+ Workspace: workspace,
+ RepoRelPath: ".",
+ User: models.User{Username: "username"},
+ }, []string{"extra", "args"}, "/path")
ErrEquals(t, "terraform version 0.8.0 does not support workspaces", err)
}
@@ -112,23 +106,21 @@ func TestRun_SwitchesWorkspace(t *testing.T) {
tfVersion, _ := version.NewVersion(c.tfVersion)
logger := logging.NewNoopLogger()
- s := runtime.PlanStep{
- Meta: runtime.StepMeta{
- Log: logger,
- Workspace: "workspace",
- AbsolutePath: "/path",
- DirRelativeToRepoRoot: ".",
- TerraformExecutor: terraform,
- TerraformVersion: tfVersion,
- ExtraCommentArgs: []string{"comment", "args"},
- Username: "username",
- },
- ExtraArgs: []string{"extra", "args"},
+
+ s := runtime.PlanStepOperator{
+ TerraformExecutor: terraform,
+ DefaultTFVersion: tfVersion,
}
When(terraform.RunCommandWithVersion(matchers.AnyPtrToLoggingSimpleLogger(), AnyString(), AnyStringSlice(), matchers2.AnyPtrToGoVersionVersion(), AnyString())).
ThenReturn("output", nil)
- output, err := s.Run()
+ output, err := s.Run(models.ProjectCommandContext{
+ Log: logger,
+ Workspace: "workspace",
+ RepoRelPath: ".",
+ User: models.User{Username: "username"},
+ CommentArgs: []string{"comment", "args"},
+ }, []string{"extra", "args"}, "/path")
Ok(t, err)
Equals(t, "output", output)
@@ -170,18 +162,9 @@ func TestRun_CreatesWorkspace(t *testing.T) {
terraform := mocks.NewMockClient()
tfVersion, _ := version.NewVersion(c.tfVersion)
logger := logging.NewNoopLogger()
- s := runtime.PlanStep{
- Meta: runtime.StepMeta{
- Log: logger,
- Workspace: "workspace",
- AbsolutePath: "/path",
- DirRelativeToRepoRoot: ".",
- TerraformExecutor: terraform,
- TerraformVersion: tfVersion,
- ExtraCommentArgs: []string{"comment", "args"},
- Username: "username",
- },
- ExtraArgs: []string{"extra", "args"},
+ s := runtime.PlanStepOperator{
+ TerraformExecutor: terraform,
+ DefaultTFVersion: tfVersion,
}
// Ensure that we actually try to switch workspaces by making the
@@ -194,7 +177,13 @@ func TestRun_CreatesWorkspace(t *testing.T) {
expPlanArgs := []string{"plan", "-refresh", "-no-color", "-out", "/path/workspace.tfplan", "-var", "atlantis_user=username", "extra", "args", "comment", "args"}
When(terraform.RunCommandWithVersion(logger, "/path", expPlanArgs, tfVersion, "workspace")).ThenReturn("output", nil)
- output, err := s.Run()
+ output, err := s.Run(models.ProjectCommandContext{
+ Log: logger,
+ Workspace: "workspace",
+ RepoRelPath: ".",
+ User: models.User{Username: "username"},
+ CommentArgs: []string{"comment", "args"},
+ }, []string{"extra", "args"}, "/path")
Ok(t, err)
Equals(t, "output", output)
@@ -212,26 +201,22 @@ func TestRun_NoWorkspaceSwitchIfNotNecessary(t *testing.T) {
terraform := mocks.NewMockClient()
tfVersion, _ := version.NewVersion("0.10.0")
logger := logging.NewNoopLogger()
- s := runtime.PlanStep{
- Meta: runtime.StepMeta{
- Log: logger,
- Workspace: "workspace",
- AbsolutePath: "/path",
- DirRelativeToRepoRoot: ".",
- TerraformExecutor: terraform,
- TerraformVersion: tfVersion,
- ExtraCommentArgs: []string{"comment", "args"},
- Username: "username",
- },
- ExtraArgs: []string{"extra", "args"},
+ s := runtime.PlanStepOperator{
+ TerraformExecutor: terraform,
+ DefaultTFVersion: tfVersion,
}
-
When(terraform.RunCommandWithVersion(logger, "/path", []string{"workspace", "show"}, tfVersion, "workspace")).ThenReturn("workspace\n", nil)
expPlanArgs := []string{"plan", "-refresh", "-no-color", "-out", "/path/workspace.tfplan", "-var", "atlantis_user=username", "extra", "args", "comment", "args"}
When(terraform.RunCommandWithVersion(logger, "/path", expPlanArgs, tfVersion, "workspace")).ThenReturn("output", nil)
- output, err := s.Run()
+ output, err := s.Run(models.ProjectCommandContext{
+ Log: logger,
+ Workspace: "workspace",
+ RepoRelPath: ".",
+ User: models.User{Username: "username"},
+ CommentArgs: []string{"comment", "args"},
+ }, []string{"extra", "args"}, "/path")
Ok(t, err)
Equals(t, "output", output)
@@ -258,28 +243,25 @@ func TestRun_AddsEnvVarFile(t *testing.T) {
// Using version >= 0.10 here so we don't expect any env commands.
tfVersion, _ := version.NewVersion("0.10.0")
logger := logging.NewNoopLogger()
- s := runtime.PlanStep{
- Meta: runtime.StepMeta{
- Log: logger,
- Workspace: "workspace",
- AbsolutePath: tmpDir,
- DirRelativeToRepoRoot: ".",
- TerraformExecutor: terraform,
- TerraformVersion: tfVersion,
- ExtraCommentArgs: []string{"comment", "args"},
- Username: "username",
- },
- ExtraArgs: []string{"extra", "args"},
+ s := runtime.PlanStepOperator{
+ TerraformExecutor: terraform,
+ DefaultTFVersion: tfVersion,
}
expPlanArgs := []string{"plan", "-refresh", "-no-color", "-out", filepath.Join(tmpDir, "workspace.tfplan"), "-var", "atlantis_user=username", "extra", "args", "comment", "args", "-var-file", envVarsFile}
When(terraform.RunCommandWithVersion(logger, tmpDir, expPlanArgs, tfVersion, "workspace")).ThenReturn("output", nil)
- output, err := s.Run()
+ output, err := s.Run(models.ProjectCommandContext{
+ Log: logger,
+ Workspace: "workspace",
+ RepoRelPath: ".",
+ User: models.User{Username: "username"},
+ CommentArgs: []string{"comment", "args"},
+ }, []string{"extra", "args"}, tmpDir)
Ok(t, err)
- Equals(t, "output", output)
// Verify that env select was never called since we're in version >= 0.10
terraform.VerifyWasCalled(Never()).RunCommandWithVersion(logger, tmpDir, []string{"env", "select", "-no-color", "workspace"}, tfVersion, "workspace")
terraform.VerifyWasCalledOnce().RunCommandWithVersion(logger, tmpDir, expPlanArgs, tfVersion, "workspace")
+ Equals(t, "output", output)
}
diff --git a/server/events/yaml/parser_validator_test.go b/server/events/yaml/parser_validator_test.go
index 51fa1ca70..15bcd1960 100644
--- a/server/events/yaml/parser_validator_test.go
+++ b/server/events/yaml/parser_validator_test.go
@@ -6,6 +6,7 @@ import (
"path/filepath"
"testing"
+ "github.com/hashicorp/go-version"
"github.com/runatlantis/atlantis/server/events/yaml"
"github.com/runatlantis/atlantis/server/events/yaml/valid"
. "github.com/runatlantis/atlantis/testing"
@@ -72,6 +73,7 @@ func TestReadConfig_UnmarshalErrors(t *testing.T) {
}
func TestReadConfig(t *testing.T) {
+ tfVersion, _ := version.NewVersion("v0.11.0")
cases := []struct {
description string
input string
@@ -169,7 +171,7 @@ workflows:
Dir: ".",
Workspace: "myworkspace",
Workflow: String("myworkflow"),
- TerraformVersion: String("v0.11.0"),
+ TerraformVersion: tfVersion,
Autoplan: valid.Autoplan{
WhenModified: []string{"**/*.tf"},
Enabled: true,
@@ -203,7 +205,7 @@ workflows:
Dir: ".",
Workspace: "myworkspace",
Workflow: String("myworkflow"),
- TerraformVersion: String("v0.11.0"),
+ TerraformVersion: tfVersion,
Autoplan: valid.Autoplan{
WhenModified: []string{"**/*.tf"},
Enabled: false,
diff --git a/server/events/yaml/raw/project.go b/server/events/yaml/raw/project.go
index 3273cb38a..29335e795 100644
--- a/server/events/yaml/raw/project.go
+++ b/server/events/yaml/raw/project.go
@@ -1,12 +1,12 @@
package raw
import (
- "errors"
"fmt"
"strings"
"github.com/go-ozzo/ozzo-validation"
"github.com/hashicorp/go-version"
+ "github.com/pkg/errors"
"github.com/runatlantis/atlantis/server/events/yaml/valid"
)
@@ -41,11 +41,12 @@ func (p Project) Validate() error {
return nil
}
validTFVersion := func(value interface{}) error {
- // Safe to dereference because this is only called if the pointer is
- // not nil.
- versionStr := *value.(*string)
- _, err := version.NewVersion(versionStr)
- return err
+ strPtr := value.(*string)
+ if strPtr == nil {
+ return nil
+ }
+ _, err := version.NewVersion(*strPtr)
+ return errors.Wrapf(err, "version %q could not be parsed", *strPtr)
}
return validation.ValidateStruct(&p,
validation.Field(&p.Dir, validation.Required, validation.By(hasDotDot)),
diff --git a/server/events/yaml/raw/project_test.go b/server/events/yaml/raw/project_test.go
index 9c0691489..b10452afe 100644
--- a/server/events/yaml/raw/project_test.go
+++ b/server/events/yaml/raw/project_test.go
@@ -4,6 +4,7 @@ import (
"testing"
"github.com/go-ozzo/ozzo-validation"
+ "github.com/hashicorp/go-version"
"github.com/runatlantis/atlantis/server/events/yaml/raw"
"github.com/runatlantis/atlantis/server/events/yaml/valid"
. "github.com/runatlantis/atlantis/testing"
@@ -107,6 +108,30 @@ func TestProject_Validate(t *testing.T) {
},
expErr: "",
},
+ {
+ description: "empty tf version string",
+ input: raw.Project{
+ Dir: String("."),
+ TerraformVersion: String(""),
+ },
+ expErr: "terraform_version: version \"\" could not be parsed: Malformed version: .",
+ },
+ {
+ description: "tf version with v prepended",
+ input: raw.Project{
+ Dir: String("."),
+ TerraformVersion: String("v1"),
+ },
+ expErr: "",
+ },
+ {
+ description: "tf version without prepended",
+ input: raw.Project{
+ Dir: String("."),
+ TerraformVersion: String("1"),
+ },
+ expErr: "",
+ },
}
validation.ErrorTag = "yaml"
for _, c := range cases {
@@ -122,6 +147,7 @@ func TestProject_Validate(t *testing.T) {
}
func TestProject_ToValid(t *testing.T) {
+ tfVersionPointEleven, _ := version.NewVersion("v0.11.0")
cases := []struct {
description string
input raw.Project
@@ -161,7 +187,7 @@ func TestProject_ToValid(t *testing.T) {
Dir: ".",
Workspace: "myworkspace",
Workflow: String("myworkflow"),
- TerraformVersion: String("v0.11.0"),
+ TerraformVersion: tfVersionPointEleven,
Autoplan: valid.Autoplan{
WhenModified: []string{"hi"},
Enabled: false,
@@ -169,6 +195,22 @@ func TestProject_ToValid(t *testing.T) {
ApplyRequirements: []string{"approved"},
},
},
+ {
+ description: "tf version without 'v'",
+ input: raw.Project{
+ Dir: String("."),
+ TerraformVersion: String("0.11.0"),
+ },
+ exp: valid.Project{
+ Dir: ".",
+ Workspace: "default",
+ TerraformVersion: tfVersionPointEleven,
+ Autoplan: valid.Autoplan{
+ WhenModified: []string{"**/*.tf"},
+ Enabled: true,
+ },
+ },
+ },
}
for _, c := range cases {
t.Run(c.description, func(t *testing.T) {
diff --git a/server/events_controller_test.go b/server/events_controller_test.go
index 7997a56d8..bb0682ba6 100644
--- a/server/events_controller_test.go
+++ b/server/events_controller_test.go
@@ -293,31 +293,6 @@ func TestPost_GithubCommentSuccess(t *testing.T) {
cr.VerifyWasCalledOnce().ExecuteCommand(baseRepo, baseRepo, user, 1, &cmd)
}
-func TestPost_GithubPullRequestNotClosed(t *testing.T) {
- t.Log("when the event is a github pull reuqest but it's not a closed event we ignore it")
- e, v, _, _, _, _, _, _ := setup(t)
- req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
- req.Header.Set(githubHeader, "pull_request")
- event := `{"action": "opened"}`
- When(v.Validate(req, secret)).ThenReturn([]byte(event), nil)
- w := httptest.NewRecorder()
- e.Post(w, req)
- responseContains(t, w, http.StatusOK, "Ignoring opened pull request event")
-}
-
-func TestPost_GitlabMergeRequestNotClosed(t *testing.T) {
- t.Log("when the event is a gitlab merge request but it's not a closed event we ignore it")
- e, _, gl, p, _, _, _, _ := setup(t)
- req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
- req.Header.Set(gitlabHeader, "value")
- event := gitlab.MergeEvent{}
- When(gl.Validate(req, secret)).ThenReturn(event, nil)
- When(p.ParseGitlabMergeEvent(event)).ThenReturn(models.PullRequest{State: models.Open}, models.Repo{}, nil)
- w := httptest.NewRecorder()
- e.Post(w, req)
- responseContains(t, w, http.StatusOK, "Ignoring opened pull request event")
-}
-
func TestPost_GithubPullRequestInvalid(t *testing.T) {
t.Log("when the event is a github pull request with invalid data we return a 400")
e, v, _, p, _, _, _, _ := setup(t)
@@ -383,15 +358,14 @@ func TestPost_GithubPullRequestErrCleaningPull(t *testing.T) {
}
func TestPost_GitlabMergeRequestErrCleaningPull(t *testing.T) {
- t.Log("when the event is a gitlab merge request and an error occurs calling CleanUpPull we return a 503")
+ t.Log("when the event is a gitlab merge request and an error occurs calling CleanUpPull we return a 500")
e, _, gl, p, _, c, _, _ := setup(t)
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
req.Header.Set(gitlabHeader, "value")
- event := gitlab.MergeEvent{}
- When(gl.Validate(req, secret)).ThenReturn(event, nil)
+ When(gl.Validate(req, secret)).ThenReturn(gitlabMergeEvent, nil)
repo := models.Repo{}
pullRequest := models.PullRequest{State: models.Closed}
- When(p.ParseGitlabMergeEvent(event)).ThenReturn(pullRequest, repo, nil)
+ When(p.ParseGitlabMergeEvent(gitlabMergeEvent)).ThenReturn(pullRequest, repo, repo, nil)
When(c.CleanUpPull(repo, pullRequest)).ThenReturn(errors.New("err"))
w := httptest.NewRecorder()
e.Post(w, req)
@@ -421,11 +395,10 @@ func TestPost_GitlabMergeRequestSuccess(t *testing.T) {
e, _, gl, p, _, _, _, _ := setup(t)
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
req.Header.Set(gitlabHeader, "value")
- event := gitlab.MergeEvent{}
- When(gl.Validate(req, secret)).ThenReturn(event, nil)
+ When(gl.Validate(req, secret)).ThenReturn(gitlabMergeEvent, nil)
repo := models.Repo{}
pullRequest := models.PullRequest{State: models.Closed}
- When(p.ParseGitlabMergeEvent(event)).ThenReturn(pullRequest, repo, nil)
+ When(p.ParseGitlabMergeEvent(gitlabMergeEvent)).ThenReturn(pullRequest, repo, repo, nil)
w := httptest.NewRecorder()
e.Post(w, req)
responseContains(t, w, http.StatusOK, "Pull request cleaned successfully")
@@ -458,3 +431,60 @@ func setup(t *testing.T) (server.EventsController, *mocks.MockGithubRequestValid
}
return e, v, gl, p, cr, c, vcsmock, cp
}
+
+var gitlabMergeEvent = gitlab.MergeEvent{
+ ObjectAttributes: struct {
+ ID int `json:"id"`
+ TargetBranch string `json:"target_branch"`
+ SourceBranch string `json:"source_branch"`
+ SourceProjectID int `json:"source_project_id"`
+ AuthorID int `json:"author_id"`
+ AssigneeID int `json:"assignee_id"`
+ Title string `json:"title"`
+ CreatedAt string `json:"created_at"`
+ UpdatedAt string `json:"updated_at"`
+ StCommits []*gitlab.Commit `json:"st_commits"`
+ StDiffs []*gitlab.Diff `json:"st_diffs"`
+ MilestoneID int `json:"milestone_id"`
+ State string `json:"state"`
+ MergeStatus string `json:"merge_status"`
+ TargetProjectID int `json:"target_project_id"`
+ IID int `json:"iid"`
+ Description string `json:"description"`
+ Position int `json:"position"`
+ LockedAt string `json:"locked_at"`
+ UpdatedByID int `json:"updated_by_id"`
+ MergeError string `json:"merge_error"`
+ MergeParams struct {
+ ForceRemoveSourceBranch string `json:"force_remove_source_branch"`
+ } `json:"merge_params"`
+ MergeWhenBuildSucceeds bool `json:"merge_when_build_succeeds"`
+ MergeUserID int `json:"merge_user_id"`
+ MergeCommitSha string `json:"merge_commit_sha"`
+ DeletedAt string `json:"deleted_at"`
+ ApprovalsBeforeMerge string `json:"approvals_before_merge"`
+ RebaseCommitSha string `json:"rebase_commit_sha"`
+ InProgressMergeCommitSha string `json:"in_progress_merge_commit_sha"`
+ LockVersion int `json:"lock_version"`
+ TimeEstimate int `json:"time_estimate"`
+ Source *gitlab.Repository `json:"source"`
+ Target *gitlab.Repository `json:"target"`
+ LastCommit struct {
+ ID string `json:"id"`
+ Message string `json:"message"`
+ Timestamp *time.Time `json:"timestamp"`
+ URL string `json:"url"`
+ Author *gitlab.Author `json:"author"`
+ } `json:"last_commit"`
+ WorkInProgress bool `json:"work_in_progress"`
+ URL string `json:"url"`
+ Action string `json:"action"`
+ Assignee struct {
+ Name string `json:"name"`
+ Username string `json:"username"`
+ AvatarURL string `json:"avatar_url"`
+ } `json:"assignee"`
+ }{
+ Action: "merge",
+ },
+}
diff --git a/server/logging/simple_logger.go b/server/logging/simple_logger.go
index eca5778e4..ddb56ebcd 100644
--- a/server/logging/simple_logger.go
+++ b/server/logging/simple_logger.go
@@ -23,8 +23,6 @@ import (
"unicode"
)
-//go:generate pegomock generate -m --use-experimental-model-gen --package mocks -o mocks/mock_simple_logging.go SimpleLogging
-
// SimpleLogging is the interface that our SimpleLogger implements.
// It's really only used for mocking when we need to test what's being logged.
type SimpleLogging interface {
diff --git a/server/server.go b/server/server.go
index fe6e3f7b5..734a36de4 100644
--- a/server/server.go
+++ b/server/server.go
@@ -232,7 +232,7 @@ func NewServer(userConfig UserConfig, config Config) (*Server, error) {
Logger: logger,
AllowForkPRs: userConfig.AllowForkPRs,
AllowForkPRsFlag: config.AllowForkPRsFlag,
- PullRequestOperator: events.PullRequestOperator{
+ PullRequestOperator: &events.DefaultPullRequestOperator{
TerraformExecutor: terraformClient,
DefaultTFVersion: defaultTfVersion,
ParserValidator: &yaml.ParserValidator{},