mirror of
https://git.vectorsigma.ru/public/atlantis.git
synced 2026-07-28 19:38:24 +00:00
Signed-off-by: RB <7775707+nitrocode@users.noreply.github.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: RB <7775707+nitrocode@users.noreply.github.com>
1031 lines
41 KiB
Go
1031 lines
41 KiB
Go
// Copyright 2017 HootSuite Media Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the License);
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an AS IS BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
// Modified hereafter by contributors to runatlantis/atlantis.
|
|
|
|
package events_test
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/drmaxgit/go-azuredevops/azuredevops"
|
|
"github.com/google/go-github/v71/github"
|
|
. "github.com/petergtz/pegomock/v4"
|
|
events_controllers "github.com/runatlantis/atlantis/server/controllers/events"
|
|
"github.com/runatlantis/atlantis/server/controllers/events/mocks"
|
|
"github.com/runatlantis/atlantis/server/events"
|
|
"github.com/runatlantis/atlantis/server/events/command"
|
|
emocks "github.com/runatlantis/atlantis/server/events/mocks"
|
|
"github.com/runatlantis/atlantis/server/events/models"
|
|
vcsmocks "github.com/runatlantis/atlantis/server/events/vcs/mocks"
|
|
"github.com/runatlantis/atlantis/server/logging"
|
|
"github.com/runatlantis/atlantis/server/metrics"
|
|
. "github.com/runatlantis/atlantis/testing"
|
|
gitlab "gitlab.com/gitlab-org/api/client-go"
|
|
)
|
|
|
|
const githubHeader = "X-Github-Event"
|
|
const giteaHeader = "X-Gitea-Event"
|
|
const gitlabHeader = "X-Gitlab-Event"
|
|
const azuredevopsHeader = "Request-Id"
|
|
|
|
var user = []byte("user")
|
|
var secret = []byte("secret")
|
|
|
|
func TestPost_NotGithubOrGitlab(t *testing.T) {
|
|
t.Log("when the request is not for gitlab or github a 400 is returned")
|
|
e, _, _, _, _, _, _, _, _ := setup(t)
|
|
w := httptest.NewRecorder()
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusBadRequest, "Ignoring request")
|
|
}
|
|
|
|
func TestPost_UnsupportedVCSGithub(t *testing.T) {
|
|
t.Log("when the request is for an unsupported vcs a 400 is returned")
|
|
e, _, _, _, _, _, _, _, _ := setup(t)
|
|
e.SupportedVCSHosts = nil
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(githubHeader, "value")
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusBadRequest, "Ignoring request since not configured to support GitHub")
|
|
}
|
|
|
|
func TestPost_UnsupportedVCSGitea(t *testing.T) {
|
|
t.Log("when the request is for an unsupported vcs a 400 is returned")
|
|
e, _, _, _, _, _, _, _, _ := setup(t)
|
|
e.SupportedVCSHosts = nil
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(giteaHeader, "value")
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusBadRequest, "Ignoring request since not configured to support Gitea")
|
|
}
|
|
|
|
func TestPost_UnsupportedVCSGitlab(t *testing.T) {
|
|
t.Log("when the request is for an unsupported vcs a 400 is returned")
|
|
e, _, _, _, _, _, _, _, _ := setup(t)
|
|
e.SupportedVCSHosts = nil
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(gitlabHeader, "value")
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusBadRequest, "Ignoring request since not configured to support GitLab")
|
|
}
|
|
|
|
func TestPost_InvalidGithubSecret(t *testing.T) {
|
|
t.Log("when the github payload can't be validated a 400 is returned")
|
|
e, v, _, _, _, _, _, _, _ := setup(t)
|
|
w := httptest.NewRecorder()
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(githubHeader, "value")
|
|
When(v.Validate(req, secret)).ThenReturn(nil, errors.New("err"))
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusBadRequest, "err")
|
|
}
|
|
|
|
func TestPost_InvalidGiteaSecret(t *testing.T) {
|
|
t.Log("when the gitea payload can't be validated a 400 is returned")
|
|
e, v, _, _, _, _, _, _, _ := setup(t)
|
|
w := httptest.NewRecorder()
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(giteaHeader, "value")
|
|
When(v.Validate(req, secret)).ThenReturn(nil, errors.New("err"))
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusBadRequest, "request did not pass validation")
|
|
}
|
|
|
|
func TestPost_InvalidGitlabSecret(t *testing.T) {
|
|
t.Log("when the gitlab payload can't be validated a 400 is returned")
|
|
e, _, gl, _, _, _, _, _, _ := setup(t)
|
|
w := httptest.NewRecorder()
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(gitlabHeader, "value")
|
|
When(gl.ParseAndValidate(req, secret)).ThenReturn(nil, errors.New("err"))
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusBadRequest, "err")
|
|
}
|
|
|
|
func TestPost_UnsupportedGithubEvent(t *testing.T) {
|
|
t.Log("when the event type is an unsupported github event we ignore it")
|
|
e, v, _, _, _, _, _, _, _ := setup(t)
|
|
w := httptest.NewRecorder()
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(githubHeader, "value")
|
|
When(v.Validate(req, nil)).ThenReturn([]byte(`{"not an event": ""}`), nil)
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusOK, "Ignoring unsupported event")
|
|
}
|
|
|
|
func TestPost_UnsupportedGiteaEvent(t *testing.T) {
|
|
t.Log("when the event type is an unsupported gitea event we ignore it")
|
|
e, v, _, _, _, _, _, _, _ := setup(t)
|
|
w := httptest.NewRecorder()
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(giteaHeader, "value")
|
|
e.GiteaWebhookSecret = nil
|
|
When(v.Validate(req, nil)).ThenReturn([]byte(`{"not an event": ""}`), nil)
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusOK, "Ignoring unsupported Gitea event")
|
|
}
|
|
|
|
func TestPost_UnsupportedGitlabEvent(t *testing.T) {
|
|
t.Log("when the event type is an unsupported gitlab event we ignore it")
|
|
e, _, gl, _, _, _, _, _, _ := setup(t)
|
|
w := httptest.NewRecorder()
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(gitlabHeader, "value")
|
|
When(gl.ParseAndValidate(req, secret)).ThenReturn([]byte(`{"not an event": ""}`), nil)
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusOK, "Ignoring unsupported event")
|
|
}
|
|
|
|
// Test that if the comment comes from a commit rather than a merge request,
|
|
// we give an error and ignore it.
|
|
func TestPost_GitlabCommentOnCommit(t *testing.T) {
|
|
e, _, gl, _, _, _, _, _, _ := setup(t)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
w := httptest.NewRecorder()
|
|
req.Header.Set(gitlabHeader, "value")
|
|
When(gl.ParseAndValidate(req, secret)).ThenReturn(gitlab.CommitCommentEvent{}, nil)
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusOK, "Ignoring comment on commit event")
|
|
}
|
|
|
|
func TestPost_GithubCommentNotCreated(t *testing.T) {
|
|
t.Log("when the event is a github comment but it's not a created event we ignore it")
|
|
e, v, _, _, _, _, _, _, _ := setup(t)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(githubHeader, "issue_comment")
|
|
// comment action is deleted, not created
|
|
event := `{"action": "deleted"}`
|
|
When(v.Validate(req, secret)).ThenReturn([]byte(event), nil)
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusOK, "Ignoring comment event since action was not created")
|
|
}
|
|
|
|
func TestPost_GithubInvalidComment(t *testing.T) {
|
|
t.Log("when the event is a github comment without all expected data we return a 400")
|
|
e, v, _, _, p, _, _, _, _ := setup(t)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(githubHeader, "issue_comment")
|
|
event := `{"action": "created"}`
|
|
When(v.Validate(req, secret)).ThenReturn([]byte(event), nil)
|
|
When(p.ParseGithubIssueCommentEvent(Any[logging.SimpleLogging](), Any[*github.IssueCommentEvent]())).ThenReturn(models.Repo{}, models.User{}, 1, errors.New("err"))
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusBadRequest, "Failed parsing event")
|
|
}
|
|
|
|
func TestPost_GitlabCommentInvalidCommand(t *testing.T) {
|
|
t.Log("when the event is a gitlab comment with an invalid command we ignore it")
|
|
e, _, gl, _, _, _, _, _, cp := setup(t)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(gitlabHeader, "value")
|
|
When(gl.ParseAndValidate(req, secret)).ThenReturn(gitlab.MergeCommentEvent{}, nil)
|
|
When(cp.Parse("", models.Gitlab)).ThenReturn(events.CommentParseResult{Ignore: true})
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusOK, "Ignoring non-command comment: \"\"")
|
|
}
|
|
|
|
func TestPost_GithubCommentInvalidCommand(t *testing.T) {
|
|
t.Log("when the event is a github comment with an invalid command we ignore it")
|
|
e, v, _, _, p, _, _, vcsClient, cp := setup(t)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(githubHeader, "issue_comment")
|
|
event := `{"action": "created"}`
|
|
When(v.Validate(req, secret)).ThenReturn([]byte(event), nil)
|
|
When(p.ParseGithubIssueCommentEvent(Any[logging.SimpleLogging](), Any[*github.IssueCommentEvent]())).ThenReturn(models.Repo{}, models.User{}, 1, nil)
|
|
When(cp.Parse("", models.Github)).ThenReturn(events.CommentParseResult{Ignore: true})
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusOK, "Ignoring non-command comment: \"\"")
|
|
vcsClient.VerifyWasCalled(Never()).ReactToComment(Any[logging.SimpleLogging](), Eq(models.Repo{}), Eq(1), Eq(int64(1)), Eq("eyes"))
|
|
}
|
|
|
|
func TestPost_GitlabCommentNotAllowlisted(t *testing.T) {
|
|
t.Log("when the event is a gitlab comment from a repo that isn't allowlisted we comment with an error")
|
|
RegisterMockTestingT(t)
|
|
vcsClient := vcsmocks.NewMockClient()
|
|
logger := logging.NewNoopLogger(t)
|
|
scope, _, _ := metrics.NewLoggingScope(logger, "null")
|
|
e := events_controllers.VCSEventsController{
|
|
Logger: logger,
|
|
Scope: scope,
|
|
CommentParser: &events.CommentParser{ExecutableName: "atlantis"},
|
|
GitlabRequestParserValidator: &events_controllers.DefaultGitlabRequestParserValidator{},
|
|
Parser: &events.EventParser{},
|
|
SupportedVCSHosts: []models.VCSHostType{models.Gitlab},
|
|
RepoAllowlistChecker: &events.RepoAllowlistChecker{},
|
|
VCSClient: vcsClient,
|
|
}
|
|
requestJSON, err := os.ReadFile(filepath.Join("testdata", "gitlabMergeCommentEvent_notAllowlisted.json"))
|
|
Ok(t, err)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(requestJSON))
|
|
req.Header.Set(gitlabHeader, "Note Hook")
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
|
|
resp := w.Result()
|
|
defer resp.Body.Close()
|
|
Equals(t, http.StatusForbidden, resp.StatusCode)
|
|
body, _ := io.ReadAll(resp.Body)
|
|
exp := "Repo not allowlisted"
|
|
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(
|
|
Any[logging.SimpleLogging](), Eq(expRepo), Eq(1), Eq("```\nError: This repo is not allowlisted for Atlantis.\n```"), Eq(""))
|
|
}
|
|
|
|
func TestPost_GitlabCommentNotAllowlistedWithSilenceErrors(t *testing.T) {
|
|
t.Log("when the event is a gitlab comment from a repo that isn't allowlisted and we are silencing errors, do not comment with an error")
|
|
RegisterMockTestingT(t)
|
|
vcsClient := vcsmocks.NewMockClient()
|
|
logger := logging.NewNoopLogger(t)
|
|
scope, _, _ := metrics.NewLoggingScope(logger, "null")
|
|
e := events_controllers.VCSEventsController{
|
|
Logger: logger,
|
|
Scope: scope,
|
|
CommentParser: &events.CommentParser{ExecutableName: "atlantis"},
|
|
GitlabRequestParserValidator: &events_controllers.DefaultGitlabRequestParserValidator{},
|
|
Parser: &events.EventParser{},
|
|
SupportedVCSHosts: []models.VCSHostType{models.Gitlab},
|
|
RepoAllowlistChecker: &events.RepoAllowlistChecker{},
|
|
VCSClient: vcsClient,
|
|
SilenceAllowlistErrors: true,
|
|
}
|
|
requestJSON, err := os.ReadFile(filepath.Join("testdata", "gitlabMergeCommentEvent_notAllowlisted.json"))
|
|
Ok(t, err)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(requestJSON))
|
|
req.Header.Set(gitlabHeader, "Note Hook")
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
|
|
resp := w.Result()
|
|
defer resp.Body.Close()
|
|
Equals(t, http.StatusForbidden, resp.StatusCode)
|
|
body, _ := io.ReadAll(resp.Body)
|
|
exp := "Repo not allowlisted"
|
|
Assert(t, strings.Contains(string(body), exp), "exp %q to be contained in %q", exp, string(body))
|
|
vcsClient.VerifyWasCalled(Never()).CreateComment(Any[logging.SimpleLogging](), Any[models.Repo](), Any[int](), Any[string](), Any[string]())
|
|
|
|
}
|
|
|
|
func TestPost_GithubCommentNotAllowlisted(t *testing.T) {
|
|
t.Log("when the event is a github comment from a repo that isn't allowlisted we comment with an error")
|
|
RegisterMockTestingT(t)
|
|
vcsClient := vcsmocks.NewMockClient()
|
|
logger := logging.NewNoopLogger(t)
|
|
scope, _, _ := metrics.NewLoggingScope(logger, "null")
|
|
e := events_controllers.VCSEventsController{
|
|
Logger: logger,
|
|
Scope: scope,
|
|
GithubRequestValidator: &events_controllers.DefaultGithubRequestValidator{},
|
|
CommentParser: &events.CommentParser{ExecutableName: "atlantis"},
|
|
Parser: &events.EventParser{},
|
|
SupportedVCSHosts: []models.VCSHostType{models.Github},
|
|
RepoAllowlistChecker: &events.RepoAllowlistChecker{},
|
|
VCSClient: vcsClient,
|
|
}
|
|
requestJSON, err := os.ReadFile(filepath.Join("testdata", "githubIssueCommentEvent_notAllowlisted.json"))
|
|
Ok(t, err)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(requestJSON))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.Header.Set(githubHeader, "issue_comment")
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
|
|
resp := w.Result()
|
|
defer resp.Body.Close()
|
|
Equals(t, http.StatusForbidden, resp.StatusCode)
|
|
body, _ := io.ReadAll(resp.Body)
|
|
exp := "Repo not allowlisted"
|
|
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(
|
|
Any[logging.SimpleLogging](), Eq(expRepo), Eq(2), Eq("```\nError: This repo is not allowlisted for Atlantis.\n```"), Eq(""))
|
|
}
|
|
|
|
func TestPost_GithubCommentNotAllowlistedWithSilenceErrors(t *testing.T) {
|
|
t.Log("when the event is a github comment from a repo that isn't allowlisted and we are silencing errors, do not comment with an error")
|
|
RegisterMockTestingT(t)
|
|
vcsClient := vcsmocks.NewMockClient()
|
|
logger := logging.NewNoopLogger(t)
|
|
scope, _, _ := metrics.NewLoggingScope(logger, "null")
|
|
e := events_controllers.VCSEventsController{
|
|
Logger: logger,
|
|
Scope: scope,
|
|
GithubRequestValidator: &events_controllers.DefaultGithubRequestValidator{},
|
|
CommentParser: &events.CommentParser{ExecutableName: "atlantis"},
|
|
Parser: &events.EventParser{},
|
|
SupportedVCSHosts: []models.VCSHostType{models.Github},
|
|
RepoAllowlistChecker: &events.RepoAllowlistChecker{},
|
|
VCSClient: vcsClient,
|
|
SilenceAllowlistErrors: true,
|
|
}
|
|
requestJSON, err := os.ReadFile(filepath.Join("testdata", "githubIssueCommentEvent_notAllowlisted.json"))
|
|
Ok(t, err)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(requestJSON))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.Header.Set(githubHeader, "issue_comment")
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
|
|
resp := w.Result()
|
|
defer resp.Body.Close()
|
|
Equals(t, http.StatusForbidden, resp.StatusCode)
|
|
body, _ := io.ReadAll(resp.Body)
|
|
exp := "Repo not allowlisted"
|
|
Assert(t, strings.Contains(string(body), exp), "exp %q to be contained in %q", exp, string(body))
|
|
vcsClient.VerifyWasCalled(Never()).CreateComment(Any[logging.SimpleLogging](), Any[models.Repo](), Any[int](), Any[string](), Any[string]())
|
|
}
|
|
|
|
func TestPost_GitlabCommentResponse(t *testing.T) {
|
|
// When the event is a gitlab comment that warrants a comment response we comment back.
|
|
e, _, gl, _, _, _, _, vcsClient, cp := setup(t)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(gitlabHeader, "value")
|
|
When(gl.ParseAndValidate(req, secret)).ThenReturn(gitlab.MergeCommentEvent{}, nil)
|
|
When(cp.Parse("", models.Gitlab)).ThenReturn(events.CommentParseResult{CommentResponse: "a comment"})
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
vcsClient.VerifyWasCalledOnce().CreateComment(Any[logging.SimpleLogging](), Eq(models.Repo{}), Eq(0), Eq("a comment"), Eq(""))
|
|
ResponseContains(t, w, http.StatusOK, "Commenting back on pull request")
|
|
}
|
|
|
|
func TestPost_GithubCommentResponse(t *testing.T) {
|
|
t.Log("when the event is a github comment that warrants a comment response we comment back")
|
|
e, v, _, _, p, _, _, vcsClient, cp := setup(t)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(githubHeader, "issue_comment")
|
|
event := `{"action": "created"}`
|
|
When(v.Validate(req, secret)).ThenReturn([]byte(event), nil)
|
|
baseRepo := models.Repo{}
|
|
user := models.User{}
|
|
When(p.ParseGithubIssueCommentEvent(Any[logging.SimpleLogging](), Any[*github.IssueCommentEvent]())).ThenReturn(baseRepo, user, 1, nil)
|
|
When(cp.Parse("", models.Github)).ThenReturn(events.CommentParseResult{CommentResponse: "a comment"})
|
|
w := httptest.NewRecorder()
|
|
|
|
e.Post(w, req)
|
|
vcsClient.VerifyWasCalledOnce().CreateComment(Any[logging.SimpleLogging](), Eq(baseRepo), Eq(1), Eq("a comment"), Eq(""))
|
|
ResponseContains(t, w, http.StatusOK, "Commenting back on pull request")
|
|
}
|
|
|
|
func TestPost_GitlabCommentSuccess(t *testing.T) {
|
|
t.Log("when the event is a gitlab comment with a valid command we call the command handler")
|
|
e, _, gl, _, _, cr, _, _, cp := setup(t)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(gitlabHeader, "value")
|
|
cmd := events.CommentCommand{}
|
|
When(gl.ParseAndValidate(req, secret)).ThenReturn(gitlab.MergeCommentEvent{}, nil)
|
|
When(cp.Parse(Any[string](), Eq(models.Gitlab))).ThenReturn(events.CommentParseResult{Command: &cmd})
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusOK, "Processing...")
|
|
|
|
cr.VerifyWasCalledOnce().RunCommentCommand(models.Repo{}, &models.Repo{}, nil, models.User{}, 0, &cmd)
|
|
}
|
|
|
|
func TestPost_GithubCommentSuccess(t *testing.T) {
|
|
t.Log("when the event is a github comment with a valid command we call the command handler")
|
|
e, v, _, _, p, cr, _, _, cp := setup(t)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(githubHeader, "issue_comment")
|
|
event := `{"action": "created"}`
|
|
When(v.Validate(req, secret)).ThenReturn([]byte(event), nil)
|
|
baseRepo := models.Repo{}
|
|
user := models.User{}
|
|
cmd := events.CommentCommand{}
|
|
When(p.ParseGithubIssueCommentEvent(Any[logging.SimpleLogging](), Any[*github.IssueCommentEvent]())).ThenReturn(baseRepo, user, 1, nil)
|
|
When(cp.Parse("", models.Github)).ThenReturn(events.CommentParseResult{Command: &cmd})
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusOK, "Processing...")
|
|
|
|
cr.VerifyWasCalledOnce().RunCommentCommand(baseRepo, nil, nil, user, 1, &cmd)
|
|
}
|
|
|
|
func TestPost_GithubCommentReaction(t *testing.T) {
|
|
t.Log("when the event is a github comment with a valid command we call the ReactToComment handler")
|
|
e, v, _, _, p, _, _, vcsClient, cp := setup(t)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(githubHeader, "issue_comment")
|
|
testComment := "atlantis plan"
|
|
event := fmt.Sprintf(`{"action": "created", "comment": {"body": "%v", "id": 1}}`, testComment)
|
|
When(v.Validate(req, secret)).ThenReturn([]byte(event), nil)
|
|
baseRepo := models.Repo{}
|
|
user := models.User{}
|
|
cmd := events.CommentCommand{Name: command.Plan}
|
|
When(p.ParseGithubIssueCommentEvent(Any[logging.SimpleLogging](), Any[*github.IssueCommentEvent]())).ThenReturn(baseRepo, user, 1, nil)
|
|
When(cp.Parse(testComment, models.Github)).ThenReturn(events.CommentParseResult{Command: &cmd})
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusOK, "Processing...")
|
|
|
|
vcsClient.VerifyWasCalledOnce().ReactToComment(Any[logging.SimpleLogging](), Eq(baseRepo), Eq(1), Eq(int64(1)), Eq("eyes"))
|
|
}
|
|
|
|
func TestPost_GilabCommentReaction(t *testing.T) {
|
|
t.Log("when the event is a gitlab comment with a valid command we call the ReactToComment handler")
|
|
e, _, gl, _, _, _, _, vcsClient, cp := setup(t)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(gitlabHeader, "value")
|
|
cmd := events.CommentCommand{}
|
|
When(gl.ParseAndValidate(req, secret)).ThenReturn(gitlab.MergeCommentEvent{}, nil)
|
|
When(cp.Parse(Any[string](), Eq(models.Gitlab))).ThenReturn(events.CommentParseResult{Command: &cmd})
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusOK, "Processing...")
|
|
vcsClient.VerifyWasCalledOnce().ReactToComment(Any[logging.SimpleLogging](), Eq(models.Repo{}), Eq(0), Eq(int64(0)), Eq("eyes"))
|
|
}
|
|
|
|
func TestPost_GithubPullRequestInvalid(t *testing.T) {
|
|
t.Log("when the event is a github pull request with invalid data we return a 400")
|
|
e, v, _, _, p, _, _, _, _ := setup(t)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(githubHeader, "pull_request")
|
|
|
|
event := `{"action": "closed"}`
|
|
When(v.Validate(req, secret)).ThenReturn([]byte(event), nil)
|
|
When(p.ParseGithubPullEvent(Any[logging.SimpleLogging](), Any[*github.PullRequestEvent]())).ThenReturn(models.PullRequest{}, models.OpenedPullEvent, models.Repo{}, models.Repo{}, models.User{}, errors.New("err"))
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusBadRequest, "Error parsing pull data: err")
|
|
}
|
|
|
|
func TestPost_GitlabMergeRequestInvalid(t *testing.T) {
|
|
t.Log("when the event is a gitlab merge request with invalid data we return a 400")
|
|
e, _, gl, _, p, _, _, _, _ := setup(t)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(gitlabHeader, "value")
|
|
When(gl.ParseAndValidate(req, secret)).ThenReturn(gitlab.MergeEvent{}, nil)
|
|
repo := models.Repo{}
|
|
pullRequest := models.PullRequest{State: models.ClosedPullState}
|
|
When(p.ParseGitlabMergeRequestEvent(gitlab.MergeEvent{})).ThenReturn(pullRequest, models.OpenedPullEvent, repo, repo, models.User{}, errors.New("err"))
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusBadRequest, "Error parsing webhook: err")
|
|
}
|
|
|
|
func TestPost_GithubPullRequestNotAllowlisted(t *testing.T) {
|
|
t.Log("when the event is a github pull request to a non-allowlisted repo we return a 400")
|
|
e, v, _, _, _, _, _, _, _ := setup(t)
|
|
var err error
|
|
e.RepoAllowlistChecker, err = events.NewRepoAllowlistChecker("github.com/nevermatch")
|
|
Ok(t, err)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(githubHeader, "pull_request")
|
|
|
|
event := `{"action": "closed"}`
|
|
When(v.Validate(req, secret)).ThenReturn([]byte(event), nil)
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusForbidden, "Pull request event from non-allowlisted repo")
|
|
}
|
|
|
|
func TestPost_GitlabMergeRequestNotAllowlisted(t *testing.T) {
|
|
t.Log("when the event is a gitlab merge request to a non-allowlisted repo we return a 400")
|
|
e, _, gl, _, p, _, _, _, _ := setup(t)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(gitlabHeader, "value")
|
|
|
|
var err error
|
|
e.RepoAllowlistChecker, err = events.NewRepoAllowlistChecker("github.com/nevermatch")
|
|
Ok(t, err)
|
|
When(gl.ParseAndValidate(req, secret)).ThenReturn(gitlab.MergeEvent{}, nil)
|
|
repo := models.Repo{}
|
|
pullRequest := models.PullRequest{State: models.ClosedPullState}
|
|
When(p.ParseGitlabMergeRequestEvent(gitlab.MergeEvent{})).ThenReturn(pullRequest, models.OpenedPullEvent, repo, repo, models.User{}, nil)
|
|
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusForbidden, "Pull request event from non-allowlisted repo")
|
|
}
|
|
|
|
func TestPost_GithubPullRequestUnsupportedAction(t *testing.T) {
|
|
t.Skip("relies too much on mocks, should use real event parser")
|
|
e, v, _, _, _, _, _, _, _ := setup(t)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(githubHeader, "pull_request")
|
|
|
|
event := `{"action": "unsupported"}`
|
|
When(v.Validate(req, secret)).ThenReturn([]byte(event), nil)
|
|
w := httptest.NewRecorder()
|
|
e.Parser = &events.EventParser{}
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusOK, "Ignoring non-actionable pull request event")
|
|
}
|
|
|
|
func TestPost_GitlabMergeRequestUnsupportedAction(t *testing.T) {
|
|
t.Skip("relies too much on mocks, should use real event parser")
|
|
t.Log("when the event is a gitlab merge request to a non-allowlisted repo we return a 400")
|
|
e, _, gl, _, p, _, _, _, _ := setup(t)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(gitlabHeader, "value")
|
|
var event gitlab.MergeEvent
|
|
event.ObjectAttributes.Action = "unsupported"
|
|
When(gl.ParseAndValidate(req, secret)).ThenReturn(event, nil)
|
|
repo := models.Repo{}
|
|
pullRequest := models.PullRequest{State: models.ClosedPullState}
|
|
When(p.ParseGitlabMergeRequestEvent(event)).ThenReturn(pullRequest, repo, repo, models.User{}, nil)
|
|
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusOK, "Ignoring non-actionable pull request event")
|
|
}
|
|
|
|
func TestPost_AzureDevopsPullRequestIgnoreEvent(t *testing.T) {
|
|
t.Log("when the event is an azure devops pull request update that should not trigger workflow we ignore it")
|
|
e, _, _, ado, _, _, _, _, _ := setup(t)
|
|
|
|
event := `{
|
|
"subscriptionId": "11111111-1111-1111-1111-111111111111",
|
|
"notificationId": 1,
|
|
"id": "22222222-2222-2222-2222-222222222222",
|
|
"eventType": "git.pullrequest.updated",
|
|
"publisherId": "tfs",
|
|
"message": {
|
|
"text": "Dev %s pull request 1 (Name in repo)"
|
|
},
|
|
"resource": {}}`
|
|
|
|
cases := []struct {
|
|
message string
|
|
}{
|
|
{
|
|
"has changed the reviewer list on",
|
|
},
|
|
{
|
|
"has approved",
|
|
},
|
|
{
|
|
"has approved and left suggestions on",
|
|
},
|
|
{
|
|
"is waiting for the author on",
|
|
},
|
|
{
|
|
"rejected",
|
|
},
|
|
{
|
|
"voted on",
|
|
},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
t.Run(c.message, func(t *testing.T) {
|
|
payload := fmt.Sprintf(event, c.message)
|
|
req, _ := http.NewRequest("GET", "", strings.NewReader(payload))
|
|
req.Header.Set(azuredevopsHeader, "reqID")
|
|
When(ado.Validate(req, user, secret)).ThenReturn([]byte(payload), nil)
|
|
w := httptest.NewRecorder()
|
|
e.Parser = &events.EventParser{}
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusOK, "pull request updated event is not a supported type")
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPost_AzureDevopsPullRequestDeletedCommentIgnoreEvent(t *testing.T) {
|
|
t.Log("when the event is an azure devops pull request deleted comment event we ignore it")
|
|
e, _, _, ado, _, _, _, _, _ := setup(t)
|
|
|
|
payload := `{
|
|
"subscriptionId": "11111111-1111-1111-1111-111111111111",
|
|
"notificationId": 1,
|
|
"id": "22222222-2222-2222-2222-222222222222",
|
|
"eventType": "ms.vss-code.git-pullrequest-comment-event",
|
|
"publisherId": "tfs",
|
|
"message": {
|
|
"text": "Dev has deleted a pull request comment"
|
|
},
|
|
"resource": {
|
|
"comment": {
|
|
"id": 1,
|
|
"isDeleted": true,
|
|
"commentType": "text"
|
|
}
|
|
}
|
|
}`
|
|
|
|
t.Run("Dev has deleted a pull request comment", func(t *testing.T) {
|
|
req, _ := http.NewRequest("GET", "", strings.NewReader(payload))
|
|
req.Header.Set(azuredevopsHeader, "reqID")
|
|
When(ado.Validate(req, user, secret)).ThenReturn([]byte(payload), nil)
|
|
w := httptest.NewRecorder()
|
|
e.Parser = &events.EventParser{}
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusOK, "Ignoring comment event since it is linked to deleting a pull request comment")
|
|
})
|
|
}
|
|
|
|
func TestPost_AzureDevopsPullRequestCommentWebhookTestIgnoreEvent(t *testing.T) {
|
|
t.Log("when the event is an azure devops webhook test we ignore it")
|
|
e, _, _, ado, _, _, _, _, _ := setup(t)
|
|
|
|
event := `{
|
|
"subscriptionId": "11111111-1111-1111-1111-111111111111",
|
|
"notificationId": 1,
|
|
"id": "22222222-2222-2222-2222-222222222222",
|
|
"eventType": "%s",
|
|
"publisherId": "tfs",
|
|
"message": {
|
|
"text": "%s"
|
|
},
|
|
"resource": {
|
|
"pullRequest": {
|
|
"repository":{
|
|
"url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079"
|
|
}
|
|
},
|
|
"comment": {
|
|
"content": "This is my comment."
|
|
}
|
|
}}`
|
|
|
|
cases := []struct {
|
|
eventType string
|
|
message string
|
|
}{
|
|
{
|
|
"ms.vss-code.git-pullrequest-comment-event",
|
|
"Jamal Hartnett has edited a pull request comment",
|
|
},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
t.Run(c.message, func(t *testing.T) {
|
|
payload := fmt.Sprintf(event, c.eventType, c.message)
|
|
req, _ := http.NewRequest("GET", "", strings.NewReader(payload))
|
|
req.Header.Set(azuredevopsHeader, "reqID")
|
|
When(ado.Validate(req, user, secret)).ThenReturn([]byte(payload), nil)
|
|
w := httptest.NewRecorder()
|
|
e.Parser = &events.EventParser{}
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusOK, "Ignoring Azure DevOps Test Event with Repo URL")
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPost_AzureDevopsPullRequestWebhookTestIgnoreEvent(t *testing.T) {
|
|
t.Log("when the event is an azure devops webhook tests we ignore it")
|
|
e, _, _, ado, _, _, _, _, _ := setup(t)
|
|
|
|
event := `{
|
|
"subscriptionId": "11111111-1111-1111-1111-111111111111",
|
|
"notificationId": 1,
|
|
"id": "22222222-2222-2222-2222-222222222222",
|
|
"eventType": "%s",
|
|
"publisherId": "tfs",
|
|
"message": {
|
|
"text": "%s"
|
|
},
|
|
"resource": {
|
|
"repository":{
|
|
"url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079"
|
|
}
|
|
}}`
|
|
|
|
cases := []struct {
|
|
eventType string
|
|
message string
|
|
}{
|
|
{
|
|
"git.pullrequest.created",
|
|
"Jamal Hartnett created a new pull request",
|
|
},
|
|
{
|
|
"git.pullrequest.updated",
|
|
"Jamal Hartnett marked the pull request as completed",
|
|
},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
t.Run(c.message, func(t *testing.T) {
|
|
payload := fmt.Sprintf(event, c.eventType, c.message)
|
|
req, _ := http.NewRequest("GET", "", strings.NewReader(payload))
|
|
req.Header.Set(azuredevopsHeader, "reqID")
|
|
When(ado.Validate(req, user, secret)).ThenReturn([]byte(payload), nil)
|
|
w := httptest.NewRecorder()
|
|
e.Parser = &events.EventParser{}
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusOK, "Ignoring Azure DevOps Test Event with Repo URL")
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPost_AzureDevopsPullRequestCommentPassingIgnores(t *testing.T) {
|
|
t.Log("when the event should not be ignored it should pass through all ignore statements without error")
|
|
e, _, _, ado, _, _, _, _, cp := setup(t)
|
|
|
|
testComment := "atlantis plan"
|
|
repo := models.Repo{}
|
|
cmd := events.CommentCommand{Name: command.Plan}
|
|
When(e.Parser.ParseAzureDevopsRepo(Any[*azuredevops.GitRepository]())).ThenReturn(repo, nil)
|
|
When(cp.Parse(testComment, models.AzureDevops)).ThenReturn(events.CommentParseResult{Command: &cmd})
|
|
payload := fmt.Sprintf(`{
|
|
"subscriptionId": "11111111-1111-1111-1111-111111111111",
|
|
"notificationId": 1,
|
|
"id": "22222222-2222-2222-2222-222222222222",
|
|
"eventType": "ms.vss-code.git-pullrequest-comment-event",
|
|
"publisherId": "tfs",
|
|
"message": {
|
|
"text": "Testing to see if comment passes ignore conditions"
|
|
},
|
|
"resource": {
|
|
"comment": {
|
|
"id": 1,
|
|
"commentType": "text",
|
|
"content": "%v"
|
|
},
|
|
"pullRequest": {
|
|
"pullRequestId": 1,
|
|
"repository": {}
|
|
}
|
|
}
|
|
}`, testComment)
|
|
|
|
t.Run("Testing to see if comment passes ignore conditions", func(t *testing.T) {
|
|
req, _ := http.NewRequest("GET", "", strings.NewReader(payload))
|
|
req.Header.Set(azuredevopsHeader, "reqID")
|
|
When(ado.Validate(req, user, secret)).ThenReturn([]byte(payload), nil)
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusOK, "Processing...")
|
|
})
|
|
}
|
|
|
|
func TestPost_GithubPullRequestClosedErrCleaningPull(t *testing.T) {
|
|
t.Skip("relies too much on mocks, should use real event parser")
|
|
t.Log("when the event is a closed pull request and we have an error calling CleanUpPull we return a 503")
|
|
RegisterMockTestingT(t)
|
|
e, v, _, _, p, _, c, _, _ := setup(t)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(githubHeader, "pull_request")
|
|
|
|
event := `{"action": "closed"}`
|
|
When(v.Validate(req, secret)).ThenReturn([]byte(event), nil)
|
|
repo := models.Repo{}
|
|
pull := models.PullRequest{State: models.ClosedPullState}
|
|
When(p.ParseGithubPullEvent(Any[logging.SimpleLogging](), Any[*github.PullRequestEvent]())).ThenReturn(pull, models.OpenedPullEvent, repo, repo, models.User{}, nil)
|
|
When(c.CleanUpPull(Any[logging.SimpleLogging](), repo, pull)).ThenReturn(errors.New("cleanup err"))
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusInternalServerError, "Error cleaning pull request: cleanup err")
|
|
}
|
|
|
|
func TestPost_GitlabMergeRequestClosedErrCleaningPull(t *testing.T) {
|
|
t.Skip("relies too much on mocks, should use real event parser")
|
|
t.Log("when the event is a closed gitlab merge request and an error occurs calling CleanUpPull we return a 500")
|
|
e, _, gl, _, p, _, c, _, _ := setup(t)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(gitlabHeader, "value")
|
|
var event gitlab.MergeEvent
|
|
event.ObjectAttributes.Action = "close"
|
|
When(gl.ParseAndValidate(req, secret)).ThenReturn(event, nil)
|
|
repo := models.Repo{}
|
|
pullRequest := models.PullRequest{State: models.ClosedPullState}
|
|
When(p.ParseGitlabMergeRequestEvent(event)).ThenReturn(pullRequest, models.OpenedPullEvent, repo, repo, models.User{}, nil)
|
|
When(c.CleanUpPull(Any[logging.SimpleLogging](), repo, pullRequest)).ThenReturn(errors.New("err"))
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusInternalServerError, "Error cleaning pull request: err")
|
|
}
|
|
|
|
func TestPost_GithubClosedPullRequestSuccess(t *testing.T) {
|
|
t.Skip("relies too much on mocks, should use real event parser")
|
|
t.Log("when the event is a pull request and everything works we return a 200")
|
|
e, v, _, _, p, _, c, _, _ := setup(t)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(githubHeader, "pull_request")
|
|
|
|
event := `{"action": "closed"}`
|
|
When(v.Validate(req, secret)).ThenReturn([]byte(event), nil)
|
|
repo := models.Repo{}
|
|
pull := models.PullRequest{State: models.ClosedPullState}
|
|
When(p.ParseGithubPullEvent(Any[logging.SimpleLogging](), Any[*github.PullRequestEvent]())).ThenReturn(pull, models.OpenedPullEvent, repo, repo, models.User{}, nil)
|
|
When(c.CleanUpPull(Any[logging.SimpleLogging](), repo, pull)).ThenReturn(nil)
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusOK, "Pull request cleaned successfully")
|
|
}
|
|
|
|
func TestPost_GitlabMergeRequestSuccess(t *testing.T) {
|
|
t.Skip("relies too much on mocks, should use real event parser")
|
|
t.Log("when the event is a gitlab merge request and the cleanup works we return a 200")
|
|
e, _, gl, _, p, _, _, _, _ := setup(t)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
req.Header.Set(gitlabHeader, "value")
|
|
When(gl.ParseAndValidate(req, secret)).ThenReturn(gitlab.MergeEvent{}, nil)
|
|
repo := models.Repo{}
|
|
pullRequest := models.PullRequest{State: models.ClosedPullState}
|
|
When(p.ParseGitlabMergeRequestEvent(gitlab.MergeEvent{})).ThenReturn(pullRequest, models.OpenedPullEvent, repo, repo, models.User{}, nil)
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusOK, "Pull request cleaned successfully")
|
|
}
|
|
|
|
// Test Bitbucket server pull closed events.
|
|
func TestPost_BBServerPullClosed(t *testing.T) {
|
|
cases := []struct {
|
|
header string
|
|
}{
|
|
{
|
|
"pr:deleted",
|
|
},
|
|
{
|
|
"pr:merged",
|
|
},
|
|
{
|
|
"pr:declined",
|
|
},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
t.Run(c.header, func(t *testing.T) {
|
|
RegisterMockTestingT(t)
|
|
pullCleaner := emocks.NewMockPullCleaner()
|
|
allowlist, err := events.NewRepoAllowlistChecker("*")
|
|
Ok(t, err)
|
|
logger := logging.NewNoopLogger(t)
|
|
scope, _, _ := metrics.NewLoggingScope(logger, "null")
|
|
ec := &events_controllers.VCSEventsController{
|
|
PullCleaner: pullCleaner,
|
|
Parser: &events.EventParser{
|
|
BitbucketUser: "bb-user",
|
|
BitbucketToken: "bb-token",
|
|
BitbucketServerURL: "https://bbserver.com",
|
|
},
|
|
RepoAllowlistChecker: allowlist,
|
|
SupportedVCSHosts: []models.VCSHostType{models.BitbucketServer},
|
|
VCSClient: nil,
|
|
Logger: logger,
|
|
Scope: scope,
|
|
}
|
|
|
|
// Build HTTP request.
|
|
requestBytes, err := os.ReadFile(filepath.Join("testdata", "bb-server-pull-deleted-event.json"))
|
|
// Replace the eventKey field with our event type.
|
|
requestJSON := strings.Replace(string(requestBytes), `"eventKey":"pr:deleted",`, fmt.Sprintf(`"eventKey":"%s",`, c.header), -1)
|
|
Ok(t, err)
|
|
req, err := http.NewRequest("POST", "/events", bytes.NewBuffer([]byte(requestJSON)))
|
|
Ok(t, err)
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.Header.Set("X-Event-Key", c.header)
|
|
req.Header.Set("X-Request-ID", "request-id")
|
|
|
|
// Send the request.
|
|
w := httptest.NewRecorder()
|
|
ec.Post(w, req)
|
|
|
|
// Make our assertions.
|
|
ResponseContains(t, w, 200, "Pull request cleaned successfully")
|
|
|
|
expRepo := models.Repo{
|
|
FullName: "project/repository",
|
|
Owner: "project",
|
|
Name: "repository",
|
|
CloneURL: "https://bb-user:bb-token@bbserver.com/scm/proj/repository.git",
|
|
SanitizedCloneURL: "https://bb-user:<redacted>@bbserver.com/scm/proj/repository.git",
|
|
VCSHost: models.VCSHost{
|
|
Hostname: "bbserver.com",
|
|
Type: models.BitbucketServer,
|
|
},
|
|
}
|
|
pullCleaner.VerifyWasCalledOnce().CleanUpPull(
|
|
logger,
|
|
expRepo, models.PullRequest{
|
|
Num: 10,
|
|
HeadCommit: "2d9fb6b9a46eafb1dcef7b008d1a429d45ca742c",
|
|
URL: "https://bbserver.com/projects/PROJ/repos/repository/pull-requests/10",
|
|
HeadBranch: "decline-me",
|
|
BaseBranch: "main",
|
|
Author: "admin",
|
|
State: models.OpenPullState,
|
|
BaseRepo: expRepo,
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPost_PullOpenedOrUpdated(t *testing.T) {
|
|
cases := []struct {
|
|
Description string
|
|
HostType models.VCSHostType
|
|
Action string
|
|
}{
|
|
{
|
|
"github opened",
|
|
models.Github,
|
|
"opened",
|
|
},
|
|
{
|
|
"gitlab opened",
|
|
models.Gitlab,
|
|
"open",
|
|
},
|
|
{
|
|
"github synchronized",
|
|
models.Github,
|
|
"synchronize",
|
|
},
|
|
{
|
|
"gitlab update",
|
|
models.Gitlab,
|
|
"update",
|
|
},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
t.Run(c.Description, func(t *testing.T) {
|
|
e, v, gl, _, p, cr, _, _, _ := setup(t)
|
|
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
var pullRequest models.PullRequest
|
|
var repo models.Repo
|
|
|
|
switch c.HostType {
|
|
case models.Gitlab:
|
|
req.Header.Set(gitlabHeader, "value")
|
|
var event gitlab.MergeEvent
|
|
event.ObjectAttributes.Action = c.Action
|
|
When(gl.ParseAndValidate(req, secret)).ThenReturn(event, nil)
|
|
repo = models.Repo{}
|
|
pullRequest = models.PullRequest{State: models.ClosedPullState}
|
|
When(p.ParseGitlabMergeRequestEvent(event)).ThenReturn(pullRequest, models.OpenedPullEvent, repo, repo, models.User{}, nil)
|
|
case models.Github:
|
|
req.Header.Set(githubHeader, "pull_request")
|
|
event := fmt.Sprintf(`{"action": "%s"}`, c.Action)
|
|
When(v.Validate(req, secret)).ThenReturn([]byte(event), nil)
|
|
repo = models.Repo{}
|
|
pullRequest = models.PullRequest{State: models.ClosedPullState}
|
|
When(p.ParseGithubPullEvent(Any[logging.SimpleLogging](), Any[*github.PullRequestEvent]())).ThenReturn(pullRequest, models.OpenedPullEvent, repo, repo, models.User{}, nil)
|
|
}
|
|
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, req)
|
|
ResponseContains(t, w, http.StatusOK, "Processing...")
|
|
cr.VerifyWasCalledOnce().RunAutoplanCommand(models.Repo{}, models.Repo{}, models.PullRequest{State: models.ClosedPullState}, models.User{})
|
|
})
|
|
}
|
|
}
|
|
|
|
func setup(t *testing.T) (events_controllers.VCSEventsController, *mocks.MockGithubRequestValidator, *mocks.MockGitlabRequestParserValidator, *mocks.MockAzureDevopsRequestValidator, *emocks.MockEventParsing, *emocks.MockCommandRunner, *emocks.MockPullCleaner, *vcsmocks.MockClient, *emocks.MockCommentParsing) {
|
|
RegisterMockTestingT(t)
|
|
v := mocks.NewMockGithubRequestValidator()
|
|
gl := mocks.NewMockGitlabRequestParserValidator()
|
|
ado := mocks.NewMockAzureDevopsRequestValidator()
|
|
p := emocks.NewMockEventParsing()
|
|
cp := emocks.NewMockCommentParsing()
|
|
cr := emocks.NewMockCommandRunner()
|
|
c := emocks.NewMockPullCleaner()
|
|
vcsmock := vcsmocks.NewMockClient()
|
|
repoAllowlistChecker, err := events.NewRepoAllowlistChecker("*")
|
|
Ok(t, err)
|
|
logger := logging.NewNoopLogger(t)
|
|
scope, _, _ := metrics.NewLoggingScope(logger, "null")
|
|
e := events_controllers.VCSEventsController{
|
|
ExecutableName: "atlantis",
|
|
EmojiReaction: "eyes",
|
|
TestingMode: true,
|
|
Logger: logger,
|
|
Scope: scope,
|
|
ApplyDisabled: false,
|
|
AzureDevopsWebhookBasicUser: user,
|
|
AzureDevopsWebhookBasicPassword: secret,
|
|
AzureDevopsRequestValidator: ado,
|
|
GithubRequestValidator: v,
|
|
Parser: p,
|
|
CommentParser: cp,
|
|
CommandRunner: cr,
|
|
PullCleaner: c,
|
|
GithubWebhookSecret: secret,
|
|
SupportedVCSHosts: []models.VCSHostType{models.Github, models.Gitlab, models.AzureDevops, models.Gitea},
|
|
GiteaWebhookSecret: secret,
|
|
GitlabWebhookSecret: secret,
|
|
GitlabRequestParserValidator: gl,
|
|
RepoAllowlistChecker: repoAllowlistChecker,
|
|
VCSClient: vcsmock,
|
|
}
|
|
return e, v, gl, ado, p, cr, c, vcsmock, cp
|
|
}
|