From aa1bfc0a2798cd92882b52ae908bd930e25383e7 Mon Sep 17 00:00:00 2001 From: Chris Alexander Date: Tue, 12 May 2020 16:40:24 -0500 Subject: [PATCH] Add "plan" to continued statement --- server/events/command_runner.go | 21 ++++++++-------- server/events/command_runner_test.go | 24 +++++++++---------- server/events/pull_closed_executor.go | 2 +- server/events/pull_closed_executor_test.go | 4 ++-- server/events/vcs/azuredevops_client.go | 2 +- server/events/vcs/bitbucketcloud/client.go | 2 +- server/events/vcs/bitbucketserver/client.go | 2 +- server/events/vcs/client.go | 2 +- server/events/vcs/github_client.go | 14 ++++++++--- server/events/vcs/github_client_test.go | 7 ++++-- server/events/vcs/gitlab_client.go | 2 +- server/events/vcs/mocks/mock_client.go | 20 +++++++++------- .../events/vcs/not_configured_vcs_client.go | 2 +- server/events/vcs/proxy.go | 4 ++-- server/events_controller.go | 4 ++-- server/events_controller_e2e_test.go | 2 +- server/events_controller_test.go | 12 +++++----- server/locks_controller.go | 2 +- server/locks_controller_test.go | 6 ++--- 19 files changed, 75 insertions(+), 59 deletions(-) diff --git a/server/events/command_runner.go b/server/events/command_runner.go index 1c4f02505..910885267 100644 --- a/server/events/command_runner.go +++ b/server/events/command_runner.go @@ -111,7 +111,7 @@ type DefaultCommandRunner struct { // RunAutoplanCommand runs plan when a pull request is opened or updated. func (c *DefaultCommandRunner) RunAutoplanCommand(baseRepo models.Repo, headRepo models.Repo, pull models.PullRequest, user models.User) { if opStarted := c.Drainer.StartOp(); !opStarted { - if commentErr := c.VCSClient.CreateComment(baseRepo, pull.Num, ShutdownComment); commentErr != nil { + if commentErr := c.VCSClient.CreateComment(baseRepo, pull.Num, ShutdownComment, models.PlanCommand.String()); commentErr != nil { c.Logger.Log(logging.Error, "unable to comment that Atlantis is shutting down: %s", commentErr) } return @@ -189,7 +189,7 @@ func (c *DefaultCommandRunner) RunAutoplanCommand(baseRepo models.Repo, headRepo // wasteful) call to get the necessary data. func (c *DefaultCommandRunner) RunCommentCommand(baseRepo models.Repo, maybeHeadRepo *models.Repo, maybePull *models.PullRequest, user models.User, pullNum int, cmd *CommentCommand) { if opStarted := c.Drainer.StartOp(); !opStarted { - if commentErr := c.VCSClient.CreateComment(baseRepo, pullNum, ShutdownComment); commentErr != nil { + if commentErr := c.VCSClient.CreateComment(baseRepo, pullNum, ShutdownComment, ""); commentErr != nil { c.Logger.Log(logging.Error, "unable to comment that Atlantis is shutting down: %s", commentErr) } return @@ -201,7 +201,7 @@ func (c *DefaultCommandRunner) RunCommentCommand(baseRepo models.Repo, maybeHead if c.DisableApplyAll && cmd.Name == models.ApplyCommand && !cmd.IsForSpecificProject() { log.Info("ignoring apply command without flags since apply all is disabled") - if err := c.VCSClient.CreateComment(baseRepo, pullNum, applyAllDisabledComment); err != nil { + if err := c.VCSClient.CreateComment(baseRepo, pullNum, applyAllDisabledComment, models.ApplyCommand.String()); err != nil { log.Err("unable to comment on pull request: %s", err) } return @@ -232,7 +232,7 @@ func (c *DefaultCommandRunner) RunCommentCommand(baseRepo models.Repo, maybeHead } if err != nil { log.Err(err.Error()) - if commentErr := c.VCSClient.CreateComment(baseRepo, pullNum, fmt.Sprintf("`Error: %s`", err)); commentErr != nil { + if commentErr := c.VCSClient.CreateComment(baseRepo, pullNum, fmt.Sprintf("`Error: %s`", err), ""); commentErr != nil { log.Err("unable to comment: %s", commentErr) } return @@ -255,7 +255,7 @@ func (c *DefaultCommandRunner) RunCommentCommand(baseRepo models.Repo, maybeHead vcsMessage = "Failed to delete PR locks" log.Err("failed to delete locks by pull %s", err.Error()) } - if commentErr := c.VCSClient.CreateComment(baseRepo, pullNum, vcsMessage); commentErr != nil { + if commentErr := c.VCSClient.CreateComment(baseRepo, pullNum, vcsMessage, models.UnlockCommand.String()); commentErr != nil { log.Err("unable to comment: %s", commentErr) } return @@ -377,7 +377,7 @@ func (c *DefaultCommandRunner) automerge(ctx *CommandContext, pullStatus models. } // Comment that we're automerging the pull request. - if err := c.VCSClient.CreateComment(ctx.BaseRepo, ctx.Pull.Num, automergeComment); err != nil { + if err := c.VCSClient.CreateComment(ctx.BaseRepo, ctx.Pull.Num, automergeComment, models.ApplyCommand.String()); err != nil { ctx.Log.Err("failed to comment about automerge: %s", err) // Commenting isn't required so continue. } @@ -390,7 +390,7 @@ func (c *DefaultCommandRunner) automerge(ctx *CommandContext, pullStatus models. ctx.Log.Err("automerging failed: %s", err) failureComment := fmt.Sprintf("Automerging failed:\n```\n%s\n```", err) - if commentErr := c.VCSClient.CreateComment(ctx.BaseRepo, ctx.Pull.Num, failureComment); commentErr != nil { + if commentErr := c.VCSClient.CreateComment(ctx.BaseRepo, ctx.Pull.Num, failureComment, models.ApplyCommand.String()); commentErr != nil { ctx.Log.Err("failed to comment about automerge failing: %s", err) } } @@ -499,7 +499,7 @@ func (c *DefaultCommandRunner) validateCtxAndComment(ctx *CommandContext) bool { return false } ctx.Log.Info("command was run on a fork pull request which is disallowed") - if err := c.VCSClient.CreateComment(ctx.BaseRepo, ctx.Pull.Num, fmt.Sprintf("Atlantis commands can't be run on fork pull requests. To enable, set --%s or, to disable this message, set --%s", c.AllowForkPRsFlag, c.SilenceForkPRErrorsFlag)); err != nil { + if err := c.VCSClient.CreateComment(ctx.BaseRepo, ctx.Pull.Num, fmt.Sprintf("Atlantis commands can't be run on fork pull requests. To enable, set --%s or, to disable this message, set --%s", c.AllowForkPRsFlag, c.SilenceForkPRErrorsFlag), ""); err != nil { ctx.Log.Err("unable to comment: %s", err) } return false @@ -507,7 +507,7 @@ func (c *DefaultCommandRunner) validateCtxAndComment(ctx *CommandContext) bool { if ctx.Pull.State != models.OpenPullState { ctx.Log.Info("command was run on closed pull request") - if err := c.VCSClient.CreateComment(ctx.BaseRepo, ctx.Pull.Num, "Atlantis commands can't be run on closed pull requests"); err != nil { + if err := c.VCSClient.CreateComment(ctx.BaseRepo, ctx.Pull.Num, "Atlantis commands can't be run on closed pull requests", ""); err != nil { ctx.Log.Err("unable to comment: %s", err) } return false @@ -533,7 +533,7 @@ func (c *DefaultCommandRunner) updatePull(ctx *CommandContext, command PullComma } comment := c.MarkdownRenderer.Render(res, command.CommandName(), ctx.Log.History.String(), command.IsVerbose(), ctx.BaseRepo.VCSHost.Type) - if err := c.VCSClient.CreateComment(ctx.BaseRepo, ctx.Pull.Num, comment); err != nil { + if err := c.VCSClient.CreateComment(ctx.BaseRepo, ctx.Pull.Num, comment, command.CommandName().String()); err != nil { ctx.Log.Err("unable to comment: %s", err) } } @@ -547,6 +547,7 @@ func (c *DefaultCommandRunner) logPanics(baseRepo models.Repo, pullNum int, logg baseRepo, pullNum, fmt.Sprintf("**Error: goroutine panic. This is a bug.**\n```\n%s\n%s```", err, stack), + "", ); commentErr != nil { logger.Err("unable to comment: %s", commentErr) } diff --git a/server/events/command_runner_test.go b/server/events/command_runner_test.go index 280e4f5eb..be5cbc70f 100644 --- a/server/events/command_runner_test.go +++ b/server/events/command_runner_test.go @@ -100,7 +100,7 @@ func TestRunCommentCommand_LogPanics(t *testing.T) { vcsClient := setup(t) When(githubGetter.GetPullRequest(fixtures.GithubRepo, fixtures.Pull.Num)).ThenPanic("panic test - if you're seeing this in a test failure this isn't the failing test") ch.RunCommentCommand(fixtures.GithubRepo, &fixtures.GithubRepo, nil, fixtures.User, 1, &events.CommentCommand{Name: models.PlanCommand}) - _, _, comment := vcsClient.VerifyWasCalledOnce().CreateComment(matchers.AnyModelsRepo(), AnyInt(), AnyString()).GetCapturedArguments() + _, _, comment, _ := vcsClient.VerifyWasCalledOnce().CreateComment(matchers.AnyModelsRepo(), AnyInt(), AnyString(), AnyString()).GetCapturedArguments() Assert(t, strings.Contains(comment, "Error: goroutine panic"), fmt.Sprintf("comment should be about a goroutine panic but was %q", comment)) } @@ -125,7 +125,7 @@ func TestRunCommentCommand_GithubPullErr(t *testing.T) { vcsClient := setup(t) When(githubGetter.GetPullRequest(fixtures.GithubRepo, fixtures.Pull.Num)).ThenReturn(nil, errors.New("err")) ch.RunCommentCommand(fixtures.GithubRepo, &fixtures.GithubRepo, nil, fixtures.User, fixtures.Pull.Num, nil) - vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, fixtures.Pull.Num, "`Error: making pull request API call to GitHub: err`") + vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, fixtures.Pull.Num, "`Error: making pull request API call to GitHub: err`", "") } func TestRunCommentCommand_GitlabMergeRequestErr(t *testing.T) { @@ -133,7 +133,7 @@ func TestRunCommentCommand_GitlabMergeRequestErr(t *testing.T) { vcsClient := setup(t) When(gitlabGetter.GetMergeRequest(fixtures.GitlabRepo.FullName, fixtures.Pull.Num)).ThenReturn(nil, errors.New("err")) ch.RunCommentCommand(fixtures.GitlabRepo, &fixtures.GitlabRepo, nil, fixtures.User, fixtures.Pull.Num, nil) - vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GitlabRepo, fixtures.Pull.Num, "`Error: making merge request API call to GitLab: err`") + vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GitlabRepo, fixtures.Pull.Num, "`Error: making merge request API call to GitLab: err`", "") } func TestRunCommentCommand_GithubPullParseErr(t *testing.T) { @@ -144,7 +144,7 @@ func TestRunCommentCommand_GithubPullParseErr(t *testing.T) { When(eventParsing.ParseGithubPull(&pull)).ThenReturn(fixtures.Pull, fixtures.GithubRepo, fixtures.GitlabRepo, errors.New("err")) ch.RunCommentCommand(fixtures.GithubRepo, &fixtures.GithubRepo, nil, fixtures.User, fixtures.Pull.Num, nil) - vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, fixtures.Pull.Num, "`Error: extracting required fields from comment data: err`") + vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, fixtures.Pull.Num, "`Error: extracting required fields from comment data: err`", "") } func TestRunCommentCommand_ForkPRDisabled(t *testing.T) { @@ -165,7 +165,7 @@ func TestRunCommentCommand_ForkPRDisabled(t *testing.T) { ch.RunCommentCommand(fixtures.GithubRepo, nil, nil, fixtures.User, fixtures.Pull.Num, nil) commentMessage := fmt.Sprintf("Atlantis commands can't be run on fork pull requests. To enable, set --%s or, to disable this message, set --%s", ch.AllowForkPRsFlag, ch.SilenceForkPRErrorsFlag) - vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, modelPull.Num, commentMessage) + vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, modelPull.Num, commentMessage, "") } func TestRunCommentCommand_ForkPRDisabled_SilenceEnabled(t *testing.T) { @@ -183,7 +183,7 @@ func TestRunCommentCommand_ForkPRDisabled_SilenceEnabled(t *testing.T) { When(eventParsing.ParseGithubPull(&pull)).ThenReturn(modelPull, modelPull.BaseRepo, headRepo, nil) ch.RunCommentCommand(fixtures.GithubRepo, nil, nil, fixtures.User, fixtures.Pull.Num, nil) - vcsClient.VerifyWasCalled(Never()).CreateComment(matchers.AnyModelsRepo(), AnyInt(), AnyString()) + vcsClient.VerifyWasCalled(Never()).CreateComment(matchers.AnyModelsRepo(), AnyInt(), AnyString(), AnyString()) } func TestRunCommentCommand_DisableApplyAllDisabled(t *testing.T) { @@ -193,7 +193,7 @@ func TestRunCommentCommand_DisableApplyAllDisabled(t *testing.T) { ch.DisableApplyAll = true modelPull := models.PullRequest{State: models.OpenPullState} ch.RunCommentCommand(fixtures.GithubRepo, nil, nil, fixtures.User, modelPull.Num, &events.CommentCommand{Name: models.ApplyCommand}) - vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, modelPull.Num, "**Error:** Running `atlantis apply` without flags is disabled. You must specify which project to apply via the `-d `, `-w ` or `-p ` flags.") + vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, modelPull.Num, "**Error:** Running `atlantis apply` without flags is disabled. You must specify which project to apply via the `-d `, `-w ` or `-p ` flags.", "apply") } func TestRunCommentCommand_ClosedPull(t *testing.T) { @@ -208,7 +208,7 @@ func TestRunCommentCommand_ClosedPull(t *testing.T) { When(eventParsing.ParseGithubPull(pull)).ThenReturn(modelPull, modelPull.BaseRepo, fixtures.GithubRepo, nil) ch.RunCommentCommand(fixtures.GithubRepo, &fixtures.GithubRepo, nil, fixtures.User, fixtures.Pull.Num, nil) - vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, modelPull.Num, "Atlantis commands can't be run on closed pull requests") + vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, modelPull.Num, "Atlantis commands can't be run on closed pull requests", "") } func TestRunUnlockCommand_VCSComment(t *testing.T) { @@ -226,7 +226,7 @@ func TestRunUnlockCommand_VCSComment(t *testing.T) { ch.RunCommentCommand(fixtures.GithubRepo, &fixtures.GithubRepo, nil, fixtures.User, fixtures.Pull.Num, &events.CommentCommand{Name: models.UnlockCommand}) deleteLockCommand.VerifyWasCalledOnce().DeleteLocksByPull(fixtures.GithubRepo.FullName, fixtures.Pull.Num) - vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, fixtures.Pull.Num, "All Atlantis locks for this PR have been unlocked and plans discarded") + vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, fixtures.Pull.Num, "All Atlantis locks for this PR have been unlocked and plans discarded", "unlock") } func TestRunUnlockCommandFail_VCSComment(t *testing.T) { @@ -244,7 +244,7 @@ func TestRunUnlockCommandFail_VCSComment(t *testing.T) { ch.RunCommentCommand(fixtures.GithubRepo, &fixtures.GithubRepo, nil, fixtures.User, fixtures.Pull.Num, &events.CommentCommand{Name: models.UnlockCommand}) - vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, fixtures.Pull.Num, "Failed to delete PR locks") + vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, fixtures.Pull.Num, "Failed to delete PR locks", "unlock") } // Test that if one plan fails and we are using automerge, that @@ -348,7 +348,7 @@ func TestRunCommentCommand_DrainOngoing(t *testing.T) { vcsClient := setup(t) drainer.ShutdownBlocking() ch.RunCommentCommand(fixtures.GithubRepo, &fixtures.GithubRepo, nil, fixtures.User, fixtures.Pull.Num, nil) - vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, fixtures.Pull.Num, "Atlantis server is shutting down, please try again later.") + vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, fixtures.Pull.Num, "Atlantis server is shutting down, please try again later.", "") } func TestRunCommentCommand_DrainNotOngoing(t *testing.T) { @@ -365,7 +365,7 @@ func TestRunAutoplanCommand_DrainOngoing(t *testing.T) { vcsClient := setup(t) drainer.ShutdownBlocking() ch.RunAutoplanCommand(fixtures.GithubRepo, fixtures.GithubRepo, fixtures.Pull, fixtures.User) - vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, fixtures.Pull.Num, "Atlantis server is shutting down, please try again later.") + vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, fixtures.Pull.Num, "Atlantis server is shutting down, please try again later.", "plan") } func TestRunAutoplanCommand_DrainNotOngoing(t *testing.T) { diff --git a/server/events/pull_closed_executor.go b/server/events/pull_closed_executor.go index b8a5a5219..94dc4743f 100644 --- a/server/events/pull_closed_executor.go +++ b/server/events/pull_closed_executor.go @@ -88,7 +88,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()) + 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 6504adb62..b84a1f825 100644 --- a/server/events/pull_closed_executor_test.go +++ b/server/events/pull_closed_executor_test.go @@ -77,7 +77,7 @@ func TestCleanUpPullNoLocks(t *testing.T) { 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()) + cp.VerifyWasCalled(Never()).CreateComment(matchers.AnyModelsRepo(), AnyInt(), AnyString(), AnyString()) } func TestCleanUpPullComments(t *testing.T) { @@ -164,7 +164,7 @@ func TestCleanUpPullComments(t *testing.T) { 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()).GetCapturedArguments() + _, _, comment, _ := cp.VerifyWasCalledOnce().CreateComment(matchers.AnyModelsRepo(), AnyInt(), AnyString(), 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/azuredevops_client.go b/server/events/vcs/azuredevops_client.go index 1e75f8f9c..26a69a5e7 100644 --- a/server/events/vcs/azuredevops_client.go +++ b/server/events/vcs/azuredevops_client.go @@ -89,7 +89,7 @@ func (g *AzureDevopsClient) GetModifiedFiles(repo models.Repo, pull models.PullR // // If comment length is greater than the max comment length we split into // multiple comments. -func (g *AzureDevopsClient) CreateComment(repo models.Repo, pullNum int, comment string) error { +func (g *AzureDevopsClient) CreateComment(repo models.Repo, pullNum int, comment string, command string) error { sepEnd := "\n```\n" + "\n
\n\n**Warning**: Output length greater than max comment size. Continued in next comment." sepStart := "Continued from previous comment.\n
Show Output\n\n" + diff --git a/server/events/vcs/bitbucketcloud/client.go b/server/events/vcs/bitbucketcloud/client.go index b8bcb8d16..88d631294 100644 --- a/server/events/vcs/bitbucketcloud/client.go +++ b/server/events/vcs/bitbucketcloud/client.go @@ -85,7 +85,7 @@ func (b *Client) GetModifiedFiles(repo models.Repo, pull models.PullRequest) ([] } // CreateComment creates a comment on the merge request. -func (b *Client) CreateComment(repo models.Repo, pullNum int, comment string) error { +func (b *Client) CreateComment(repo models.Repo, pullNum int, comment string, command string) error { // NOTE: I tried to find the maximum size of a comment for bitbucket.org but // I got up to 200k chars without issue so for now I'm not going to bother // to detect this. diff --git a/server/events/vcs/bitbucketserver/client.go b/server/events/vcs/bitbucketserver/client.go index 10653439e..0c9962737 100644 --- a/server/events/vcs/bitbucketserver/client.go +++ b/server/events/vcs/bitbucketserver/client.go @@ -129,7 +129,7 @@ func (b *Client) GetProjectKey(repoName string, cloneURL string) (string, error) // CreateComment creates a comment on the merge request. It will write multiple // comments if a single comment is too long. -func (b *Client) CreateComment(repo models.Repo, pullNum int, comment string) error { +func (b *Client) CreateComment(repo models.Repo, pullNum int, comment string, command string) error { sepEnd := "\n```\n**Warning**: Output length greater than max comment size. Continued in next comment." sepStart := "Continued from previous comment.\n```diff\n" comments := common.SplitComment(comment, maxCommentLength, sepEnd, sepStart) diff --git a/server/events/vcs/client.go b/server/events/vcs/client.go index 6cd35b39a..5afb69f7b 100644 --- a/server/events/vcs/client.go +++ b/server/events/vcs/client.go @@ -24,7 +24,7 @@ type Client interface { // GetModifiedFiles returns the names of files that were modified in the merge request // relative to the repo root, e.g. parent/child/file.txt. GetModifiedFiles(repo models.Repo, pull models.PullRequest) ([]string, error) - CreateComment(repo models.Repo, pullNum int, comment string) error + CreateComment(repo models.Repo, pullNum int, comment string, command string) error HidePrevPlanComments(repo models.Repo, pullNum int) error PullIsApproved(repo models.Repo, pull models.PullRequest) (bool, error) PullIsMergeable(repo models.Repo, pull models.PullRequest) (bool, error) diff --git a/server/events/vcs/github_client.go b/server/events/vcs/github_client.go index 9ca0a066a..c912cb395 100644 --- a/server/events/vcs/github_client.go +++ b/server/events/vcs/github_client.go @@ -134,11 +134,19 @@ func (g *GithubClient) GetModifiedFiles(repo models.Repo, pull models.PullReques // CreateComment creates a comment on the pull request. // If comment length is greater than the max comment length we split into // multiple comments. -func (g *GithubClient) CreateComment(repo models.Repo, pullNum int, comment string) error { +func (g *GithubClient) CreateComment(repo models.Repo, pullNum int, comment string, command string) error { + var sepStart string + sepEnd := "\n```\n
" + "\n
\n\n**Warning**: Output length greater than max comment size. Continued in next comment." - sepStart := "Continued from previous comment.\n
Show Output\n\n" + - "```diff\n" + + if command != "" { + sepStart = "Continued from previous comment.\n
Show Output\n\n" + + "```diff\n" + } else { + sepStart = fmt.Sprintf("Continued %s output from previous comment.\n
Show Output\n\n", command) + + "```diff\n" + } comments := common.SplitComment(comment, maxCommentLength, sepEnd, sepStart) for _, c := range comments { diff --git a/server/events/vcs/github_client_test.go b/server/events/vcs/github_client_test.go index ad830c3af..4d6fbf8f7 100644 --- a/server/events/vcs/github_client_test.go +++ b/server/events/vcs/github_client_test.go @@ -244,7 +244,9 @@ func TestGithubClient_HideOldComments(t *testing.T) { {"node_id": "4", "body": "asdasdasd\nasdasdasd", "user": {"login": "user"}}, {"node_id": "5", "body": "asd\nplan\nasd", "user": {"login": "user"}}, {"node_id": "6", "body": "asd plan\nasd", "user": {"login": "user"}}, - {"node_id": "7", "body": "asdasdasd", "user": {"login": "user"}} + {"node_id": "7", "body": "asdasdasd", "user": {"login": "user"}}, + {"node_id": "8", "body": "asd plan\nasd", "user": {"login": "user"}}, + {"node_id": "9", "body": "Continued Plan from previous comment\nasd", "user": {"login": "user"}} ]` minimizeResp := "{}" type graphQLCall struct { @@ -313,8 +315,9 @@ func TestGithubClient_HideOldComments(t *testing.T) { 123, ) Ok(t, err) - Equals(t, 1, len(gotMinimizeCalls)) + Equals(t, 3, len(gotMinimizeCalls)) Equals(t, "6", gotMinimizeCalls[0].Variables.Input.SubjectID) + Equals(t, "9", gotMinimizeCalls[2].Variables.Input.SubjectID) Equals(t, githubv4.ReportedContentClassifiersOutdated, gotMinimizeCalls[0].Variables.Input.Classifier) } diff --git a/server/events/vcs/gitlab_client.go b/server/events/vcs/gitlab_client.go index 076a1a60a..6e1933d61 100644 --- a/server/events/vcs/gitlab_client.go +++ b/server/events/vcs/gitlab_client.go @@ -134,7 +134,7 @@ func (g *GitlabClient) GetModifiedFiles(repo models.Repo, pull models.PullReques } // CreateComment creates a comment on the merge request. -func (g *GitlabClient) CreateComment(repo models.Repo, pullNum int, comment string) error { +func (g *GitlabClient) CreateComment(repo models.Repo, pullNum int, comment string, command string) error { _, _, err := g.Client.Notes.CreateMergeRequestNote(repo.FullName, pullNum, &gitlab.CreateMergeRequestNoteOptions{Body: gitlab.String(comment)}) return err } diff --git a/server/events/vcs/mocks/mock_client.go b/server/events/vcs/mocks/mock_client.go index 62e022f1f..4a0e9a669 100644 --- a/server/events/vcs/mocks/mock_client.go +++ b/server/events/vcs/mocks/mock_client.go @@ -44,11 +44,11 @@ func (mock *MockClient) GetModifiedFiles(repo models.Repo, pull models.PullReque return ret0, ret1 } -func (mock *MockClient) CreateComment(repo models.Repo, pullNum int, comment string) error { +func (mock *MockClient) CreateComment(repo models.Repo, pullNum int, comment string, command string) error { if mock == nil { panic("mock must not be nil. Use myMock := NewMockClient().") } - params := []pegomock.Param{repo, pullNum, comment} + params := []pegomock.Param{repo, pullNum, comment, command} result := pegomock.GetGenericMockFrom(mock).Invoke("CreateComment", params, []reflect.Type{reflect.TypeOf((*error)(nil)).Elem()}) var ret0 error if len(result) != 0 { @@ -229,8 +229,8 @@ func (c *MockClient_GetModifiedFiles_OngoingVerification) GetAllCapturedArgument return } -func (verifier *VerifierMockClient) CreateComment(repo models.Repo, pullNum int, comment string) *MockClient_CreateComment_OngoingVerification { - params := []pegomock.Param{repo, pullNum, comment} +func (verifier *VerifierMockClient) CreateComment(repo models.Repo, pullNum int, comment string, command string) *MockClient_CreateComment_OngoingVerification { + params := []pegomock.Param{repo, pullNum, comment, command} methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "CreateComment", params, verifier.timeout) return &MockClient_CreateComment_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } @@ -240,12 +240,12 @@ type MockClient_CreateComment_OngoingVerification struct { methodInvocations []pegomock.MethodInvocation } -func (c *MockClient_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 *MockClient_CreateComment_OngoingVerification) GetCapturedArguments() (models.Repo, int, string, string) { + repo, pullNum, comment, command := c.GetAllCapturedArguments() + return repo[len(repo)-1], pullNum[len(pullNum)-1], comment[len(comment)-1], command[len(command)-1] } -func (c *MockClient_CreateComment_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []int, _param2 []string) { +func (c *MockClient_CreateComment_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []int, _param2 []string, _param3 []string) { params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) if len(params) > 0 { _param0 = make([]models.Repo, len(c.methodInvocations)) @@ -260,6 +260,10 @@ func (c *MockClient_CreateComment_OngoingVerification) GetAllCapturedArguments() for u, param := range params[2] { _param2[u] = param.(string) } + _param3 = make([]string, len(c.methodInvocations)) + for u, param := range params[3] { + _param3[u] = param.(string) + } } return } diff --git a/server/events/vcs/not_configured_vcs_client.go b/server/events/vcs/not_configured_vcs_client.go index 6a5b3d747..c8fe20ed9 100644 --- a/server/events/vcs/not_configured_vcs_client.go +++ b/server/events/vcs/not_configured_vcs_client.go @@ -29,7 +29,7 @@ type NotConfiguredVCSClient struct { func (a *NotConfiguredVCSClient) GetModifiedFiles(repo models.Repo, pull models.PullRequest) ([]string, error) { return nil, a.err() } -func (a *NotConfiguredVCSClient) CreateComment(repo models.Repo, pullNum int, comment string) error { +func (a *NotConfiguredVCSClient) CreateComment(repo models.Repo, pullNum int, comment string, command string) error { return a.err() } func (a *NotConfiguredVCSClient) HidePrevPlanComments(repo models.Repo, pullNum int) error { diff --git a/server/events/vcs/proxy.go b/server/events/vcs/proxy.go index ed25c4d60..6511bf2d9 100644 --- a/server/events/vcs/proxy.go +++ b/server/events/vcs/proxy.go @@ -56,8 +56,8 @@ func (d *ClientProxy) GetModifiedFiles(repo models.Repo, pull models.PullRequest return d.clients[repo.VCSHost.Type].GetModifiedFiles(repo, pull) } -func (d *ClientProxy) CreateComment(repo models.Repo, pullNum int, comment string) error { - return d.clients[repo.VCSHost.Type].CreateComment(repo, pullNum, comment) +func (d *ClientProxy) CreateComment(repo models.Repo, pullNum int, comment string, command string) error { + return d.clients[repo.VCSHost.Type].CreateComment(repo, pullNum, comment, command) } func (d *ClientProxy) HidePrevPlanComments(repo models.Repo, pullNum int) error { diff --git a/server/events_controller.go b/server/events_controller.go index 96b17d3e7..983d42311 100644 --- a/server/events_controller.go +++ b/server/events_controller.go @@ -428,7 +428,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); 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") @@ -548,7 +548,7 @@ func (e *EventsController) commentNotWhitelisted(baseRepo models.Repo, pullNum i } errMsg := "```\nError: This repo is not whitelisted for Atlantis.\n```" - if err := e.VCSClient.CreateComment(baseRepo, pullNum, errMsg); err != nil { + if err := e.VCSClient.CreateComment(baseRepo, pullNum, errMsg, ""); err != nil { e.Logger.Err("unable to comment on pull request: %s", err) } } diff --git a/server/events_controller_e2e_test.go b/server/events_controller_e2e_test.go index f19c02dc7..d37f816d2 100644 --- a/server/events_controller_e2e_test.go +++ b/server/events_controller_e2e_test.go @@ -379,7 +379,7 @@ func TestGitHubWorkflow(t *testing.T) { expNumReplies++ } - _, _, actReplies := vcsClient.VerifyWasCalled(Times(expNumReplies)).CreateComment(AnyRepo(), AnyInt(), AnyString()).GetAllCapturedArguments() + _, _, actReplies, _ := vcsClient.VerifyWasCalled(Times(expNumReplies)).CreateComment(AnyRepo(), AnyInt(), AnyString(), AnyString()).GetAllCapturedArguments() Assert(t, len(c.ExpReplies) == len(actReplies), "missing expected replies, got %d but expected %d", len(actReplies), len(c.ExpReplies)) for i, expReply := range c.ExpReplies { assertCommentEquals(t, expReply, actReplies[i], c.RepoDir, c.ExpParallel) diff --git a/server/events_controller_test.go b/server/events_controller_test.go index a3dd538ad..f538ceee7 100644 --- a/server/events_controller_test.go +++ b/server/events_controller_test.go @@ -207,7 +207,7 @@ func TestPost_GitlabCommentNotWhitelisted(t *testing.T) { exp := "Repo not whitelisted" Assert(t, strings.Contains(string(body), exp), "exp %q to be contained in %q", exp, string(body)) 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```") + vcsClient.VerifyWasCalledOnce().CreateComment(expRepo, 1, "```\nError: This repo is not whitelisted for Atlantis.\n```", "") } func TestPost_GitlabCommentNotWhitelistedWithSilenceErrors(t *testing.T) { @@ -235,7 +235,7 @@ func TestPost_GitlabCommentNotWhitelistedWithSilenceErrors(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)) - vcsClient.VerifyWasCalled(Never()).CreateComment(matchers.AnyModelsRepo(), AnyInt(), AnyString()) + vcsClient.VerifyWasCalled(Never()).CreateComment(matchers.AnyModelsRepo(), AnyInt(), AnyString(), AnyString()) } @@ -265,7 +265,7 @@ func TestPost_GithubCommentNotWhitelisted(t *testing.T) { exp := "Repo not whitelisted" Assert(t, strings.Contains(string(body), exp), "exp %q to be contained in %q", exp, string(body)) 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```") + vcsClient.VerifyWasCalledOnce().CreateComment(expRepo, 2, "```\nError: This repo is not whitelisted for Atlantis.\n```", "") } func TestPost_GithubCommentNotWhitelistedWithSilenceErrors(t *testing.T) { @@ -294,7 +294,7 @@ func TestPost_GithubCommentNotWhitelistedWithSilenceErrors(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)) - vcsClient.VerifyWasCalled(Never()).CreateComment(matchers.AnyModelsRepo(), AnyInt(), AnyString()) + vcsClient.VerifyWasCalled(Never()).CreateComment(matchers.AnyModelsRepo(), AnyInt(), AnyString(), AnyString()) } func TestPost_GitlabCommentResponse(t *testing.T) { @@ -306,7 +306,7 @@ func TestPost_GitlabCommentResponse(t *testing.T) { When(cp.Parse("", models.Gitlab)).ThenReturn(events.CommentParseResult{CommentResponse: "a comment"}) w := httptest.NewRecorder() e.Post(w, req) - vcsClient.VerifyWasCalledOnce().CreateComment(models.Repo{}, 0, "a comment") + vcsClient.VerifyWasCalledOnce().CreateComment(models.Repo{}, 0, "a comment", "") responseContains(t, w, http.StatusOK, "Commenting back on pull request") } @@ -324,7 +324,7 @@ func TestPost_GithubCommentResponse(t *testing.T) { w := httptest.NewRecorder() e.Post(w, req) - vcsClient.VerifyWasCalledOnce().CreateComment(baseRepo, 1, "a comment") + vcsClient.VerifyWasCalledOnce().CreateComment(baseRepo, 1, "a comment", "") responseContains(t, w, http.StatusOK, "Commenting back on pull request") } diff --git a/server/locks_controller.go b/server/locks_controller.go index 31ae5deb3..60151b16d 100644 --- a/server/locks_controller.go +++ b/server/locks_controller.go @@ -118,7 +118,7 @@ func (l *LocksController) DeleteLock(w http.ResponseWriter, r *http.Request) { // Once the lock has been deleted, comment back on the pull request. comment := fmt.Sprintf("**Warning**: The plan for dir: `%s` workspace: `%s` was **discarded** via the Atlantis UI.\n\n"+ "To `apply` this plan you must run `plan` again.", lock.Project.Path, lock.Workspace) - if err = l.VCSClient.CreateComment(lock.Pull.BaseRepo, lock.Pull.Num, comment); err != nil { + if err = l.VCSClient.CreateComment(lock.Pull.BaseRepo, lock.Pull.Num, comment, ""); err != nil { l.Logger.Warn("failed commenting on pull request: %s", err) } } else { diff --git a/server/locks_controller_test.go b/server/locks_controller_test.go index 77fff183e..42487afbf 100644 --- a/server/locks_controller_test.go +++ b/server/locks_controller_test.go @@ -189,7 +189,7 @@ func TestDeleteLock_OldFormat(t *testing.T) { w := httptest.NewRecorder() lc.DeleteLock(w, req) responseContains(t, w, http.StatusOK, "Deleted lock id \"id\"") - cp.VerifyWasCalled(Never()).CreateComment(AnyRepo(), AnyInt(), AnyString()) + cp.VerifyWasCalled(Never()).CreateComment(AnyRepo(), AnyInt(), AnyString(), AnyString()) } func TestDeleteLock_UpdateProjectStatus(t *testing.T) { @@ -269,7 +269,7 @@ func TestDeleteLock_CommentFailed(t *testing.T) { cp := vcsmocks.NewMockClient() workingDir := mocks2.NewMockWorkingDir() workingDirLocker := events.NewDefaultWorkingDirLocker() - When(cp.CreateComment(AnyRepo(), AnyInt(), AnyString())).ThenReturn(errors.New("err")) + When(cp.CreateComment(AnyRepo(), AnyInt(), AnyString(), AnyString())).ThenReturn(errors.New("err")) tmp, cleanup := TempDir(t) defer cleanup() db, err := db.New(tmp) @@ -326,5 +326,5 @@ func TestDeleteLock_CommentSuccess(t *testing.T) { responseContains(t, w, http.StatusOK, "Deleted lock id \"id\"") cp.VerifyWasCalled(Once()).CreateComment(pull.BaseRepo, pull.Num, "**Warning**: The plan for dir: `path` workspace: `workspace` was **discarded** via the Atlantis UI.\n\n"+ - "To `apply` this plan you must run `plan` again.") + "To `apply` this plan you must run `plan` again.", "") }