mirror of
https://git.vectorsigma.ru/public/atlantis.git
synced 2026-07-28 23:08:26 +00:00
Fix all tests
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
@@ -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+"<details><summary>Log</summary>\n <p>\n\n```\nlog```\n</p></details>\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+"<details><summary>Log</summary>\n <p>\n\n```\nlog```\n</p></details>\n", s)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
154
server/events/mocks/mock_pull_request_operator.go
Normal file
154
server/events/mocks/mock_pull_request_operator.go
Normal file
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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{},
|
||||
|
||||
Reference in New Issue
Block a user