diff --git a/server/events/apply_executor.go b/server/events/apply_executor.go index 492e0ff35b..0ca0dc044f 100644 --- a/server/events/apply_executor.go +++ b/server/events/apply_executor.go @@ -40,7 +40,7 @@ type ApplyExecutor struct { // Execute executes apply for the ctx. func (a *ApplyExecutor) Execute(ctx *CommandContext) CommandResponse { if a.RequireApproval { - approved, err := a.VCSClient.PullIsApproved(ctx.BaseRepo, ctx.Pull, ctx.VCSHost) + approved, err := a.VCSClient.PullIsApproved(ctx.BaseRepo, ctx.Pull) if err != nil { return CommandResponse{Error: errors.Wrap(err, "checking if pull request was approved")} } diff --git a/server/events/command_context.go b/server/events/command_context.go index 19f5f6605e..35a2a1b141 100644 --- a/server/events/command_context.go +++ b/server/events/command_context.go @@ -15,7 +15,6 @@ package events import ( "github.com/runatlantis/atlantis/server/events/models" - "github.com/runatlantis/atlantis/server/events/vcs" "github.com/runatlantis/atlantis/server/logging" ) @@ -34,6 +33,4 @@ type CommandContext struct { User models.User Command *Command Log *logging.SimpleLogger - // VCSHost is the host that the command came from. - VCSHost vcs.Host } diff --git a/server/events/command_handler.go b/server/events/command_handler.go index 85824de994..fb70901fe2 100644 --- a/server/events/command_handler.go +++ b/server/events/command_handler.go @@ -32,7 +32,7 @@ type CommandRunner interface { // ExecuteCommand is the first step after a command request has been parsed. // It handles gathering additional information needed to execute the command // and then calling the appropriate services to finish executing the command. - ExecuteCommand(baseRepo models.Repo, headRepo models.Repo, user models.User, pullNum int, cmd *Command, vcsHost vcs.Host) + ExecuteCommand(baseRepo models.Repo, headRepo models.Repo, user models.User, pullNum int, cmd *Command) } //go:generate pegomock generate -m --use-experimental-model-gen --package mocks -o mocks/mock_github_pull_getter.go GithubPullGetter @@ -73,20 +73,23 @@ type CommandHandler struct { } // ExecuteCommand executes the command. -// If vcsHost is GitHub, we don't use headRepo and instead make an API call +// If the repo is from GitHub, we don't use headRepo and instead make an API call // to get the headRepo. This is because the caller is unable to pass in a // headRepo since there's not enough data available on the initial webhook // payload. -func (c *CommandHandler) ExecuteCommand(baseRepo models.Repo, headRepo models.Repo, user models.User, pullNum int, cmd *Command, vcsHost vcs.Host) { +func (c *CommandHandler) ExecuteCommand(baseRepo models.Repo, headRepo models.Repo, user models.User, pullNum int, cmd *Command) { + log := c.buildLogger(baseRepo.FullName, pullNum) + var err error var pull models.PullRequest - if vcsHost == vcs.Github { + switch baseRepo.VCSHost.Type { + case models.Github: pull, headRepo, err = c.getGithubData(baseRepo, pullNum) - } else if vcsHost == vcs.Gitlab { + case models.Gitlab: pull, err = c.getGitlabData(baseRepo.FullName, pullNum) + default: + err = errors.New("Unknown VCS type, this is a bug!") } - - log := c.buildLogger(baseRepo.FullName, pullNum) if err != nil { log.Err(err.Error()) return @@ -97,7 +100,6 @@ func (c *CommandHandler) ExecuteCommand(baseRepo models.Repo, headRepo models.Re Pull: pull, HeadRepo: headRepo, Command: cmd, - VCSHost: vcsHost, BaseRepo: baseRepo, } c.run(ctx) @@ -147,17 +149,17 @@ func (c *CommandHandler) run(ctx *CommandContext) { if !c.AllowForkPRs && ctx.HeadRepo.Owner != ctx.BaseRepo.Owner { ctx.Log.Info("command was run on a fork pull request which is disallowed") - c.VCSClient.CreateComment(ctx.BaseRepo, ctx.Pull.Num, fmt.Sprintf("Atlantis commands can't be run on fork pull requests. To enable, set --%s", c.AllowForkPRsFlag), ctx.VCSHost) // nolint: errcheck + c.VCSClient.CreateComment(ctx.BaseRepo, ctx.Pull.Num, fmt.Sprintf("Atlantis commands can't be run on fork pull requests. To enable, set --%s", c.AllowForkPRsFlag)) // nolint: errcheck return } if ctx.Pull.State != models.Open { ctx.Log.Info("command was run on closed pull request") - c.VCSClient.CreateComment(ctx.BaseRepo, ctx.Pull.Num, "Atlantis commands can't be run on closed pull requests", ctx.VCSHost) // nolint: errcheck + c.VCSClient.CreateComment(ctx.BaseRepo, ctx.Pull.Num, "Atlantis commands can't be run on closed pull requests") // nolint: errcheck return } - if err := c.CommitStatusUpdater.Update(ctx.BaseRepo, ctx.Pull, vcs.Pending, ctx.Command, ctx.VCSHost); err != nil { + if err := c.CommitStatusUpdater.Update(ctx.BaseRepo, ctx.Pull, vcs.Pending, ctx.Command); err != nil { ctx.Log.Warn("unable to update commit status: %s", err) } if !c.AtlantisWorkspaceLocker.TryLock(ctx.BaseRepo.FullName, ctx.Command.Workspace, ctx.Pull.Num) { @@ -197,7 +199,7 @@ func (c *CommandHandler) updatePull(ctx *CommandContext, res CommandResponse) { ctx.Log.Warn("unable to update commit status: %s", err) } comment := c.MarkdownRenderer.Render(res, ctx.Command.Name, ctx.Log.History.String(), ctx.Command.Verbose) - c.VCSClient.CreateComment(ctx.BaseRepo, ctx.Pull.Num, comment, ctx.VCSHost) // nolint: errcheck + c.VCSClient.CreateComment(ctx.BaseRepo, ctx.Pull.Num, comment) // nolint: errcheck } // logPanics logs and creates a comment on the pull request for panics. @@ -205,7 +207,7 @@ func (c *CommandHandler) logPanics(ctx *CommandContext) { if err := recover(); err != nil { stack := recovery.Stack(3) c.VCSClient.CreateComment(ctx.BaseRepo, ctx.Pull.Num, // nolint: errcheck - fmt.Sprintf("**Error: goroutine panic. This is a bug.**\n```\n%s\n%s```", err, stack), ctx.VCSHost) + fmt.Sprintf("**Error: goroutine panic. This is a bug.**\n```\n%s\n%s```", err, stack)) ctx.Log.Err("PANIC: %s\n%s", err, stack) } } diff --git a/server/events/command_handler_test.go b/server/events/command_handler_test.go index 1ff3a0781f..598ed6e234 100644 --- a/server/events/command_handler_test.go +++ b/server/events/command_handler_test.go @@ -78,9 +78,9 @@ func TestExecuteCommand_LogPanics(t *testing.T) { setup(t) ch.AllowForkPRs = true // Lets us get to the panic code. defer func() { ch.AllowForkPRs = false }() - When(ghStatus.Update(fixtures.Repo, fixtures.Pull, vcs.Pending, nil, vcs.Github)).ThenPanic("panic") - ch.ExecuteCommand(fixtures.Repo, fixtures.Repo, fixtures.User, 1, nil, vcs.Github) - _, _, comment, _ := vcsClient.VerifyWasCalledOnce().CreateComment(matchers.AnyModelsRepo(), AnyInt(), AnyString(), matchers.AnyVcsHost()).GetCapturedArguments() + When(ghStatus.Update(fixtures.GithubRepo, fixtures.Pull, vcs.Pending, nil)).ThenPanic("panic") + ch.ExecuteCommand(fixtures.GithubRepo, fixtures.GithubRepo, fixtures.User, 1, nil) + _, _, comment := vcsClient.VerifyWasCalledOnce().CreateComment(matchers.AnyModelsRepo(), AnyInt(), AnyString()).GetCapturedArguments() Assert(t, strings.Contains(comment, "Error: goroutine panic"), "comment should be about a goroutine panic") } @@ -88,7 +88,7 @@ func TestExecuteCommand_NoGithubPullGetter(t *testing.T) { t.Log("if CommandHandler was constructed with a nil GithubPullGetter an error should be logged") setup(t) ch.GithubPullGetter = nil - ch.ExecuteCommand(fixtures.Repo, fixtures.Repo, fixtures.User, 1, nil, vcs.Github) + ch.ExecuteCommand(fixtures.GithubRepo, fixtures.GithubRepo, fixtures.User, 1, nil) Equals(t, "[ERROR] runatlantis/atlantis#1: Atlantis not configured to support GitHub\n", logBytes.String()) } @@ -96,23 +96,23 @@ func TestExecuteCommand_NoGitlabMergeGetter(t *testing.T) { t.Log("if CommandHandler was constructed with a nil GitlabMergeRequestGetter an error should be logged") setup(t) ch.GitlabMergeRequestGetter = nil - ch.ExecuteCommand(fixtures.Repo, fixtures.Repo, fixtures.User, 1, nil, vcs.Gitlab) + ch.ExecuteCommand(fixtures.GitlabRepo, fixtures.GitlabRepo, fixtures.User, 1, nil) Equals(t, "[ERROR] runatlantis/atlantis#1: Atlantis not configured to support GitLab\n", logBytes.String()) } func TestExecuteCommand_GithubPullErr(t *testing.T) { t.Log("if getting the github pull request fails an error should be logged") setup(t) - When(githubGetter.GetPullRequest(fixtures.Repo, fixtures.Pull.Num)).ThenReturn(nil, errors.New("err")) - ch.ExecuteCommand(fixtures.Repo, fixtures.Repo, fixtures.User, fixtures.Pull.Num, nil, vcs.Github) + When(githubGetter.GetPullRequest(fixtures.GithubRepo, fixtures.Pull.Num)).ThenReturn(nil, errors.New("err")) + ch.ExecuteCommand(fixtures.GithubRepo, fixtures.GithubRepo, fixtures.User, fixtures.Pull.Num, nil) Equals(t, "[ERROR] runatlantis/atlantis#1: Making pull request API call to GitHub: err\n", logBytes.String()) } func TestExecuteCommand_GitlabMergeRequestErr(t *testing.T) { t.Log("if getting the gitlab merge request fails an error should be logged") setup(t) - When(gitlabGetter.GetMergeRequest(fixtures.Repo.FullName, fixtures.Pull.Num)).ThenReturn(nil, errors.New("err")) - ch.ExecuteCommand(fixtures.Repo, fixtures.Repo, fixtures.User, fixtures.Pull.Num, nil, vcs.Gitlab) + When(gitlabGetter.GetMergeRequest(fixtures.GithubRepo.FullName, fixtures.Pull.Num)).ThenReturn(nil, errors.New("err")) + ch.ExecuteCommand(fixtures.GitlabRepo, fixtures.GitlabRepo, fixtures.User, fixtures.Pull.Num, nil) Equals(t, "[ERROR] runatlantis/atlantis#1: Making merge request API call to GitLab: err\n", logBytes.String()) } @@ -120,10 +120,10 @@ func TestExecuteCommand_GithubPullParseErr(t *testing.T) { t.Log("if parsing the returned github pull request fails an error should be logged") setup(t) var pull github.PullRequest - When(githubGetter.GetPullRequest(fixtures.Repo, fixtures.Pull.Num)).ThenReturn(&pull, nil) - When(eventParsing.ParseGithubPull(&pull)).ThenReturn(fixtures.Pull, fixtures.Repo, errors.New("err")) + When(githubGetter.GetPullRequest(fixtures.GithubRepo, fixtures.Pull.Num)).ThenReturn(&pull, nil) + When(eventParsing.ParseGithubPull(&pull)).ThenReturn(fixtures.Pull, fixtures.GithubRepo, errors.New("err")) - ch.ExecuteCommand(fixtures.Repo, fixtures.Repo, fixtures.User, fixtures.Pull.Num, nil, vcs.Github) + ch.ExecuteCommand(fixtures.GithubRepo, fixtures.GithubRepo, fixtures.User, fixtures.Pull.Num, nil) Equals(t, "[ERROR] runatlantis/atlantis#1: Extracting required fields from comment data: err\n", logBytes.String()) } @@ -134,15 +134,15 @@ func TestExecuteCommand_ForkPRDisabled(t *testing.T) { ch.AllowForkPRs = false // by default it's false so don't need to reset var pull github.PullRequest modelPull := models.PullRequest{State: models.Open} - When(githubGetter.GetPullRequest(fixtures.Repo, fixtures.Pull.Num)).ThenReturn(&pull, nil) + When(githubGetter.GetPullRequest(fixtures.GithubRepo, fixtures.Pull.Num)).ThenReturn(&pull, nil) - headRepo := fixtures.Repo + headRepo := fixtures.GithubRepo headRepo.FullName = "forkrepo/atlantis" headRepo.Owner = "forkrepo" When(eventParsing.ParseGithubPull(&pull)).ThenReturn(modelPull, headRepo, nil) - ch.ExecuteCommand(fixtures.Repo, models.Repo{} /* this isn't used */, fixtures.User, fixtures.Pull.Num, nil, vcs.Github) - vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.Repo, modelPull.Num, "Atlantis commands can't be run on fork pull requests. To enable, set --"+ch.AllowForkPRsFlag, vcs.Github) + ch.ExecuteCommand(fixtures.GithubRepo, models.Repo{} /* this isn't used */, fixtures.User, fixtures.Pull.Num, nil) + vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, modelPull.Num, "Atlantis commands can't be run on fork pull requests. To enable, set --"+ch.AllowForkPRsFlag) } func TestExecuteCommand_ClosedPull(t *testing.T) { @@ -153,11 +153,11 @@ func TestExecuteCommand_ClosedPull(t *testing.T) { State: github.String("closed"), } modelPull := models.PullRequest{State: models.Closed} - When(githubGetter.GetPullRequest(fixtures.Repo, fixtures.Pull.Num)).ThenReturn(pull, nil) - When(eventParsing.ParseGithubPull(pull)).ThenReturn(modelPull, fixtures.Repo, nil) + When(githubGetter.GetPullRequest(fixtures.GithubRepo, fixtures.Pull.Num)).ThenReturn(pull, nil) + When(eventParsing.ParseGithubPull(pull)).ThenReturn(modelPull, fixtures.GithubRepo, nil) - ch.ExecuteCommand(fixtures.Repo, fixtures.Repo, fixtures.User, fixtures.Pull.Num, nil, vcs.Github) - vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.Repo, modelPull.Num, "Atlantis commands can't be run on closed pull requests", vcs.Github) + ch.ExecuteCommand(fixtures.GithubRepo, fixtures.GithubRepo, fixtures.User, fixtures.Pull.Num, nil) + vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, modelPull.Num, "Atlantis commands can't be run on closed pull requests") } func TestExecuteCommand_WorkspaceLocked(t *testing.T) { @@ -171,19 +171,19 @@ func TestExecuteCommand_WorkspaceLocked(t *testing.T) { Workspace: "workspace", } - When(githubGetter.GetPullRequest(fixtures.Repo, fixtures.Pull.Num)).ThenReturn(pull, nil) - When(eventParsing.ParseGithubPull(pull)).ThenReturn(fixtures.Pull, fixtures.Repo, nil) - When(workspaceLocker.TryLock(fixtures.Repo.FullName, cmd.Workspace, fixtures.Pull.Num)).ThenReturn(false) - ch.ExecuteCommand(fixtures.Repo, fixtures.Repo, fixtures.User, fixtures.Pull.Num, &cmd, vcs.Github) + When(githubGetter.GetPullRequest(fixtures.GithubRepo, fixtures.Pull.Num)).ThenReturn(pull, nil) + When(eventParsing.ParseGithubPull(pull)).ThenReturn(fixtures.Pull, fixtures.GithubRepo, nil) + When(workspaceLocker.TryLock(fixtures.GithubRepo.FullName, cmd.Workspace, fixtures.Pull.Num)).ThenReturn(false) + ch.ExecuteCommand(fixtures.GithubRepo, fixtures.GithubRepo, fixtures.User, fixtures.Pull.Num, &cmd) msg := "The workspace workspace is currently locked by another" + " command that is running for this pull request." + " Wait until the previous command is complete and try again." - ghStatus.VerifyWasCalledOnce().Update(fixtures.Repo, fixtures.Pull, vcs.Pending, &cmd, vcs.Github) + ghStatus.VerifyWasCalledOnce().Update(fixtures.GithubRepo, fixtures.Pull, vcs.Pending, &cmd) _, response := ghStatus.VerifyWasCalledOnce().UpdateProjectResult(matchers.AnyPtrToEventsCommandContext(), matchers.AnyEventsCommandResponse()).GetCapturedArguments() Equals(t, msg, response.Failure) - vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.Repo, fixtures.Pull.Num, - "**Plan Failed**: "+msg+"\n\n", vcs.Github) + vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, fixtures.Pull.Num, + "**Plan Failed**: "+msg+"\n\n") } func TestExecuteCommand_FullRun(t *testing.T) { @@ -198,9 +198,9 @@ func TestExecuteCommand_FullRun(t *testing.T) { Name: c, Workspace: "workspace", } - When(githubGetter.GetPullRequest(fixtures.Repo, fixtures.Pull.Num)).ThenReturn(pull, nil) - When(eventParsing.ParseGithubPull(pull)).ThenReturn(fixtures.Pull, fixtures.Repo, nil) - When(workspaceLocker.TryLock(fixtures.Repo.FullName, cmd.Workspace, fixtures.Pull.Num)).ThenReturn(true) + When(githubGetter.GetPullRequest(fixtures.GithubRepo, fixtures.Pull.Num)).ThenReturn(pull, nil) + When(eventParsing.ParseGithubPull(pull)).ThenReturn(fixtures.Pull, fixtures.GithubRepo, nil) + 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) @@ -208,13 +208,13 @@ func TestExecuteCommand_FullRun(t *testing.T) { When(applier.Execute(matchers.AnyPtrToEventsCommandContext())).ThenReturn(cmdResponse) } - ch.ExecuteCommand(fixtures.Repo, fixtures.Repo, fixtures.User, fixtures.Pull.Num, &cmd, vcs.Github) + ch.ExecuteCommand(fixtures.GithubRepo, fixtures.GithubRepo, fixtures.User, fixtures.Pull.Num, &cmd) - ghStatus.VerifyWasCalledOnce().Update(fixtures.Repo, fixtures.Pull, vcs.Pending, &cmd, vcs.Github) + ghStatus.VerifyWasCalledOnce().Update(fixtures.GithubRepo, fixtures.Pull, vcs.Pending, &cmd) _, response := ghStatus.VerifyWasCalledOnce().UpdateProjectResult(matchers.AnyPtrToEventsCommandContext(), matchers.AnyEventsCommandResponse()).GetCapturedArguments() Equals(t, cmdResponse, response) - vcsClient.VerifyWasCalledOnce().CreateComment(matchers.AnyModelsRepo(), AnyInt(), AnyString(), matchers.AnyVcsHost()) - workspaceLocker.VerifyWasCalledOnce().Unlock(fixtures.Repo.FullName, cmd.Workspace, fixtures.Pull.Num) + vcsClient.VerifyWasCalledOnce().CreateComment(matchers.AnyModelsRepo(), AnyInt(), AnyString()) + workspaceLocker.VerifyWasCalledOnce().Unlock(fixtures.GithubRepo.FullName, cmd.Workspace, fixtures.Pull.Num) } } @@ -232,19 +232,19 @@ func TestExecuteCommand_ForkPREnabled(t *testing.T) { Name: events.Plan, Workspace: "workspace", } - When(githubGetter.GetPullRequest(fixtures.Repo, fixtures.Pull.Num)).ThenReturn(&pull, nil) - headRepo := fixtures.Repo + When(githubGetter.GetPullRequest(fixtures.GithubRepo, fixtures.Pull.Num)).ThenReturn(&pull, nil) + headRepo := fixtures.GithubRepo headRepo.FullName = "forkrepo/atlantis" headRepo.Owner = "forkrepo" When(eventParsing.ParseGithubPull(&pull)).ThenReturn(fixtures.Pull, headRepo, nil) - When(workspaceLocker.TryLock(fixtures.Repo.FullName, cmd.Workspace, fixtures.Pull.Num)).ThenReturn(true) + When(workspaceLocker.TryLock(fixtures.GithubRepo.FullName, cmd.Workspace, fixtures.Pull.Num)).ThenReturn(true) When(planner.Execute(matchers.AnyPtrToEventsCommandContext())).ThenReturn(cmdResponse) - ch.ExecuteCommand(fixtures.Repo, models.Repo{} /* this isn't used */, fixtures.User, fixtures.Pull.Num, &cmd, vcs.Github) + ch.ExecuteCommand(fixtures.GithubRepo, models.Repo{} /* this isn't used */, fixtures.User, fixtures.Pull.Num, &cmd) - ghStatus.VerifyWasCalledOnce().Update(fixtures.Repo, fixtures.Pull, vcs.Pending, &cmd, vcs.Github) + ghStatus.VerifyWasCalledOnce().Update(fixtures.GithubRepo, fixtures.Pull, vcs.Pending, &cmd) _, response := ghStatus.VerifyWasCalledOnce().UpdateProjectResult(matchers.AnyPtrToEventsCommandContext(), matchers.AnyEventsCommandResponse()).GetCapturedArguments() Equals(t, cmdResponse, response) - vcsClient.VerifyWasCalledOnce().CreateComment(matchers.AnyModelsRepo(), AnyInt(), AnyString(), matchers.AnyVcsHost()) - workspaceLocker.VerifyWasCalledOnce().Unlock(fixtures.Repo.FullName, cmd.Workspace, fixtures.Pull.Num) + vcsClient.VerifyWasCalledOnce().CreateComment(matchers.AnyModelsRepo(), AnyInt(), AnyString()) + workspaceLocker.VerifyWasCalledOnce().Unlock(fixtures.GithubRepo.FullName, cmd.Workspace, fixtures.Pull.Num) } diff --git a/server/events/comment_parser.go b/server/events/comment_parser.go index 198439e71f..4b024dfc5c 100644 --- a/server/events/comment_parser.go +++ b/server/events/comment_parser.go @@ -20,7 +20,7 @@ import ( "path/filepath" "strings" - "github.com/runatlantis/atlantis/server/events/vcs" + "github.com/runatlantis/atlantis/server/events/models" "github.com/spf13/pflag" ) @@ -39,7 +39,7 @@ const ( type CommentParsing interface { // Parse attempts to parse a pull request comment to see if it's an Atlantis // commmand. - Parse(comment string, vcsHost vcs.Host) CommentParseResult + Parse(comment string, vcsHost models.VCSHostType) CommentParseResult } // CommentParser implements CommentParsing @@ -79,7 +79,7 @@ type CommentParseResult struct { // - atlantis plan --verbose -- -key=value -key2 value2 // // nolint: gocyclo -func (e *CommentParser) Parse(comment string, vcsHost vcs.Host) CommentParseResult { +func (e *CommentParser) Parse(comment string, vcsHost models.VCSHostType) CommentParseResult { if multiLineRegex.MatchString(comment) { return CommentParseResult{Ignore: true} } @@ -99,7 +99,7 @@ func (e *CommentParser) Parse(comment string, vcsHost vcs.Host) CommentParseResu // Atlantis can be invoked using the name of the VCS host user we're // running under. Need to be able to match against that user. vcsUser := e.GithubUser - if vcsHost == vcs.Gitlab { + if vcsHost == models.Gitlab { vcsUser = e.GitlabUser } executableNames := []string{"run", "atlantis", "@" + vcsUser} diff --git a/server/events/comment_parser_test.go b/server/events/comment_parser_test.go index 8edbc1417b..87b14f358b 100644 --- a/server/events/comment_parser_test.go +++ b/server/events/comment_parser_test.go @@ -19,7 +19,7 @@ import ( "testing" "github.com/runatlantis/atlantis/server/events" - "github.com/runatlantis/atlantis/server/events/vcs" + "github.com/runatlantis/atlantis/server/events/models" . "github.com/runatlantis/atlantis/testing" ) @@ -41,7 +41,7 @@ func TestParse_Ignored(t *testing.T) { "terraform plan\nbut with newlines", } for _, c := range ignoreComments { - r := commentParser.Parse(c, vcs.Github) + r := commentParser.Parse(c, models.Github) Assert(t, r.Ignore, "expected Ignore to be true for comment %q", c) } } @@ -60,7 +60,7 @@ func TestParse_HelpResponse(t *testing.T) { "atlantis help plan", } for _, c := range helpComments { - r := commentParser.Parse(c, vcs.Github) + r := commentParser.Parse(c, models.Github) Equals(t, events.HelpComment, r.CommentResponse) } } @@ -121,7 +121,7 @@ func TestParse_UnusedArguments(t *testing.T) { for _, c := range cases { comment := fmt.Sprintf("atlantis %s %s", c.Command.String(), c.Args) t.Run(comment, func(t *testing.T) { - r := commentParser.Parse(comment, vcs.Github) + r := commentParser.Parse(comment, models.Github) usage := PlanUsage if c.Command == events.Apply { usage = ApplyUsage @@ -144,7 +144,7 @@ func TestParse_DidYouMeanAtlantis(t *testing.T) { "terraform plan -w workspace -d . -- test", } for _, c := range comments { - r := commentParser.Parse(c, vcs.Github) + r := commentParser.Parse(c, models.Github) Assert(t, r.CommentResponse == events.DidYouMeanAtlantisComment, "For comment %q expected CommentResponse==%q but got %q", c, events.DidYouMeanAtlantisComment, r.CommentResponse) } @@ -159,7 +159,7 @@ func TestParse_InvalidCommand(t *testing.T) { "atlantis appely apply", } for _, c := range comments { - r := commentParser.Parse(c, vcs.Github) + r := commentParser.Parse(c, models.Github) exp := fmt.Sprintf("```\nError: unknown command %q.\nRun 'atlantis --help' for usage.\n```", strings.Fields(c)[1]) Assert(t, r.CommentResponse == exp, "For comment %q expected CommentResponse==%q but got %q", c, exp, r.CommentResponse) @@ -176,7 +176,7 @@ func TestParse_SubcommandUsage(t *testing.T) { "atlantis apply --help", } for _, c := range comments { - r := commentParser.Parse(c, vcs.Github) + r := commentParser.Parse(c, models.Github) exp := "Usage of " + strings.Fields(c)[1] Assert(t, strings.Contains(r.CommentResponse, exp), "For comment %q expected CommentResponse %q to contain %q", c, r.CommentResponse, exp) @@ -210,7 +210,7 @@ func TestParse_InvalidFlags(t *testing.T) { }, } for _, c := range cases { - r := commentParser.Parse(c.comment, vcs.Github) + r := commentParser.Parse(c.comment, models.Github) Assert(t, strings.Contains(r.CommentResponse, c.exp), "For comment %q expected CommentResponse %q to contain %q", c.comment, r.CommentResponse, c.exp) Assert(t, strings.Contains(r.CommentResponse, "Usage of "), @@ -232,7 +232,7 @@ func TestParse_RelativeDirPath(t *testing.T) { "atlantis apply -d a/../..", } for _, c := range comments { - r := commentParser.Parse(c, vcs.Github) + r := commentParser.Parse(c, models.Github) exp := "Error: using a relative path" Assert(t, strings.Contains(r.CommentResponse, exp), "For comment %q expected CommentResponse %q to contain %q", c, r.CommentResponse, exp) @@ -252,7 +252,7 @@ func TestParse_InvalidWorkspace(t *testing.T) { "atlantis apply -w ../../../etc/passwd", } for _, c := range comments { - r := commentParser.Parse(c, vcs.Github) + r := commentParser.Parse(c, models.Github) exp := "Error: invalid workspace" Assert(t, strings.Contains(r.CommentResponse, exp), "For comment %q expected CommentResponse %q to contain %q", c, r.CommentResponse, exp) @@ -412,7 +412,7 @@ func TestParse_Parsing(t *testing.T) { for _, test := range cases { for _, cmdName := range []string{"plan", "apply"} { comment := fmt.Sprintf("atlantis %s %s", cmdName, test.flags) - r := commentParser.Parse(comment, vcs.Github) + r := commentParser.Parse(comment, models.Github) Assert(t, r.CommentResponse == "", "CommentResponse should have been empty but was %q for comment %q", r.CommentResponse, comment) Assert(t, test.expDir == r.Command.Dir, "exp dir to equal %q but was %q for comment %q", test.expDir, r.Command.Dir, comment) Assert(t, test.expWorkspace == r.Command.Workspace, "exp workspace to equal %q but was %q for comment %q", test.expWorkspace, r.Command.Workspace, comment) diff --git a/server/events/commit_status_updater.go b/server/events/commit_status_updater.go index 7669b34eec..3debcd43fe 100644 --- a/server/events/commit_status_updater.go +++ b/server/events/commit_status_updater.go @@ -27,7 +27,7 @@ import ( // the status to signify whether the plan/apply succeeds. type CommitStatusUpdater interface { // Update updates the status of the head commit of pull. - Update(repo models.Repo, pull models.PullRequest, status vcs.CommitStatus, cmd *Command, host vcs.Host) error + Update(repo models.Repo, pull models.PullRequest, status vcs.CommitStatus, cmd *Command) error // UpdateProjectResult updates the status of the head commit given the // state of response. UpdateProjectResult(ctx *CommandContext, res CommandResponse) error @@ -39,9 +39,9 @@ type DefaultCommitStatusUpdater struct { } // Update updates the commit status. -func (d *DefaultCommitStatusUpdater) Update(repo models.Repo, pull models.PullRequest, status vcs.CommitStatus, cmd *Command, host vcs.Host) error { +func (d *DefaultCommitStatusUpdater) Update(repo models.Repo, pull models.PullRequest, status vcs.CommitStatus, cmd *Command) error { description := fmt.Sprintf("%s %s", strings.Title(cmd.Name.String()), strings.Title(status.String())) - return d.Client.UpdateStatus(repo, pull, status, description, host) + return d.Client.UpdateStatus(repo, pull, status, description) } // UpdateProjectResult updates the commit status based on the status of res. @@ -56,7 +56,7 @@ func (d *DefaultCommitStatusUpdater) UpdateProjectResult(ctx *CommandContext, re } status = d.worstStatus(statuses) } - return d.Update(ctx.BaseRepo, ctx.Pull, status, ctx.Command, ctx.VCSHost) + return d.Update(ctx.BaseRepo, ctx.Pull, status, ctx.Command) } func (d *DefaultCommitStatusUpdater) worstStatus(ss []vcs.CommitStatus) vcs.CommitStatus { diff --git a/server/events/commit_status_updater_test.go b/server/events/commit_status_updater_test.go index 27a22afbca..7d05264b04 100644 --- a/server/events/commit_status_updater_test.go +++ b/server/events/commit_status_updater_test.go @@ -48,9 +48,9 @@ func TestUpdate(t *testing.T) { RegisterMockTestingT(t) client := mocks.NewMockClientProxy() s := events.DefaultCommitStatusUpdater{Client: client} - err := s.Update(repoModel, pullModel, status, &cmd, vcs.Github) + err := s.Update(repoModel, pullModel, status, &cmd) Ok(t, err) - client.VerifyWasCalledOnce().UpdateStatus(repoModel, pullModel, status, "Plan Success", vcs.Github) + client.VerifyWasCalledOnce().UpdateStatus(repoModel, pullModel, status, "Plan Success") } func TestUpdateProjectResult_Error(t *testing.T) { @@ -59,13 +59,12 @@ func TestUpdateProjectResult_Error(t *testing.T) { BaseRepo: repoModel, Pull: pullModel, Command: &events.Command{Name: events.Plan}, - VCSHost: vcs.Github, } client := mocks.NewMockClientProxy() s := events.DefaultCommitStatusUpdater{Client: client} err := s.UpdateProjectResult(ctx, events.CommandResponse{Error: errors.New("err")}) Ok(t, err) - client.VerifyWasCalledOnce().UpdateStatus(repoModel, pullModel, vcs.Failed, "Plan Failed", vcs.Github) + client.VerifyWasCalledOnce().UpdateStatus(repoModel, pullModel, vcs.Failed, "Plan Failed") } func TestUpdateProjectResult_Failure(t *testing.T) { @@ -74,13 +73,12 @@ func TestUpdateProjectResult_Failure(t *testing.T) { BaseRepo: repoModel, Pull: pullModel, Command: &events.Command{Name: events.Plan}, - VCSHost: vcs.Github, } client := mocks.NewMockClientProxy() s := events.DefaultCommitStatusUpdater{Client: client} err := s.UpdateProjectResult(ctx, events.CommandResponse{Failure: "failure"}) Ok(t, err) - client.VerifyWasCalledOnce().UpdateStatus(repoModel, pullModel, vcs.Failed, "Plan Failed", vcs.Github) + client.VerifyWasCalledOnce().UpdateStatus(repoModel, pullModel, vcs.Failed, "Plan Failed") } func TestUpdateProjectResult(t *testing.T) { @@ -91,7 +89,6 @@ func TestUpdateProjectResult(t *testing.T) { BaseRepo: repoModel, Pull: pullModel, Command: &events.Command{Name: events.Plan}, - VCSHost: vcs.Github, } cases := []struct { @@ -148,6 +145,6 @@ func TestUpdateProjectResult(t *testing.T) { s := events.DefaultCommitStatusUpdater{Client: client} err := s.UpdateProjectResult(ctx, resp) Ok(t, err) - client.VerifyWasCalledOnce().UpdateStatus(repoModel, pullModel, c.Expected, "Plan "+strings.Title(c.Expected.String()), vcs.Github) + client.VerifyWasCalledOnce().UpdateStatus(repoModel, pullModel, c.Expected, "Plan "+strings.Title(c.Expected.String())) } } diff --git a/server/events/event_parser.go b/server/events/event_parser.go index 2eed88daec..eb372704f8 100644 --- a/server/events/event_parser.go +++ b/server/events/event_parser.go @@ -125,7 +125,7 @@ func (e *EventParser) ParseGithubPull(pull *github.PullRequest) (models.PullRequ } func (e *EventParser) ParseGithubRepo(ghRepo *github.Repository) (models.Repo, error) { - return models.NewRepo(ghRepo.GetFullName(), ghRepo.GetCloneURL(), e.GithubUser, e.GithubToken) + return models.NewRepo(models.Github, ghRepo.GetFullName(), ghRepo.GetCloneURL(), e.GithubUser, e.GithubToken) } func (e *EventParser) ParseGitlabMergeEvent(event gitlab.MergeEvent) (models.PullRequest, models.Repo, error) { @@ -145,7 +145,7 @@ func (e *EventParser) ParseGitlabMergeEvent(event gitlab.MergeEvent) (models.Pul State: modelState, } - repo, err := models.NewRepo(event.Project.PathWithNamespace, event.Project.GitHTTPURL, e.GitlabUser, e.GitlabToken) + repo, err := models.NewRepo(models.Gitlab, event.Project.PathWithNamespace, event.Project.GitHTTPURL, e.GitlabUser, e.GitlabToken) return pull, repo, err } @@ -154,7 +154,7 @@ func (e *EventParser) ParseGitlabMergeCommentEvent(event gitlab.MergeCommentEven // Parse the base repo first. repoFullName := event.Project.PathWithNamespace cloneURL := event.Project.GitHTTPURL - baseRepo, err = models.NewRepo(repoFullName, cloneURL, e.GitlabUser, e.GitlabToken) + baseRepo, err = models.NewRepo(models.Gitlab, repoFullName, cloneURL, e.GitlabUser, e.GitlabToken) if err != nil { return } @@ -165,7 +165,7 @@ func (e *EventParser) ParseGitlabMergeCommentEvent(event gitlab.MergeCommentEven // Now parse the head repo. headRepoFullName := event.MergeRequest.Source.PathWithNamespace headCloneURL := event.MergeRequest.Source.GitHTTPURL - headRepo, err = models.NewRepo(headRepoFullName, headCloneURL, e.GitlabUser, e.GitlabToken) + headRepo, err = models.NewRepo(models.Gitlab, headRepoFullName, headCloneURL, e.GitlabUser, e.GitlabToken) return } diff --git a/server/events/event_parser_test.go b/server/events/event_parser_test.go index 931bd9bf8c..3d4ab57e3f 100644 --- a/server/events/event_parser_test.go +++ b/server/events/event_parser_test.go @@ -42,7 +42,10 @@ func TestParseGithubRepo(t *testing.T) { CloneURL: "https://github-user:github-token@github.com/owner/repo.git", SanitizedCloneURL: Repo.GetCloneURL(), Name: "repo", - Hostname: "github.com", + VCSHost: models.VCSHost{ + Hostname: "github.com", + Type: models.Github, + }, }, r) } @@ -88,7 +91,10 @@ func TestParseGithubIssueCommentEvent(t *testing.T) { CloneURL: "https://github-user:github-token@github.com/owner/repo.git", SanitizedCloneURL: *comment.Repo.CloneURL, Name: "repo", - Hostname: "github.com", + VCSHost: models.VCSHost{ + Hostname: "github.com", + Type: models.Github, + }, }, repo) Equals(t, models.User{ Username: *comment.Comment.User.Login, @@ -139,7 +145,10 @@ func TestParseGithubPull(t *testing.T) { CloneURL: "https://github-user:github-token@github.com/owner/repo.git", SanitizedCloneURL: Repo.GetCloneURL(), Name: "repo", - Hostname: "github.com", + VCSHost: models.VCSHost{ + Hostname: "github.com", + Type: models.Github, + }, }, repoRes) } @@ -165,7 +174,10 @@ func TestParseGitlabMergeEvent(t *testing.T) { SanitizedCloneURL: "https://example.com/gitlabhq/gitlab-test.git", Owner: "gitlabhq", CloneURL: "https://gitlab-user:gitlab-token@example.com/gitlabhq/gitlab-test.git", - Hostname: "example.com", + VCSHost: models.VCSHost{ + Hostname: "example.com", + Type: models.Gitlab, + }, }, repo) t.Log("If the state is closed, should set field correctly.") @@ -209,7 +221,10 @@ func TestParseGitlabMergeCommentEvent(t *testing.T) { SanitizedCloneURL: "https://example.com/gitlabhq/gitlab-test.git", Owner: "gitlabhq", CloneURL: "https://gitlab-user:gitlab-token@example.com/gitlabhq/gitlab-test.git", - Hostname: "example.com", + VCSHost: models.VCSHost{ + Hostname: "example.com", + Type: models.Gitlab, + }, }, baseRepo) Equals(t, models.Repo{ FullName: "gitlab-org/gitlab-test", @@ -217,7 +232,10 @@ func TestParseGitlabMergeCommentEvent(t *testing.T) { SanitizedCloneURL: "https://example.com/gitlab-org/gitlab-test.git", Owner: "gitlab-org", CloneURL: "https://gitlab-user:gitlab-token@example.com/gitlab-org/gitlab-test.git", - Hostname: "example.com", + VCSHost: models.VCSHost{ + Hostname: "example.com", + Type: models.Gitlab, + }, }, headRepo) Equals(t, models.User{ Username: "root", diff --git a/server/events/mocks/matchers/models_vcshosttype.go b/server/events/mocks/matchers/models_vcshosttype.go new file mode 100644 index 0000000000..e38331b62c --- /dev/null +++ b/server/events/mocks/matchers/models_vcshosttype.go @@ -0,0 +1,20 @@ +package matchers + +import ( + "reflect" + + "github.com/petergtz/pegomock" + models "github.com/runatlantis/atlantis/server/events/models" +) + +func AnyModelsVCSHostType() models.VCSHostType { + pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*(models.VCSHostType))(nil)).Elem())) + var nullValue models.VCSHostType + return nullValue +} + +func EqModelsVCSHostType(value models.VCSHostType) models.VCSHostType { + pegomock.RegisterMatcher(&pegomock.EqMatcher{Value: value}) + var nullValue models.VCSHostType + return nullValue +} diff --git a/server/events/mocks/matchers/vcs_host.go b/server/events/mocks/matchers/vcs_host.go deleted file mode 100644 index 51a6399dc4..0000000000 --- a/server/events/mocks/matchers/vcs_host.go +++ /dev/null @@ -1,20 +0,0 @@ -package matchers - -import ( - "reflect" - - "github.com/petergtz/pegomock" - vcs "github.com/runatlantis/atlantis/server/events/vcs" -) - -func AnyVcsHost() vcs.Host { - pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*(vcs.Host))(nil)).Elem())) - var nullValue vcs.Host - return nullValue -} - -func EqVcsHost(value vcs.Host) vcs.Host { - pegomock.RegisterMatcher(&pegomock.EqMatcher{Value: value}) - var nullValue vcs.Host - return nullValue -} diff --git a/server/events/mocks/mock_command_runner.go b/server/events/mocks/mock_command_runner.go index 5e42db1a5b..481fcf72f5 100644 --- a/server/events/mocks/mock_command_runner.go +++ b/server/events/mocks/mock_command_runner.go @@ -9,7 +9,6 @@ import ( pegomock "github.com/petergtz/pegomock" events "github.com/runatlantis/atlantis/server/events" models "github.com/runatlantis/atlantis/server/events/models" - vcs "github.com/runatlantis/atlantis/server/events/vcs" ) type MockCommandRunner struct { @@ -20,8 +19,8 @@ func NewMockCommandRunner() *MockCommandRunner { return &MockCommandRunner{fail: pegomock.GlobalFailHandler} } -func (mock *MockCommandRunner) ExecuteCommand(baseRepo models.Repo, headRepo models.Repo, user models.User, pullNum int, cmd *events.Command, vcsHost vcs.Host) { - params := []pegomock.Param{baseRepo, headRepo, user, pullNum, cmd, vcsHost} +func (mock *MockCommandRunner) ExecuteCommand(baseRepo models.Repo, headRepo models.Repo, user models.User, pullNum int, cmd *events.Command) { + params := []pegomock.Param{baseRepo, headRepo, user, pullNum, cmd} pegomock.GetGenericMockFrom(mock).Invoke("ExecuteCommand", params, []reflect.Type{}) } @@ -43,8 +42,8 @@ type VerifierCommandRunner struct { inOrderContext *pegomock.InOrderContext } -func (verifier *VerifierCommandRunner) ExecuteCommand(baseRepo models.Repo, headRepo models.Repo, user models.User, pullNum int, cmd *events.Command, vcsHost vcs.Host) *CommandRunner_ExecuteCommand_OngoingVerification { - params := []pegomock.Param{baseRepo, headRepo, user, pullNum, cmd, vcsHost} +func (verifier *VerifierCommandRunner) ExecuteCommand(baseRepo models.Repo, headRepo models.Repo, user models.User, pullNum int, cmd *events.Command) *CommandRunner_ExecuteCommand_OngoingVerification { + params := []pegomock.Param{baseRepo, headRepo, user, pullNum, cmd} methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "ExecuteCommand", params) return &CommandRunner_ExecuteCommand_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } @@ -54,12 +53,12 @@ type CommandRunner_ExecuteCommand_OngoingVerification struct { methodInvocations []pegomock.MethodInvocation } -func (c *CommandRunner_ExecuteCommand_OngoingVerification) GetCapturedArguments() (models.Repo, models.Repo, models.User, int, *events.Command, vcs.Host) { - baseRepo, headRepo, user, pullNum, cmd, vcsHost := c.GetAllCapturedArguments() - return baseRepo[len(baseRepo)-1], headRepo[len(headRepo)-1], user[len(user)-1], pullNum[len(pullNum)-1], cmd[len(cmd)-1], vcsHost[len(vcsHost)-1] +func (c *CommandRunner_ExecuteCommand_OngoingVerification) GetCapturedArguments() (models.Repo, models.Repo, models.User, int, *events.Command) { + baseRepo, headRepo, user, pullNum, cmd := c.GetAllCapturedArguments() + return baseRepo[len(baseRepo)-1], headRepo[len(headRepo)-1], user[len(user)-1], pullNum[len(pullNum)-1], cmd[len(cmd)-1] } -func (c *CommandRunner_ExecuteCommand_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []models.Repo, _param2 []models.User, _param3 []int, _param4 []*events.Command, _param5 []vcs.Host) { +func (c *CommandRunner_ExecuteCommand_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []models.Repo, _param2 []models.User, _param3 []int, _param4 []*events.Command) { params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) if len(params) > 0 { _param0 = make([]models.Repo, len(params[0])) @@ -82,10 +81,6 @@ func (c *CommandRunner_ExecuteCommand_OngoingVerification) GetAllCapturedArgumen for u, param := range params[4] { _param4[u] = param.(*events.Command) } - _param5 = make([]vcs.Host, len(params[5])) - for u, param := range params[5] { - _param5[u] = param.(vcs.Host) - } } return } diff --git a/server/events/mocks/mock_comment_parsing.go b/server/events/mocks/mock_comment_parsing.go index 54dabbd7de..fed14dc14a 100644 --- a/server/events/mocks/mock_comment_parsing.go +++ b/server/events/mocks/mock_comment_parsing.go @@ -8,7 +8,7 @@ import ( pegomock "github.com/petergtz/pegomock" events "github.com/runatlantis/atlantis/server/events" - vcs "github.com/runatlantis/atlantis/server/events/vcs" + models "github.com/runatlantis/atlantis/server/events/models" ) type MockCommentParsing struct { @@ -19,7 +19,7 @@ func NewMockCommentParsing() *MockCommentParsing { return &MockCommentParsing{fail: pegomock.GlobalFailHandler} } -func (mock *MockCommentParsing) Parse(comment string, vcsHost vcs.Host) events.CommentParseResult { +func (mock *MockCommentParsing) Parse(comment string, vcsHost models.VCSHostType) events.CommentParseResult { params := []pegomock.Param{comment, vcsHost} result := pegomock.GetGenericMockFrom(mock).Invoke("Parse", params, []reflect.Type{reflect.TypeOf((*events.CommentParseResult)(nil)).Elem()}) var ret0 events.CommentParseResult @@ -49,7 +49,7 @@ type VerifierCommentParsing struct { inOrderContext *pegomock.InOrderContext } -func (verifier *VerifierCommentParsing) Parse(comment string, vcsHost vcs.Host) *CommentParsing_Parse_OngoingVerification { +func (verifier *VerifierCommentParsing) Parse(comment string, vcsHost models.VCSHostType) *CommentParsing_Parse_OngoingVerification { params := []pegomock.Param{comment, vcsHost} methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Parse", params) return &CommentParsing_Parse_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} @@ -60,21 +60,21 @@ type CommentParsing_Parse_OngoingVerification struct { methodInvocations []pegomock.MethodInvocation } -func (c *CommentParsing_Parse_OngoingVerification) GetCapturedArguments() (string, vcs.Host) { +func (c *CommentParsing_Parse_OngoingVerification) GetCapturedArguments() (string, models.VCSHostType) { comment, vcsHost := c.GetAllCapturedArguments() return comment[len(comment)-1], vcsHost[len(vcsHost)-1] } -func (c *CommentParsing_Parse_OngoingVerification) GetAllCapturedArguments() (_param0 []string, _param1 []vcs.Host) { +func (c *CommentParsing_Parse_OngoingVerification) GetAllCapturedArguments() (_param0 []string, _param1 []models.VCSHostType) { params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) if len(params) > 0 { _param0 = make([]string, len(params[0])) for u, param := range params[0] { _param0[u] = param.(string) } - _param1 = make([]vcs.Host, len(params[1])) + _param1 = make([]models.VCSHostType, len(params[1])) for u, param := range params[1] { - _param1[u] = param.(vcs.Host) + _param1[u] = param.(models.VCSHostType) } } return diff --git a/server/events/mocks/mock_commit_status_updater.go b/server/events/mocks/mock_commit_status_updater.go index 6a51f79881..3ed9e933b4 100644 --- a/server/events/mocks/mock_commit_status_updater.go +++ b/server/events/mocks/mock_commit_status_updater.go @@ -20,8 +20,8 @@ func NewMockCommitStatusUpdater() *MockCommitStatusUpdater { return &MockCommitStatusUpdater{fail: pegomock.GlobalFailHandler} } -func (mock *MockCommitStatusUpdater) Update(repo models.Repo, pull models.PullRequest, status vcs.CommitStatus, cmd *events.Command, host vcs.Host) error { - params := []pegomock.Param{repo, pull, status, cmd, host} +func (mock *MockCommitStatusUpdater) Update(repo models.Repo, pull models.PullRequest, status vcs.CommitStatus, cmd *events.Command) error { + params := []pegomock.Param{repo, pull, status, cmd} result := pegomock.GetGenericMockFrom(mock).Invoke("Update", params, []reflect.Type{reflect.TypeOf((*error)(nil)).Elem()}) var ret0 error if len(result) != 0 { @@ -62,8 +62,8 @@ type VerifierCommitStatusUpdater struct { inOrderContext *pegomock.InOrderContext } -func (verifier *VerifierCommitStatusUpdater) Update(repo models.Repo, pull models.PullRequest, status vcs.CommitStatus, cmd *events.Command, host vcs.Host) *CommitStatusUpdater_Update_OngoingVerification { - params := []pegomock.Param{repo, pull, status, cmd, host} +func (verifier *VerifierCommitStatusUpdater) Update(repo models.Repo, pull models.PullRequest, status vcs.CommitStatus, cmd *events.Command) *CommitStatusUpdater_Update_OngoingVerification { + params := []pegomock.Param{repo, pull, status, cmd} methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Update", params) return &CommitStatusUpdater_Update_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } @@ -73,12 +73,12 @@ type CommitStatusUpdater_Update_OngoingVerification struct { methodInvocations []pegomock.MethodInvocation } -func (c *CommitStatusUpdater_Update_OngoingVerification) GetCapturedArguments() (models.Repo, models.PullRequest, vcs.CommitStatus, *events.Command, vcs.Host) { - repo, pull, status, cmd, host := c.GetAllCapturedArguments() - return repo[len(repo)-1], pull[len(pull)-1], status[len(status)-1], cmd[len(cmd)-1], host[len(host)-1] +func (c *CommitStatusUpdater_Update_OngoingVerification) GetCapturedArguments() (models.Repo, models.PullRequest, vcs.CommitStatus, *events.Command) { + repo, pull, status, cmd := c.GetAllCapturedArguments() + return repo[len(repo)-1], pull[len(pull)-1], status[len(status)-1], cmd[len(cmd)-1] } -func (c *CommitStatusUpdater_Update_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []models.PullRequest, _param2 []vcs.CommitStatus, _param3 []*events.Command, _param4 []vcs.Host) { +func (c *CommitStatusUpdater_Update_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []models.PullRequest, _param2 []vcs.CommitStatus, _param3 []*events.Command) { params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) if len(params) > 0 { _param0 = make([]models.Repo, len(params[0])) @@ -97,10 +97,6 @@ func (c *CommitStatusUpdater_Update_OngoingVerification) GetAllCapturedArguments for u, param := range params[3] { _param3[u] = param.(*events.Command) } - _param4 = make([]vcs.Host, len(params[4])) - for u, param := range params[4] { - _param4[u] = param.(vcs.Host) - } } return } diff --git a/server/events/mocks/mock_pull_cleaner.go b/server/events/mocks/mock_pull_cleaner.go index 8801279099..c7930238e4 100644 --- a/server/events/mocks/mock_pull_cleaner.go +++ b/server/events/mocks/mock_pull_cleaner.go @@ -8,7 +8,6 @@ import ( pegomock "github.com/petergtz/pegomock" models "github.com/runatlantis/atlantis/server/events/models" - vcs "github.com/runatlantis/atlantis/server/events/vcs" ) type MockPullCleaner struct { @@ -19,8 +18,8 @@ func NewMockPullCleaner() *MockPullCleaner { return &MockPullCleaner{fail: pegomock.GlobalFailHandler} } -func (mock *MockPullCleaner) CleanUpPull(repo models.Repo, pull models.PullRequest, host vcs.Host) error { - params := []pegomock.Param{repo, pull, host} +func (mock *MockPullCleaner) CleanUpPull(repo models.Repo, pull models.PullRequest) error { + params := []pegomock.Param{repo, pull} result := pegomock.GetGenericMockFrom(mock).Invoke("CleanUpPull", params, []reflect.Type{reflect.TypeOf((*error)(nil)).Elem()}) var ret0 error if len(result) != 0 { @@ -49,8 +48,8 @@ type VerifierPullCleaner struct { inOrderContext *pegomock.InOrderContext } -func (verifier *VerifierPullCleaner) CleanUpPull(repo models.Repo, pull models.PullRequest, host vcs.Host) *PullCleaner_CleanUpPull_OngoingVerification { - params := []pegomock.Param{repo, pull, host} +func (verifier *VerifierPullCleaner) CleanUpPull(repo models.Repo, pull models.PullRequest) *PullCleaner_CleanUpPull_OngoingVerification { + params := []pegomock.Param{repo, pull} methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "CleanUpPull", params) return &PullCleaner_CleanUpPull_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } @@ -60,12 +59,12 @@ type PullCleaner_CleanUpPull_OngoingVerification struct { methodInvocations []pegomock.MethodInvocation } -func (c *PullCleaner_CleanUpPull_OngoingVerification) GetCapturedArguments() (models.Repo, models.PullRequest, vcs.Host) { - repo, pull, host := c.GetAllCapturedArguments() - return repo[len(repo)-1], pull[len(pull)-1], host[len(host)-1] +func (c *PullCleaner_CleanUpPull_OngoingVerification) GetCapturedArguments() (models.Repo, models.PullRequest) { + repo, pull := c.GetAllCapturedArguments() + return repo[len(repo)-1], pull[len(pull)-1] } -func (c *PullCleaner_CleanUpPull_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []models.PullRequest, _param2 []vcs.Host) { +func (c *PullCleaner_CleanUpPull_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []models.PullRequest) { params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) if len(params) > 0 { _param0 = make([]models.Repo, len(params[0])) @@ -76,10 +75,6 @@ func (c *PullCleaner_CleanUpPull_OngoingVerification) GetAllCapturedArguments() for u, param := range params[1] { _param1[u] = param.(models.PullRequest) } - _param2 = make([]vcs.Host, len(params[2])) - for u, param := range params[2] { - _param2[u] = param.(vcs.Host) - } } return } diff --git a/server/events/models/fixtures/fixtures.go b/server/events/models/fixtures/fixtures.go index 4935831984..a44b104cf3 100644 --- a/server/events/models/fixtures/fixtures.go +++ b/server/events/models/fixtures/fixtures.go @@ -23,12 +23,28 @@ var Pull = models.PullRequest{ URL: "url", } -var Repo = models.Repo{ +var GithubRepo = models.Repo{ CloneURL: "https://user:password@github.com/runatlantis/atlantis.git", FullName: "runatlantis/atlantis", Owner: "runatlantis", SanitizedCloneURL: "https://github.com/runatlantis/atlantis.git", Name: "atlantis", + VCSHost: models.VCSHost{ + Hostname: "github.com", + Type: models.Github, + }, +} + +var GitlabRepo = models.Repo{ + CloneURL: "https://user:password@github.com/runatlantis/atlantis.git", + FullName: "runatlantis/atlantis", + Owner: "runatlantis", + SanitizedCloneURL: "https://gitlab.com/runatlantis/atlantis.git", + Name: "atlantis", + VCSHost: models.VCSHost{ + Hostname: "gitlab.com", + Type: models.Gitlab, + }, } var User = models.User{ diff --git a/server/events/models/models.go b/server/events/models/models.go index bb345b2d08..3775a40a2f 100644 --- a/server/events/models/models.go +++ b/server/events/models/models.go @@ -41,11 +41,11 @@ type Repo struct { // SanitizedCloneURL is the full HTTPS url for cloning without the username and password. // ex. "https://github.com/atlantis/atlantis.git". SanitizedCloneURL string - // Hostname of the VCS provider this repo is hosted on. - Hostname string + // VCSHost is where this repo is hosted. + VCSHost VCSHost } -func NewRepo(repoFullName string, cloneURL string, vcsUser string, vcsToken string) (Repo, error) { +func NewRepo(vcsHostType VCSHostType, repoFullName string, cloneURL string, vcsUser string, vcsToken string) (Repo, error) { if repoFullName == "" { return Repo{}, errors.New("repoFullName can't be empty") } @@ -85,7 +85,10 @@ func NewRepo(repoFullName string, cloneURL string, vcsUser string, vcsToken stri Name: repo, CloneURL: authedCloneURL, SanitizedCloneURL: cloneURL, - Hostname: cloneURLParsed.Hostname(), + VCSHost: VCSHost{ + Type: vcsHostType, + Hostname: cloneURLParsed.Hostname(), + }, }, nil } @@ -173,3 +176,30 @@ func NewProject(repoFullName string, path string) Project { Path: path, } } + +// VCSHost is a Git hosting provider, for example GitHub. +type VCSHost struct { + // Hostname is the hostname of the VCS provider, ex. "github.com" or + // "github-enterprise.example.com". + Hostname string + + // Type is which type of VCS host this is, ex. GitHub or GitLab. + Type VCSHostType +} + +type VCSHostType int + +const ( + Github VCSHostType = iota + Gitlab +) + +func (h VCSHostType) String() string { + switch h { + case Github: + return "Github" + case Gitlab: + return "Gitlab" + } + return "" +} diff --git a/server/events/models/models_test.go b/server/events/models/models_test.go index 937f91a639..0dbb4f49ff 100644 --- a/server/events/models/models_test.go +++ b/server/events/models/models_test.go @@ -22,22 +22,22 @@ import ( ) func TestNewRepo_EmptyRepoFullName(t *testing.T) { - _, err := models.NewRepo("", "https://github.com/notowner/repo.git", "u", "p") + _, err := models.NewRepo(models.Github, "", "https://github.com/notowner/repo.git", "u", "p") ErrEquals(t, "repoFullName can't be empty", err) } func TestNewRepo_EmptyCloneURL(t *testing.T) { - _, err := models.NewRepo("owner/repo", "", "u", "p") + _, err := models.NewRepo(models.Github, "owner/repo", "", "u", "p") ErrEquals(t, "cloneURL can't be empty", err) } func TestNewRepo_InvalidCloneURL(t *testing.T) { - _, err := models.NewRepo("owner/repo", ":", "u", "p") + _, err := models.NewRepo(models.Github, "owner/repo", ":", "u", "p") ErrEquals(t, "invalid clone url: parse :: missing protocol scheme", err) } func TestNewRepo_CloneURLWrongRepo(t *testing.T) { - _, err := models.NewRepo("owner/repo", "https://github.com/notowner/repo.git", "u", "p") + _, err := models.NewRepo(models.Github, "owner/repo", "https://github.com/notowner/repo.git", "u", "p") ErrEquals(t, `expected clone url to have path "/owner/repo.git" but had "/notowner/repo.git"`, err) } @@ -53,7 +53,7 @@ func TestNewRepo_FullNameWrongFormat(t *testing.T) { for _, c := range cases { t.Run(c, func(t *testing.T) { cloneURL := fmt.Sprintf("https://github.com/%s.git", c) - _, err := models.NewRepo(c, cloneURL, "u", "p") + _, err := models.NewRepo(models.Github, c, cloneURL, "u", "p") ErrEquals(t, fmt.Sprintf(`invalid repo format "%s"`, c), err) }) } @@ -61,10 +61,13 @@ func TestNewRepo_FullNameWrongFormat(t *testing.T) { func TestNewRepo_HTTPAuth(t *testing.T) { // When the url has http the auth should be added. - repo, err := models.NewRepo("owner/repo", "http://github.com/owner/repo.git", "u", "p") + repo, err := models.NewRepo(models.Github, "owner/repo", "http://github.com/owner/repo.git", "u", "p") Ok(t, err) Equals(t, models.Repo{ - Hostname: "github.com", + VCSHost: models.VCSHost{ + Hostname: "github.com", + Type: models.Github, + }, SanitizedCloneURL: "http://github.com/owner/repo.git", CloneURL: "http://u:p@github.com/owner/repo.git", FullName: "owner/repo", @@ -75,10 +78,13 @@ func TestNewRepo_HTTPAuth(t *testing.T) { func TestNewRepo_HTTPSAuth(t *testing.T) { // When the url has https the auth should be added. - repo, err := models.NewRepo("owner/repo", "https://github.com/owner/repo.git", "u", "p") + repo, err := models.NewRepo(models.Github, "owner/repo", "https://github.com/owner/repo.git", "u", "p") Ok(t, err) Equals(t, models.Repo{ - Hostname: "github.com", + VCSHost: models.VCSHost{ + Hostname: "github.com", + Type: models.Github, + }, SanitizedCloneURL: "https://github.com/owner/repo.git", CloneURL: "https://u:p@github.com/owner/repo.git", FullName: "owner/repo", diff --git a/server/events/plan_executor.go b/server/events/plan_executor.go index e6ec2fa403..478de10a22 100644 --- a/server/events/plan_executor.go +++ b/server/events/plan_executor.go @@ -74,7 +74,7 @@ func (p *PlanExecutor) Execute(ctx *CommandContext) CommandResponse { if ctx.Command.Dir == "" { // If they didn't specify a directory to plan in, figure out what // projects have been modified so we know where to run plan. - modifiedFiles, err := p.VCSClient.GetModifiedFiles(ctx.BaseRepo, ctx.Pull, ctx.VCSHost) + modifiedFiles, err := p.VCSClient.GetModifiedFiles(ctx.BaseRepo, ctx.Pull) if err != nil { return CommandResponse{Error: errors.Wrap(err, "getting modified files")} } diff --git a/server/events/plan_executor_test.go b/server/events/plan_executor_test.go index 61c7b37d6a..24e5452c9b 100644 --- a/server/events/plan_executor_test.go +++ b/server/events/plan_executor_test.go @@ -50,7 +50,7 @@ var planCtx = events.CommandContext{ func TestExecute_ModifiedFilesErr(t *testing.T) { t.Log("If GetModifiedFiles returns an error we return an error") p, _, _ := setupPlanExecutorTest(t) - When(p.VCSClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest(), matchers.AnyVcsHost())).ThenReturn(nil, errors.New("err")) + When(p.VCSClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest())).ThenReturn(nil, errors.New("err")) r := p.Execute(&planCtx) Assert(t, r.Error != nil, "exp .Error to be set") @@ -70,7 +70,7 @@ func TestExecute_NoModifiedProjects(t *testing.T) { func TestExecute_CloneErr(t *testing.T) { t.Log("If AtlantisWorkspace.Clone returns an error we return an error") p, _, _ := setupPlanExecutorTest(t) - When(p.VCSClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest(), matchers.AnyVcsHost())).ThenReturn([]string{"file.tf"}, nil) + When(p.VCSClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest())).ThenReturn([]string{"file.tf"}, nil) When(p.Workspace.Clone(planCtx.Log, planCtx.BaseRepo, planCtx.HeadRepo, planCtx.Pull, "workspace")).ThenReturn("", errors.New("err")) r := p.Execute(&planCtx) @@ -117,7 +117,7 @@ func TestExecute_AddedArgs(t *testing.T) { ctx.Log = logging.NewNoopLogger() ctx.Command.Flags = []string{"\"-target=resource\"", "\"-var\"", "\"a=b\"", "\";\"", "\"echo\"", "\"hi\""} - When(p.VCSClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest(), matchers.AnyVcsHost())).ThenReturn([]string{"file.tf"}, nil) + When(p.VCSClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest())).ThenReturn([]string{"file.tf"}, nil) When(p.Workspace.Clone(ctx.Log, ctx.BaseRepo, ctx.HeadRepo, ctx.Pull, "workspace")). ThenReturn("/tmp/clone-repo", nil) When(p.ProjectPreExecute.Execute(&ctx, "/tmp/clone-repo", models.Project{RepoFullName: "", Path: "."})). @@ -161,7 +161,7 @@ func TestExecute_AddedArgs(t *testing.T) { func TestExecute_Success(t *testing.T) { t.Log("If there are no errors, the plan should be returned") p, runner, _ := setupPlanExecutorTest(t) - When(p.VCSClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest(), matchers.AnyVcsHost())).ThenReturn([]string{"file.tf"}, nil) + When(p.VCSClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest())).ThenReturn([]string{"file.tf"}, nil) When(p.Workspace.Clone(planCtx.Log, planCtx.BaseRepo, planCtx.HeadRepo, planCtx.Pull, "workspace")). ThenReturn("/tmp/clone-repo", nil) When(p.ProjectPreExecute.Execute(&planCtx, "/tmp/clone-repo", models.Project{RepoFullName: "", Path: "."})). @@ -190,7 +190,7 @@ func TestExecute_Success(t *testing.T) { func TestExecute_PreExecuteResult(t *testing.T) { t.Log("If DefaultProjectPreExecutor.Execute returns a ProjectResult we should return it") p, _, _ := setupPlanExecutorTest(t) - When(p.VCSClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest(), matchers.AnyVcsHost())).ThenReturn([]string{"file.tf"}, nil) + When(p.VCSClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest())).ThenReturn([]string{"file.tf"}, nil) When(p.Workspace.Clone(planCtx.Log, planCtx.BaseRepo, planCtx.HeadRepo, planCtx.Pull, "workspace")). ThenReturn("/tmp/clone-repo", nil) projectResult := events.ProjectResult{ @@ -209,7 +209,7 @@ func TestExecute_MultiProjectFailure(t *testing.T) { t.Log("If is an error planning in one project it should be returned. It shouldn't affect another project though.") p, runner, locker := setupPlanExecutorTest(t) // Two projects have been modified so we should run plan in two paths. - When(p.VCSClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest(), matchers.AnyVcsHost())).ThenReturn([]string{"path1/file.tf", "path2/file.tf"}, nil) + When(p.VCSClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest())).ThenReturn([]string{"path1/file.tf", "path2/file.tf"}, nil) When(p.Workspace.Clone(planCtx.Log, planCtx.BaseRepo, planCtx.HeadRepo, planCtx.Pull, "workspace")). ThenReturn("/tmp/clone-repo", nil) @@ -249,7 +249,7 @@ func TestExecute_MultiProjectFailure(t *testing.T) { func TestExecute_PostPlanCommands(t *testing.T) { t.Log("Should execute post-plan commands and return if there is an error") p, _, _ := setupPlanExecutorTest(t) - When(p.VCSClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest(), matchers.AnyVcsHost())).ThenReturn([]string{"file.tf"}, nil) + When(p.VCSClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest())).ThenReturn([]string{"file.tf"}, nil) When(p.Workspace.Clone(planCtx.Log, planCtx.BaseRepo, planCtx.HeadRepo, planCtx.Pull, "workspace")). ThenReturn("/tmp/clone-repo", nil) When(p.ProjectPreExecute.Execute(&planCtx, "/tmp/clone-repo", models.Project{RepoFullName: "", Path: "."})). diff --git a/server/events/pull_closed_executor.go b/server/events/pull_closed_executor.go index e5b7397de9..79dadeff0f 100644 --- a/server/events/pull_closed_executor.go +++ b/server/events/pull_closed_executor.go @@ -32,7 +32,7 @@ import ( type PullCleaner interface { // CleanUpPull deletes the workspaces used by the pull request on disk // and deletes any locks associated with this pull request for all workspaces. - CleanUpPull(repo models.Repo, pull models.PullRequest, host vcs.Host) error + CleanUpPull(repo models.Repo, pull models.PullRequest) error } // PullClosedExecutor executes the tasks required to clean up a closed pull @@ -54,7 +54,7 @@ var pullClosedTemplate = template.Must(template.New("").Parse( "- path: `{{ .Path }}` {{ .Workspaces }}{{ end }}")) // CleanUpPull cleans up after a closed pull request. -func (p *PullClosedExecutor) CleanUpPull(repo models.Repo, pull models.PullRequest, host vcs.Host) error { +func (p *PullClosedExecutor) CleanUpPull(repo models.Repo, pull models.PullRequest) error { if err := p.Workspace.Delete(repo, pull); err != nil { return errors.Wrap(err, "cleaning workspace") } @@ -77,7 +77,7 @@ func (p *PullClosedExecutor) CleanUpPull(repo models.Repo, pull models.PullReque if err = pullClosedTemplate.Execute(&buf, templateData); err != nil { return errors.Wrap(err, "rendering template for comment") } - return p.VCSClient.CreateComment(repo, pull.Num, buf.String(), host) + return p.VCSClient.CreateComment(repo, pull.Num, buf.String()) } // buildTemplateData formats the lock data into a slice that can easily be diff --git a/server/events/pull_closed_executor_test.go b/server/events/pull_closed_executor_test.go index 637077c739..e130a5304d 100644 --- a/server/events/pull_closed_executor_test.go +++ b/server/events/pull_closed_executor_test.go @@ -24,7 +24,6 @@ import ( "github.com/runatlantis/atlantis/server/events/mocks/matchers" "github.com/runatlantis/atlantis/server/events/models" "github.com/runatlantis/atlantis/server/events/models/fixtures" - "github.com/runatlantis/atlantis/server/events/vcs" vcsmocks "github.com/runatlantis/atlantis/server/events/vcs/mocks" . "github.com/runatlantis/atlantis/testing" ) @@ -37,8 +36,8 @@ func TestCleanUpPullWorkspaceErr(t *testing.T) { Workspace: w, } err := errors.New("err") - When(w.Delete(fixtures.Repo, fixtures.Pull)).ThenReturn(err) - actualErr := pce.CleanUpPull(fixtures.Repo, fixtures.Pull, vcs.Github) + When(w.Delete(fixtures.GithubRepo, fixtures.Pull)).ThenReturn(err) + actualErr := pce.CleanUpPull(fixtures.GithubRepo, fixtures.Pull) Equals(t, "cleaning workspace: err", actualErr.Error()) } @@ -52,8 +51,8 @@ func TestCleanUpPullUnlockErr(t *testing.T) { Workspace: w, } err := errors.New("err") - When(l.UnlockByPull(fixtures.Repo.FullName, fixtures.Pull.Num)).ThenReturn(nil, err) - actualErr := pce.CleanUpPull(fixtures.Repo, fixtures.Pull, vcs.Github) + When(l.UnlockByPull(fixtures.GithubRepo.FullName, fixtures.Pull.Num)).ThenReturn(nil, err) + actualErr := pce.CleanUpPull(fixtures.GithubRepo, fixtures.Pull) Equals(t, "cleaning up locks: err", actualErr.Error()) } @@ -68,10 +67,10 @@ func TestCleanUpPullNoLocks(t *testing.T) { VCSClient: cp, Workspace: w, } - When(l.UnlockByPull(fixtures.Repo.FullName, fixtures.Pull.Num)).ThenReturn(nil, nil) - err := pce.CleanUpPull(fixtures.Repo, fixtures.Pull, vcs.Github) + When(l.UnlockByPull(fixtures.GithubRepo.FullName, fixtures.Pull.Num)).ThenReturn(nil, nil) + err := pce.CleanUpPull(fixtures.GithubRepo, fixtures.Pull) Ok(t, err) - cp.VerifyWasCalled(Never()).CreateComment(matchers.AnyModelsRepo(), AnyInt(), AnyString(), matchers.AnyVcsHost()) + cp.VerifyWasCalled(Never()).CreateComment(matchers.AnyModelsRepo(), AnyInt(), AnyString()) } func TestCleanUpPullComments(t *testing.T) { @@ -149,10 +148,10 @@ func TestCleanUpPullComments(t *testing.T) { Workspace: w, } t.Log("testing: " + c.Description) - When(l.UnlockByPull(fixtures.Repo.FullName, fixtures.Pull.Num)).ThenReturn(c.Locks, nil) - err := pce.CleanUpPull(fixtures.Repo, fixtures.Pull, vcs.Github) + When(l.UnlockByPull(fixtures.GithubRepo.FullName, fixtures.Pull.Num)).ThenReturn(c.Locks, nil) + err := pce.CleanUpPull(fixtures.GithubRepo, fixtures.Pull) Ok(t, err) - _, _, comment, _ := cp.VerifyWasCalledOnce().CreateComment(matchers.AnyModelsRepo(), AnyInt(), AnyString(), matchers.AnyVcsHost()).GetCapturedArguments() + _, _, comment := cp.VerifyWasCalledOnce().CreateComment(matchers.AnyModelsRepo(), AnyInt(), AnyString()).GetCapturedArguments() expected := "Locks and plans deleted for the projects and workspaces modified in this pull request:\n\n" + c.Exp Equals(t, expected, comment) diff --git a/server/events/vcs/mocks/matchers/vcs_host.go b/server/events/vcs/mocks/matchers/vcs_host.go deleted file mode 100644 index 51a6399dc4..0000000000 --- a/server/events/vcs/mocks/matchers/vcs_host.go +++ /dev/null @@ -1,20 +0,0 @@ -package matchers - -import ( - "reflect" - - "github.com/petergtz/pegomock" - vcs "github.com/runatlantis/atlantis/server/events/vcs" -) - -func AnyVcsHost() vcs.Host { - pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*(vcs.Host))(nil)).Elem())) - var nullValue vcs.Host - return nullValue -} - -func EqVcsHost(value vcs.Host) vcs.Host { - pegomock.RegisterMatcher(&pegomock.EqMatcher{Value: value}) - var nullValue vcs.Host - return nullValue -} diff --git a/server/events/vcs/mocks/mock_proxy.go b/server/events/vcs/mocks/mock_proxy.go index 287757193e..d773f11cd4 100644 --- a/server/events/vcs/mocks/mock_proxy.go +++ b/server/events/vcs/mocks/mock_proxy.go @@ -19,8 +19,8 @@ func NewMockClientProxy() *MockClientProxy { return &MockClientProxy{fail: pegomock.GlobalFailHandler} } -func (mock *MockClientProxy) GetModifiedFiles(repo models.Repo, pull models.PullRequest, host vcs.Host) ([]string, error) { - params := []pegomock.Param{repo, pull, host} +func (mock *MockClientProxy) GetModifiedFiles(repo models.Repo, pull models.PullRequest) ([]string, error) { + params := []pegomock.Param{repo, pull} result := pegomock.GetGenericMockFrom(mock).Invoke("GetModifiedFiles", params, []reflect.Type{reflect.TypeOf((*[]string)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()}) var ret0 []string var ret1 error @@ -35,8 +35,8 @@ func (mock *MockClientProxy) GetModifiedFiles(repo models.Repo, pull models.Pull return ret0, ret1 } -func (mock *MockClientProxy) CreateComment(repo models.Repo, pullNum int, comment string, host vcs.Host) error { - params := []pegomock.Param{repo, pullNum, comment, host} +func (mock *MockClientProxy) CreateComment(repo models.Repo, pullNum int, comment string) error { + params := []pegomock.Param{repo, pullNum, comment} result := pegomock.GetGenericMockFrom(mock).Invoke("CreateComment", params, []reflect.Type{reflect.TypeOf((*error)(nil)).Elem()}) var ret0 error if len(result) != 0 { @@ -47,8 +47,8 @@ func (mock *MockClientProxy) CreateComment(repo models.Repo, pullNum int, commen return ret0 } -func (mock *MockClientProxy) PullIsApproved(repo models.Repo, pull models.PullRequest, host vcs.Host) (bool, error) { - params := []pegomock.Param{repo, pull, host} +func (mock *MockClientProxy) PullIsApproved(repo models.Repo, pull models.PullRequest) (bool, error) { + params := []pegomock.Param{repo, pull} result := pegomock.GetGenericMockFrom(mock).Invoke("PullIsApproved", params, []reflect.Type{reflect.TypeOf((*bool)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()}) var ret0 bool var ret1 error @@ -63,8 +63,8 @@ func (mock *MockClientProxy) PullIsApproved(repo models.Repo, pull models.PullRe return ret0, ret1 } -func (mock *MockClientProxy) UpdateStatus(repo models.Repo, pull models.PullRequest, state vcs.CommitStatus, description string, host vcs.Host) error { - params := []pegomock.Param{repo, pull, state, description, host} +func (mock *MockClientProxy) UpdateStatus(repo models.Repo, pull models.PullRequest, state vcs.CommitStatus, description string) error { + params := []pegomock.Param{repo, pull, state, description} result := pegomock.GetGenericMockFrom(mock).Invoke("UpdateStatus", params, []reflect.Type{reflect.TypeOf((*error)(nil)).Elem()}) var ret0 error if len(result) != 0 { @@ -93,8 +93,8 @@ type VerifierClientProxy struct { inOrderContext *pegomock.InOrderContext } -func (verifier *VerifierClientProxy) GetModifiedFiles(repo models.Repo, pull models.PullRequest, host vcs.Host) *ClientProxy_GetModifiedFiles_OngoingVerification { - params := []pegomock.Param{repo, pull, host} +func (verifier *VerifierClientProxy) GetModifiedFiles(repo models.Repo, pull models.PullRequest) *ClientProxy_GetModifiedFiles_OngoingVerification { + params := []pegomock.Param{repo, pull} methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "GetModifiedFiles", params) return &ClientProxy_GetModifiedFiles_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } @@ -104,12 +104,12 @@ type ClientProxy_GetModifiedFiles_OngoingVerification struct { methodInvocations []pegomock.MethodInvocation } -func (c *ClientProxy_GetModifiedFiles_OngoingVerification) GetCapturedArguments() (models.Repo, models.PullRequest, vcs.Host) { - repo, pull, host := c.GetAllCapturedArguments() - return repo[len(repo)-1], pull[len(pull)-1], host[len(host)-1] +func (c *ClientProxy_GetModifiedFiles_OngoingVerification) GetCapturedArguments() (models.Repo, models.PullRequest) { + repo, pull := c.GetAllCapturedArguments() + return repo[len(repo)-1], pull[len(pull)-1] } -func (c *ClientProxy_GetModifiedFiles_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []models.PullRequest, _param2 []vcs.Host) { +func (c *ClientProxy_GetModifiedFiles_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []models.PullRequest) { params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) if len(params) > 0 { _param0 = make([]models.Repo, len(params[0])) @@ -120,16 +120,12 @@ func (c *ClientProxy_GetModifiedFiles_OngoingVerification) GetAllCapturedArgumen for u, param := range params[1] { _param1[u] = param.(models.PullRequest) } - _param2 = make([]vcs.Host, len(params[2])) - for u, param := range params[2] { - _param2[u] = param.(vcs.Host) - } } return } -func (verifier *VerifierClientProxy) CreateComment(repo models.Repo, pullNum int, comment string, host vcs.Host) *ClientProxy_CreateComment_OngoingVerification { - params := []pegomock.Param{repo, pullNum, comment, host} +func (verifier *VerifierClientProxy) CreateComment(repo models.Repo, pullNum int, comment string) *ClientProxy_CreateComment_OngoingVerification { + params := []pegomock.Param{repo, pullNum, comment} methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "CreateComment", params) return &ClientProxy_CreateComment_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } @@ -139,12 +135,12 @@ type ClientProxy_CreateComment_OngoingVerification struct { methodInvocations []pegomock.MethodInvocation } -func (c *ClientProxy_CreateComment_OngoingVerification) GetCapturedArguments() (models.Repo, int, string, vcs.Host) { - repo, pullNum, comment, host := c.GetAllCapturedArguments() - return repo[len(repo)-1], pullNum[len(pullNum)-1], comment[len(comment)-1], host[len(host)-1] +func (c *ClientProxy_CreateComment_OngoingVerification) GetCapturedArguments() (models.Repo, int, string) { + repo, pullNum, comment := c.GetAllCapturedArguments() + return repo[len(repo)-1], pullNum[len(pullNum)-1], comment[len(comment)-1] } -func (c *ClientProxy_CreateComment_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []int, _param2 []string, _param3 []vcs.Host) { +func (c *ClientProxy_CreateComment_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []int, _param2 []string) { params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) if len(params) > 0 { _param0 = make([]models.Repo, len(params[0])) @@ -159,16 +155,12 @@ func (c *ClientProxy_CreateComment_OngoingVerification) GetAllCapturedArguments( for u, param := range params[2] { _param2[u] = param.(string) } - _param3 = make([]vcs.Host, len(params[3])) - for u, param := range params[3] { - _param3[u] = param.(vcs.Host) - } } return } -func (verifier *VerifierClientProxy) PullIsApproved(repo models.Repo, pull models.PullRequest, host vcs.Host) *ClientProxy_PullIsApproved_OngoingVerification { - params := []pegomock.Param{repo, pull, host} +func (verifier *VerifierClientProxy) PullIsApproved(repo models.Repo, pull models.PullRequest) *ClientProxy_PullIsApproved_OngoingVerification { + params := []pegomock.Param{repo, pull} methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "PullIsApproved", params) return &ClientProxy_PullIsApproved_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } @@ -178,12 +170,12 @@ type ClientProxy_PullIsApproved_OngoingVerification struct { methodInvocations []pegomock.MethodInvocation } -func (c *ClientProxy_PullIsApproved_OngoingVerification) GetCapturedArguments() (models.Repo, models.PullRequest, vcs.Host) { - repo, pull, host := c.GetAllCapturedArguments() - return repo[len(repo)-1], pull[len(pull)-1], host[len(host)-1] +func (c *ClientProxy_PullIsApproved_OngoingVerification) GetCapturedArguments() (models.Repo, models.PullRequest) { + repo, pull := c.GetAllCapturedArguments() + return repo[len(repo)-1], pull[len(pull)-1] } -func (c *ClientProxy_PullIsApproved_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []models.PullRequest, _param2 []vcs.Host) { +func (c *ClientProxy_PullIsApproved_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []models.PullRequest) { params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) if len(params) > 0 { _param0 = make([]models.Repo, len(params[0])) @@ -194,16 +186,12 @@ func (c *ClientProxy_PullIsApproved_OngoingVerification) GetAllCapturedArguments for u, param := range params[1] { _param1[u] = param.(models.PullRequest) } - _param2 = make([]vcs.Host, len(params[2])) - for u, param := range params[2] { - _param2[u] = param.(vcs.Host) - } } return } -func (verifier *VerifierClientProxy) UpdateStatus(repo models.Repo, pull models.PullRequest, state vcs.CommitStatus, description string, host vcs.Host) *ClientProxy_UpdateStatus_OngoingVerification { - params := []pegomock.Param{repo, pull, state, description, host} +func (verifier *VerifierClientProxy) UpdateStatus(repo models.Repo, pull models.PullRequest, state vcs.CommitStatus, description string) *ClientProxy_UpdateStatus_OngoingVerification { + params := []pegomock.Param{repo, pull, state, description} methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "UpdateStatus", params) return &ClientProxy_UpdateStatus_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } @@ -213,12 +201,12 @@ type ClientProxy_UpdateStatus_OngoingVerification struct { methodInvocations []pegomock.MethodInvocation } -func (c *ClientProxy_UpdateStatus_OngoingVerification) GetCapturedArguments() (models.Repo, models.PullRequest, vcs.CommitStatus, string, vcs.Host) { - repo, pull, state, description, host := c.GetAllCapturedArguments() - return repo[len(repo)-1], pull[len(pull)-1], state[len(state)-1], description[len(description)-1], host[len(host)-1] +func (c *ClientProxy_UpdateStatus_OngoingVerification) GetCapturedArguments() (models.Repo, models.PullRequest, vcs.CommitStatus, string) { + repo, pull, state, description := c.GetAllCapturedArguments() + return repo[len(repo)-1], pull[len(pull)-1], state[len(state)-1], description[len(description)-1] } -func (c *ClientProxy_UpdateStatus_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []models.PullRequest, _param2 []vcs.CommitStatus, _param3 []string, _param4 []vcs.Host) { +func (c *ClientProxy_UpdateStatus_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []models.PullRequest, _param2 []vcs.CommitStatus, _param3 []string) { params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) if len(params) > 0 { _param0 = make([]models.Repo, len(params[0])) @@ -237,10 +225,6 @@ func (c *ClientProxy_UpdateStatus_OngoingVerification) GetAllCapturedArguments() for u, param := range params[3] { _param3[u] = param.(string) } - _param4 = make([]vcs.Host, len(params[4])) - for u, param := range params[4] { - _param4[u] = param.(vcs.Host) - } } return } diff --git a/server/events/vcs/not_configured_vcs_client.go b/server/events/vcs/not_configured_vcs_client.go index e1d983b4f6..8bf5967760 100644 --- a/server/events/vcs/not_configured_vcs_client.go +++ b/server/events/vcs/not_configured_vcs_client.go @@ -23,7 +23,7 @@ import ( // on startup to support a certain VCS host. For example, if there is no GitHub // config then this client will be used which will error if it's ever called. type NotConfiguredVCSClient struct { - Host Host + Host models.VCSHostType } func (a *NotConfiguredVCSClient) GetModifiedFiles(repo models.Repo, pull models.PullRequest) ([]string, error) { diff --git a/server/events/vcs/proxy.go b/server/events/vcs/proxy.go index 4c1db57b42..8db3b26638 100644 --- a/server/events/vcs/proxy.go +++ b/server/events/vcs/proxy.go @@ -23,10 +23,10 @@ import ( // ClientProxy proxies calls to the correct VCS client depending on which // VCS host is required. type ClientProxy interface { - GetModifiedFiles(repo models.Repo, pull models.PullRequest, host Host) ([]string, error) - CreateComment(repo models.Repo, pullNum int, comment string, host Host) error - PullIsApproved(repo models.Repo, pull models.PullRequest, host Host) (bool, error) - UpdateStatus(repo models.Repo, pull models.PullRequest, state CommitStatus, description string, host Host) error + GetModifiedFiles(repo models.Repo, pull models.PullRequest) ([]string, error) + CreateComment(repo models.Repo, pullNum int, comment string) error + PullIsApproved(repo models.Repo, pull models.PullRequest) (bool, error) + UpdateStatus(repo models.Repo, pull models.PullRequest, state CommitStatus, description string) error } // DefaultClientProxy proxies calls to the correct VCS client depending on which @@ -51,41 +51,41 @@ func NewDefaultClientProxy(githubClient Client, gitlabClient Client) *DefaultCli var invalidVCSErr = errors.New("Invalid VCS Host. This is a bug!") -func (d *DefaultClientProxy) GetModifiedFiles(repo models.Repo, pull models.PullRequest, host Host) ([]string, error) { - switch host { - case Github: +func (d *DefaultClientProxy) GetModifiedFiles(repo models.Repo, pull models.PullRequest) ([]string, error) { + switch repo.VCSHost.Type { + case models.Github: return d.GithubClient.GetModifiedFiles(repo, pull) - case Gitlab: + case models.Gitlab: return d.GitlabClient.GetModifiedFiles(repo, pull) } return nil, invalidVCSErr } -func (d *DefaultClientProxy) CreateComment(repo models.Repo, pullNum int, comment string, host Host) error { - switch host { - case Github: +func (d *DefaultClientProxy) CreateComment(repo models.Repo, pullNum int, comment string) error { + switch repo.VCSHost.Type { + case models.Github: return d.GithubClient.CreateComment(repo, pullNum, comment) - case Gitlab: + case models.Gitlab: return d.GitlabClient.CreateComment(repo, pullNum, comment) } return invalidVCSErr } -func (d *DefaultClientProxy) PullIsApproved(repo models.Repo, pull models.PullRequest, host Host) (bool, error) { - switch host { - case Github: +func (d *DefaultClientProxy) PullIsApproved(repo models.Repo, pull models.PullRequest) (bool, error) { + switch repo.VCSHost.Type { + case models.Github: return d.GithubClient.PullIsApproved(repo, pull) - case Gitlab: + case models.Gitlab: return d.GitlabClient.PullIsApproved(repo, pull) } return false, invalidVCSErr } -func (d *DefaultClientProxy) UpdateStatus(repo models.Repo, pull models.PullRequest, state CommitStatus, description string, host Host) error { - switch host { - case Github: +func (d *DefaultClientProxy) UpdateStatus(repo models.Repo, pull models.PullRequest, state CommitStatus, description string) error { + switch repo.VCSHost.Type { + case models.Github: return d.GithubClient.UpdateStatus(repo, pull, state, description) - case Gitlab: + case models.Gitlab: return d.GitlabClient.UpdateStatus(repo, pull, state, description) } return invalidVCSErr diff --git a/server/events/vcs/vcs.go b/server/events/vcs/vcs.go index 537ab9c4b8..3f0d53a6ff 100644 --- a/server/events/vcs/vcs.go +++ b/server/events/vcs/vcs.go @@ -13,23 +13,6 @@ // package vcs -type Host int - -const ( - Github Host = iota - Gitlab -) - -func (h Host) String() string { - switch h { - case Github: - return "Github" - case Gitlab: - return "Gitlab" - } - return "" -} - // CommitStatus is the result of executing an Atlantis command for the commit. // In Github the options are: error, failure, pending, success. // In Gitlab the options are: failed, canceled, pending, running, success. diff --git a/server/events_controller.go b/server/events_controller.go index 4ec4e5340a..b5a447be14 100644 --- a/server/events_controller.go +++ b/server/events_controller.go @@ -49,21 +49,21 @@ type EventsController struct { RepoWhitelist *events.RepoWhitelist // SupportedVCSHosts is which VCS hosts Atlantis was configured upon // startup to support. - SupportedVCSHosts []vcs.Host + SupportedVCSHosts []models.VCSHostType VCSClient vcs.ClientProxy } // Post handles POST webhook requests. func (e *EventsController) Post(w http.ResponseWriter, r *http.Request) { if r.Header.Get(githubHeader) != "" { - if !e.supportsHost(vcs.Github) { + if !e.supportsHost(models.Github) { e.respond(w, logging.Debug, http.StatusBadRequest, "Ignoring request since not configured to support GitHub") return } e.handleGithubPost(w, r) return } else if r.Header.Get(gitlabHeader) != "" { - if !e.supportsHost(vcs.Gitlab) { + if !e.supportsHost(models.Gitlab) { e.respond(w, logging.Debug, http.StatusBadRequest, "Ignoring request since not configured to support GitLab") return } @@ -111,7 +111,7 @@ func (e *EventsController) HandleGithubCommentEvent(w http.ResponseWriter, event // calls to get that information but we need this code path to be generic. // Later on in CommandHandler we detect that this is a GitHub event and // make the necessary calls to get the headRepo. - e.handleCommentEvent(w, baseRepo, models.Repo{}, user, pullNum, event.Comment.GetBody(), vcs.Github) + e.handleCommentEvent(w, baseRepo, models.Repo{}, user, pullNum, event.Comment.GetBody(), models.Github) } // HandleGithubPullRequestEvent will delete any locks associated with the pull @@ -128,11 +128,11 @@ func (e *EventsController) HandleGithubPullRequestEvent(w http.ResponseWriter, p e.respond(w, logging.Error, http.StatusBadRequest, "Error parsing repo data: %s %s", err, githubReqID) return } - e.handlePullRequestEvent(w, repo, pull, vcs.Github) + e.handlePullRequestEvent(w, repo, pull) } -func (e *EventsController) handlePullRequestEvent(w http.ResponseWriter, repo models.Repo, pull models.PullRequest, vcs vcs.Host) { - if !e.RepoWhitelist.IsWhitelisted(repo.FullName, repo.Hostname) { +func (e *EventsController) handlePullRequestEvent(w http.ResponseWriter, repo models.Repo, pull models.PullRequest) { + if !e.RepoWhitelist.IsWhitelisted(repo.FullName, repo.VCSHost.Hostname) { e.respond(w, logging.Debug, http.StatusForbidden, "Ignoring pull request event from non-whitelisted repo") return } @@ -140,7 +140,7 @@ func (e *EventsController) handlePullRequestEvent(w http.ResponseWriter, repo mo e.respond(w, logging.Debug, http.StatusOK, "Ignoring opened pull request event") return } - if err := e.PullCleaner.CleanUpPull(repo, pull, vcs); err != nil { + if err := e.PullCleaner.CleanUpPull(repo, pull); err != nil { e.respond(w, logging.Error, http.StatusInternalServerError, "Error cleaning pull request: %s", err) return } @@ -173,10 +173,10 @@ func (e *EventsController) HandleGitlabCommentEvent(w http.ResponseWriter, event e.respond(w, logging.Error, http.StatusBadRequest, "Error parsing webhook: %s", err) return } - e.handleCommentEvent(w, baseRepo, headRepo, user, event.MergeRequest.IID, event.ObjectAttributes.Note, vcs.Gitlab) + e.handleCommentEvent(w, baseRepo, headRepo, user, event.MergeRequest.IID, event.ObjectAttributes.Note, models.Gitlab) } -func (e *EventsController) handleCommentEvent(w http.ResponseWriter, baseRepo models.Repo, headRepo models.Repo, user models.User, pullNum int, comment string, vcsHost vcs.Host) { +func (e *EventsController) handleCommentEvent(w http.ResponseWriter, baseRepo models.Repo, headRepo models.Repo, user models.User, pullNum int, comment string, vcsHost models.VCSHostType) { parseResult := e.CommentParser.Parse(comment, vcsHost) if parseResult.Ignore { truncated := comment @@ -190,9 +190,9 @@ func (e *EventsController) handleCommentEvent(w http.ResponseWriter, baseRepo mo // At this point we know it's a command we're not supposed to ignore, so now // we check if this repo is allowed to run commands in the first place. - if !e.RepoWhitelist.IsWhitelisted(baseRepo.FullName, baseRepo.Hostname) { + if !e.RepoWhitelist.IsWhitelisted(baseRepo.FullName, baseRepo.VCSHost.Hostname) { errMsg := "```\nError: This repo is not whitelisted for Atlantis.\n```" - if err := e.VCSClient.CreateComment(baseRepo, pullNum, errMsg, vcsHost); err != nil { + if err := e.VCSClient.CreateComment(baseRepo, pullNum, errMsg); err != nil { e.Logger.Err("unable to comment on pull request: %s", err) } e.respond(w, logging.Warn, http.StatusForbidden, "Repo not whitelisted") @@ -204,7 +204,7 @@ func (e *EventsController) handleCommentEvent(w http.ResponseWriter, baseRepo mo // We do this here rather than earlier because we need access to the pull // variable to comment back on the pull request. if parseResult.CommentResponse != "" { - if err := e.VCSClient.CreateComment(baseRepo, pullNum, parseResult.CommentResponse, vcsHost); err != nil { + if err := e.VCSClient.CreateComment(baseRepo, pullNum, parseResult.CommentResponse); err != nil { e.Logger.Err("unable to comment on pull request: %s", err) } e.respond(w, logging.Info, http.StatusOK, "Commenting back on pull request") @@ -215,7 +215,7 @@ func (e *EventsController) handleCommentEvent(w http.ResponseWriter, baseRepo mo // We use a goroutine so that this function returns and the connection is // closed. fmt.Fprintln(w, "Processing...") - go e.CommandRunner.ExecuteCommand(baseRepo, headRepo, user, pullNum, parseResult.Command, vcsHost) + go e.CommandRunner.ExecuteCommand(baseRepo, headRepo, user, pullNum, parseResult.Command) } // HandleGitlabMergeRequestEvent will delete any locks associated with the pull @@ -227,11 +227,11 @@ func (e *EventsController) HandleGitlabMergeRequestEvent(w http.ResponseWriter, e.respond(w, logging.Error, http.StatusBadRequest, "Error parsing webhook: %s", err) return } - e.handlePullRequestEvent(w, repo, pull, vcs.Gitlab) + e.handlePullRequestEvent(w, repo, pull) } // supportsHost returns true if h is in e.SupportedVCSHosts and false otherwise. -func (e *EventsController) supportsHost(h vcs.Host) bool { +func (e *EventsController) supportsHost(h models.VCSHostType) bool { for _, supported := range e.SupportedVCSHosts { if h == supported { return true diff --git a/server/events_controller_test.go b/server/events_controller_test.go index 36eb07b82c..c4664f33e3 100644 --- a/server/events_controller_test.go +++ b/server/events_controller_test.go @@ -31,7 +31,6 @@ import ( emocks "github.com/runatlantis/atlantis/server/events/mocks" "github.com/runatlantis/atlantis/server/events/mocks/matchers" "github.com/runatlantis/atlantis/server/events/models" - "github.com/runatlantis/atlantis/server/events/vcs" vcsmocks "github.com/runatlantis/atlantis/server/events/vcs/mocks" "github.com/runatlantis/atlantis/server/logging" "github.com/runatlantis/atlantis/server/mocks" @@ -141,7 +140,7 @@ func TestPost_GitlabCommentInvalidCommand(t *testing.T) { e, _, gl, _, _, _, _, cp := setup(t) eventsReq.Header.Set(gitlabHeader, "value") When(gl.Validate(eventsReq, secret)).ThenReturn(gitlab.MergeCommentEvent{}, nil) - When(cp.Parse("", vcs.Gitlab)).ThenReturn(events.CommentParseResult{Ignore: true}) + When(cp.Parse("", models.Gitlab)).ThenReturn(events.CommentParseResult{Ignore: true}) w := httptest.NewRecorder() e.Post(w, eventsReq) responseContains(t, w, http.StatusOK, "Ignoring non-command comment: \"\"") @@ -154,7 +153,7 @@ func TestPost_GithubCommentInvalidCommand(t *testing.T) { event := `{"action": "created"}` When(v.Validate(eventsReq, secret)).ThenReturn([]byte(event), nil) When(p.ParseGithubIssueCommentEvent(matchers.AnyPtrToGithubIssueCommentEvent())).ThenReturn(models.Repo{}, models.User{}, 1, nil) - When(cp.Parse("", vcs.Github)).ThenReturn(events.CommentParseResult{Ignore: true}) + When(cp.Parse("", models.Github)).ThenReturn(events.CommentParseResult{Ignore: true}) w := httptest.NewRecorder() e.Post(w, eventsReq) responseContains(t, w, http.StatusOK, "Ignoring non-command comment: \"\"") @@ -169,7 +168,7 @@ func TestPost_GitlabCommentNotWhitelisted(t *testing.T) { CommentParser: &events.CommentParser{}, GitlabRequestParser: &server.DefaultGitlabRequestParser{}, Parser: &events.EventParser{}, - SupportedVCSHosts: []vcs.Host{vcs.Gitlab}, + SupportedVCSHosts: []models.VCSHostType{models.Gitlab}, RepoWhitelist: &events.RepoWhitelist{}, VCSClient: vcsClient, } @@ -184,8 +183,8 @@ func TestPost_GitlabCommentNotWhitelisted(t *testing.T) { body, _ := ioutil.ReadAll(w.Result().Body) exp := "Repo not whitelisted" Assert(t, strings.Contains(string(body), exp), "exp %q to be contained in %q", exp, string(body)) - expRepo, _ := models.NewRepo("gitlabhq/gitlab-test", "https://example.com/gitlabhq/gitlab-test.git", "", "") - vcsClient.VerifyWasCalledOnce().CreateComment(expRepo, 1, "```\nError: This repo is not whitelisted for Atlantis.\n```", vcs.Gitlab) + expRepo, _ := models.NewRepo(models.Gitlab, "gitlabhq/gitlab-test", "https://example.com/gitlabhq/gitlab-test.git", "", "") + vcsClient.VerifyWasCalledOnce().CreateComment(expRepo, 1, "```\nError: This repo is not whitelisted for Atlantis.\n```") } func TestPost_GithubCommentNotWhitelisted(t *testing.T) { @@ -197,7 +196,7 @@ func TestPost_GithubCommentNotWhitelisted(t *testing.T) { GithubRequestValidator: &server.DefaultGithubRequestValidator{}, CommentParser: &events.CommentParser{}, Parser: &events.EventParser{}, - SupportedVCSHosts: []vcs.Host{vcs.Github}, + SupportedVCSHosts: []models.VCSHostType{models.Github}, RepoWhitelist: &events.RepoWhitelist{}, VCSClient: vcsClient, } @@ -213,8 +212,8 @@ func TestPost_GithubCommentNotWhitelisted(t *testing.T) { body, _ := ioutil.ReadAll(w.Result().Body) exp := "Repo not whitelisted" Assert(t, strings.Contains(string(body), exp), "exp %q to be contained in %q", exp, string(body)) - expRepo, _ := models.NewRepo("baxterthehacker/public-repo", "https://github.com/baxterthehacker/public-repo.git", "", "") - vcsClient.VerifyWasCalledOnce().CreateComment(expRepo, 2, "```\nError: This repo is not whitelisted for Atlantis.\n```", vcs.Github) + expRepo, _ := models.NewRepo(models.Github, "baxterthehacker/public-repo", "https://github.com/baxterthehacker/public-repo.git", "", "") + vcsClient.VerifyWasCalledOnce().CreateComment(expRepo, 2, "```\nError: This repo is not whitelisted for Atlantis.\n```") } func TestPost_GitlabCommentResponse(t *testing.T) { @@ -222,10 +221,10 @@ func TestPost_GitlabCommentResponse(t *testing.T) { e, _, gl, _, _, _, vcsClient, cp := setup(t) eventsReq.Header.Set(gitlabHeader, "value") When(gl.Validate(eventsReq, secret)).ThenReturn(gitlab.MergeCommentEvent{}, nil) - When(cp.Parse("", vcs.Gitlab)).ThenReturn(events.CommentParseResult{CommentResponse: "a comment"}) + When(cp.Parse("", models.Gitlab)).ThenReturn(events.CommentParseResult{CommentResponse: "a comment"}) w := httptest.NewRecorder() e.Post(w, eventsReq) - vcsClient.VerifyWasCalledOnce().CreateComment(models.Repo{}, 0, "a comment", vcs.Gitlab) + vcsClient.VerifyWasCalledOnce().CreateComment(models.Repo{}, 0, "a comment") responseContains(t, w, http.StatusOK, "Commenting back on pull request") } @@ -238,11 +237,11 @@ func TestPost_GithubCommentResponse(t *testing.T) { baseRepo := models.Repo{} user := models.User{} When(p.ParseGithubIssueCommentEvent(matchers.AnyPtrToGithubIssueCommentEvent())).ThenReturn(baseRepo, user, 1, nil) - When(cp.Parse("", vcs.Github)).ThenReturn(events.CommentParseResult{CommentResponse: "a comment"}) + When(cp.Parse("", models.Github)).ThenReturn(events.CommentParseResult{CommentResponse: "a comment"}) w := httptest.NewRecorder() e.Post(w, eventsReq) - vcsClient.VerifyWasCalledOnce().CreateComment(baseRepo, 1, "a comment", vcs.Github) + vcsClient.VerifyWasCalledOnce().CreateComment(baseRepo, 1, "a comment") responseContains(t, w, http.StatusOK, "Commenting back on pull request") } @@ -257,7 +256,7 @@ func TestPost_GitlabCommentSuccess(t *testing.T) { // wait for 200ms so goroutine is called time.Sleep(200 * time.Millisecond) - cr.VerifyWasCalledOnce().ExecuteCommand(models.Repo{}, models.Repo{}, models.User{}, 0, nil, vcs.Gitlab) + cr.VerifyWasCalledOnce().ExecuteCommand(models.Repo{}, models.Repo{}, models.User{}, 0, nil) } func TestPost_GithubCommentSuccess(t *testing.T) { @@ -270,14 +269,14 @@ func TestPost_GithubCommentSuccess(t *testing.T) { user := models.User{} cmd := events.Command{} When(p.ParseGithubIssueCommentEvent(matchers.AnyPtrToGithubIssueCommentEvent())).ThenReturn(baseRepo, user, 1, nil) - When(cp.Parse("", vcs.Github)).ThenReturn(events.CommentParseResult{Command: &cmd}) + When(cp.Parse("", models.Github)).ThenReturn(events.CommentParseResult{Command: &cmd}) w := httptest.NewRecorder() e.Post(w, eventsReq) responseContains(t, w, http.StatusOK, "Processing...") // wait for 200ms so goroutine is called time.Sleep(200 * time.Millisecond) - cr.VerifyWasCalledOnce().ExecuteCommand(baseRepo, baseRepo, user, 1, &cmd, vcs.Github) + cr.VerifyWasCalledOnce().ExecuteCommand(baseRepo, baseRepo, user, 1, &cmd) } func TestPost_GithubPullRequestNotClosed(t *testing.T) { @@ -357,7 +356,7 @@ func TestPost_GithubPullRequestErrCleaningPull(t *testing.T) { pull := models.PullRequest{State: models.Closed} When(p.ParseGithubPull(matchers.AnyPtrToGithubPullRequest())).ThenReturn(pull, repo, nil) When(p.ParseGithubRepo(matchers.AnyPtrToGithubRepository())).ThenReturn(repo, nil) - When(c.CleanUpPull(repo, pull, vcs.Github)).ThenReturn(errors.New("cleanup err")) + When(c.CleanUpPull(repo, pull)).ThenReturn(errors.New("cleanup err")) w := httptest.NewRecorder() e.Post(w, eventsReq) responseContains(t, w, http.StatusInternalServerError, "Error cleaning pull request: cleanup err") @@ -372,7 +371,7 @@ func TestPost_GitlabMergeRequestErrCleaningPull(t *testing.T) { repo := models.Repo{} pullRequest := models.PullRequest{State: models.Closed} When(p.ParseGitlabMergeEvent(event)).ThenReturn(pullRequest, repo, nil) - When(c.CleanUpPull(repo, pullRequest, vcs.Gitlab)).ThenReturn(errors.New("err")) + When(c.CleanUpPull(repo, pullRequest)).ThenReturn(errors.New("err")) w := httptest.NewRecorder() e.Post(w, eventsReq) responseContains(t, w, http.StatusInternalServerError, "Error cleaning pull request: err") @@ -389,7 +388,7 @@ func TestPost_GithubPullRequestSuccess(t *testing.T) { pull := models.PullRequest{State: models.Closed} When(p.ParseGithubPull(matchers.AnyPtrToGithubPullRequest())).ThenReturn(pull, repo, nil) When(p.ParseGithubRepo(matchers.AnyPtrToGithubRepository())).ThenReturn(repo, nil) - When(c.CleanUpPull(repo, pull, vcs.Github)).ThenReturn(nil) + When(c.CleanUpPull(repo, pull)).ThenReturn(nil) w := httptest.NewRecorder() e.Post(w, eventsReq) responseContains(t, w, http.StatusOK, "Pull request cleaned successfully") @@ -427,7 +426,7 @@ func setup(t *testing.T) (server.EventsController, *mocks.MockGithubRequestValid CommandRunner: cr, PullCleaner: c, GithubWebHookSecret: secret, - SupportedVCSHosts: []vcs.Host{vcs.Github, vcs.Gitlab}, + SupportedVCSHosts: []models.VCSHostType{models.Github, models.Gitlab}, GitlabWebHookSecret: secret, GitlabRequestParser: gl, RepoWhitelist: &events.RepoWhitelist{ diff --git a/server/server.go b/server/server.go index b6e272aef9..5be4122f68 100644 --- a/server/server.go +++ b/server/server.go @@ -35,6 +35,7 @@ import ( "github.com/runatlantis/atlantis/server/events" "github.com/runatlantis/atlantis/server/events/locking" "github.com/runatlantis/atlantis/server/events/locking/boltdb" + "github.com/runatlantis/atlantis/server/events/models" "github.com/runatlantis/atlantis/server/events/run" "github.com/runatlantis/atlantis/server/events/terraform" "github.com/runatlantis/atlantis/server/events/vcs" @@ -115,11 +116,11 @@ type WebhookConfig struct { // its dependencies an error will be returned. This is like the main() function // for the server CLI command because it injects all the dependencies. func NewServer(userConfig UserConfig, config Config) (*Server, error) { - var supportedVCSHosts []vcs.Host + var supportedVCSHosts []models.VCSHostType var githubClient *vcs.GithubClient var gitlabClient *vcs.GitlabClient if userConfig.GithubUser != "" { - supportedVCSHosts = append(supportedVCSHosts, vcs.Github) + supportedVCSHosts = append(supportedVCSHosts, models.Github) var err error githubClient, err = vcs.NewGithubClient(userConfig.GithubHostname, userConfig.GithubUser, userConfig.GithubToken) if err != nil { @@ -127,7 +128,7 @@ func NewServer(userConfig UserConfig, config Config) (*Server, error) { } } if userConfig.GitlabUser != "" { - supportedVCSHosts = append(supportedVCSHosts, vcs.Gitlab) + supportedVCSHosts = append(supportedVCSHosts, models.Gitlab) gitlabClient = &vcs.GitlabClient{ Client: gitlab.NewClient(nil, userConfig.GitlabToken), }