mirror of
https://git.vectorsigma.ru/public/atlantis.git
synced 2026-07-29 17:38:27 +00:00
348 lines
15 KiB
Go
348 lines
15 KiB
Go
package server_test
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/lkysow/go-gitlab"
|
|
. "github.com/petergtz/pegomock"
|
|
"github.com/runatlantis/atlantis/server"
|
|
"github.com/runatlantis/atlantis/server/events"
|
|
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"
|
|
)
|
|
|
|
const githubHeader = "X-Github-Event"
|
|
const gitlabHeader = "X-Gitlab-Event"
|
|
|
|
var secret = []byte("secret")
|
|
var eventsReq *http.Request
|
|
|
|
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()
|
|
e.Post(w, eventsReq)
|
|
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
|
|
eventsReq.Header.Set(githubHeader, "value")
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, eventsReq)
|
|
responseContains(t, w, http.StatusBadRequest, "Ignoring request since not configured to support GitHub")
|
|
}
|
|
|
|
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
|
|
eventsReq.Header.Set(gitlabHeader, "value")
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, eventsReq)
|
|
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()
|
|
eventsReq.Header.Set(githubHeader, "value")
|
|
When(v.Validate(eventsReq, secret)).ThenReturn(nil, errors.New("err"))
|
|
e.Post(w, eventsReq)
|
|
responseContains(t, w, http.StatusBadRequest, "err")
|
|
}
|
|
|
|
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()
|
|
eventsReq.Header.Set(gitlabHeader, "value")
|
|
When(gl.Validate(eventsReq, secret)).ThenReturn(nil, errors.New("err"))
|
|
e.Post(w, eventsReq)
|
|
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()
|
|
eventsReq.Header.Set(githubHeader, "value")
|
|
When(v.Validate(eventsReq, nil)).ThenReturn([]byte(`{"not an event": ""}`), nil)
|
|
e.Post(w, eventsReq)
|
|
responseContains(t, w, http.StatusOK, "Ignoring unsupported 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()
|
|
eventsReq.Header.Set(gitlabHeader, "value")
|
|
When(gl.Validate(eventsReq, secret)).ThenReturn([]byte(`{"not an event": ""}`), nil)
|
|
e.Post(w, eventsReq)
|
|
responseContains(t, w, http.StatusOK, "Ignoring unsupported 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)
|
|
eventsReq.Header.Set(githubHeader, "issue_comment")
|
|
// comment action is deleted, not created
|
|
event := `{"action": "deleted"}`
|
|
When(v.Validate(eventsReq, secret)).ThenReturn([]byte(event), nil)
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, eventsReq)
|
|
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)
|
|
eventsReq.Header.Set(githubHeader, "issue_comment")
|
|
event := `{"action": "created"}`
|
|
When(v.Validate(eventsReq, secret)).ThenReturn([]byte(event), nil)
|
|
When(p.ParseGithubIssueCommentEvent(matchers.AnyPtrToGithubIssueCommentEvent())).ThenReturn(models.Repo{}, models.User{}, 1, errors.New("err"))
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, eventsReq)
|
|
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)
|
|
eventsReq.Header.Set(gitlabHeader, "value")
|
|
When(gl.Validate(eventsReq, secret)).ThenReturn(gitlab.MergeCommentEvent{}, nil)
|
|
When(cp.Parse("", vcs.Gitlab)).ThenReturn(events.CommentParseResult{Ignore: true})
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, eventsReq)
|
|
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, _, _, _, cp := setup(t)
|
|
eventsReq.Header.Set(githubHeader, "issue_comment")
|
|
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})
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, eventsReq)
|
|
responseContains(t, w, http.StatusOK, "Ignoring non-command comment: \"\"")
|
|
}
|
|
|
|
func TestPost_GitlabCommentResponse(t *testing.T) {
|
|
t.Log("when the event is a gitlab comment that warrants a comment response we comment back")
|
|
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"})
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, eventsReq)
|
|
vcsClient.VerifyWasCalledOnce().CreateComment(models.Repo{}, 0, "a comment", vcs.Gitlab)
|
|
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)
|
|
eventsReq.Header.Set(githubHeader, "issue_comment")
|
|
event := `{"action": "created"}`
|
|
When(v.Validate(eventsReq, secret)).ThenReturn([]byte(event), nil)
|
|
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"})
|
|
w := httptest.NewRecorder()
|
|
|
|
e.Post(w, eventsReq)
|
|
vcsClient.VerifyWasCalledOnce().CreateComment(baseRepo, 1, "a comment", vcs.Github)
|
|
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, _, _, _ := setup(t)
|
|
eventsReq.Header.Set(gitlabHeader, "value")
|
|
When(gl.Validate(eventsReq, secret)).ThenReturn(gitlab.MergeCommentEvent{}, nil)
|
|
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(models.Repo{}, models.Repo{}, models.User{}, 0, nil, vcs.Gitlab)
|
|
}
|
|
|
|
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)
|
|
eventsReq.Header.Set(githubHeader, "issue_comment")
|
|
event := `{"action": "created"}`
|
|
When(v.Validate(eventsReq, secret)).ThenReturn([]byte(event), nil)
|
|
baseRepo := models.Repo{}
|
|
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})
|
|
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)
|
|
}
|
|
|
|
func TestPost_GithubPullRequestNotClosed(t *testing.T) {
|
|
t.Log("when the event is a github pull reuqest but it's not a closed event we ignore it")
|
|
e, v, _, _, _, _, _, _ := setup(t)
|
|
eventsReq.Header.Set(githubHeader, "pull_request")
|
|
event := `{"action": "opened"}`
|
|
When(v.Validate(eventsReq, secret)).ThenReturn([]byte(event), nil)
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, eventsReq)
|
|
responseContains(t, w, http.StatusOK, "Ignoring pull request event since action was not closed")
|
|
}
|
|
|
|
func TestPost_GitlabMergeRequestNotClosed(t *testing.T) {
|
|
t.Log("when the event is a gitlab merge request but it's not a closed event we ignore it")
|
|
e, _, gl, p, _, _, _, _ := setup(t)
|
|
eventsReq.Header.Set(gitlabHeader, "value")
|
|
event := gitlab.MergeEvent{}
|
|
When(gl.Validate(eventsReq, secret)).ThenReturn(event, nil)
|
|
When(p.ParseGitlabMergeEvent(event)).ThenReturn(models.PullRequest{State: models.Open}, models.Repo{})
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, eventsReq)
|
|
responseContains(t, w, http.StatusOK, "Ignoring opened merge request event")
|
|
}
|
|
|
|
func TestPost_GithubPullRequestInvalid(t *testing.T) {
|
|
t.Log("when the event is a github pull request with invalid data we return a 400")
|
|
e, v, _, p, _, _, _, _ := setup(t)
|
|
eventsReq.Header.Set(githubHeader, "pull_request")
|
|
|
|
event := `{"action": "closed"}`
|
|
When(v.Validate(eventsReq, secret)).ThenReturn([]byte(event), nil)
|
|
When(p.ParseGithubPull(matchers.AnyPtrToGithubPullRequest())).ThenReturn(models.PullRequest{}, models.Repo{}, errors.New("err"))
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, eventsReq)
|
|
responseContains(t, w, http.StatusBadRequest, "Error parsing pull data: err")
|
|
}
|
|
|
|
func TestPost_GithubPullRequestInvalidRepo(t *testing.T) {
|
|
t.Log("when the event is a github pull request with invalid repo data we return a 400")
|
|
e, v, _, p, _, _, _, _ := setup(t)
|
|
eventsReq.Header.Set(githubHeader, "pull_request")
|
|
|
|
event := `{"action": "closed"}`
|
|
When(v.Validate(eventsReq, secret)).ThenReturn([]byte(event), nil)
|
|
When(p.ParseGithubPull(matchers.AnyPtrToGithubPullRequest())).ThenReturn(models.PullRequest{}, models.Repo{}, nil)
|
|
When(p.ParseGithubRepo(matchers.AnyPtrToGithubRepository())).ThenReturn(models.Repo{}, errors.New("err"))
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, eventsReq)
|
|
responseContains(t, w, http.StatusBadRequest, "Error parsing repo data: err")
|
|
}
|
|
|
|
func TestPost_GithubPullRequestErrCleaningPull(t *testing.T) {
|
|
t.Log("when the event is a pull request and we have an error calling CleanUpPull we return a 503")
|
|
RegisterMockTestingT(t)
|
|
e, v, _, p, _, c, _, _ := setup(t)
|
|
eventsReq.Header.Set(githubHeader, "pull_request")
|
|
|
|
event := `{"action": "closed"}`
|
|
When(v.Validate(eventsReq, secret)).ThenReturn([]byte(event), nil)
|
|
repo := models.Repo{}
|
|
pull := models.PullRequest{}
|
|
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"))
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, eventsReq)
|
|
responseContains(t, w, http.StatusInternalServerError, "Error cleaning pull request: cleanup err")
|
|
}
|
|
|
|
func TestPost_GitlabMergeRequestErrCleaningPull(t *testing.T) {
|
|
t.Log("when the event is a gitlab merge request and an error occurs calling CleanUpPull we return a 503")
|
|
e, _, gl, p, _, c, _, _ := setup(t)
|
|
eventsReq.Header.Set(gitlabHeader, "value")
|
|
event := gitlab.MergeEvent{}
|
|
When(gl.Validate(eventsReq, secret)).ThenReturn(event, nil)
|
|
repo := models.Repo{}
|
|
pullRequest := models.PullRequest{State: models.Closed}
|
|
When(p.ParseGitlabMergeEvent(event)).ThenReturn(pullRequest, repo)
|
|
When(c.CleanUpPull(repo, pullRequest, vcs.Gitlab)).ThenReturn(errors.New("err"))
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, eventsReq)
|
|
responseContains(t, w, http.StatusInternalServerError, "Error cleaning pull request: err")
|
|
}
|
|
|
|
func TestPost_GithubPullRequestSuccess(t *testing.T) {
|
|
t.Log("when the event is a pull request and everything works we return a 200")
|
|
e, v, _, p, _, c, _, _ := setup(t)
|
|
eventsReq.Header.Set(githubHeader, "pull_request")
|
|
|
|
event := `{"action": "closed"}`
|
|
When(v.Validate(eventsReq, secret)).ThenReturn([]byte(event), nil)
|
|
repo := models.Repo{}
|
|
pull := models.PullRequest{}
|
|
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)
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, eventsReq)
|
|
responseContains(t, w, http.StatusOK, "Pull request cleaned successfully")
|
|
}
|
|
|
|
func TestPost_GitlabMergeRequestSuccess(t *testing.T) {
|
|
t.Log("when the event is a gitlab merge request and the cleanup works we return a 200")
|
|
e, _, gl, p, _, _, _, _ := setup(t)
|
|
eventsReq.Header.Set(gitlabHeader, "value")
|
|
event := gitlab.MergeEvent{}
|
|
When(gl.Validate(eventsReq, secret)).ThenReturn(event, nil)
|
|
repo := models.Repo{}
|
|
pullRequest := models.PullRequest{State: models.Closed}
|
|
When(p.ParseGitlabMergeEvent(event)).ThenReturn(pullRequest, repo)
|
|
w := httptest.NewRecorder()
|
|
e.Post(w, eventsReq)
|
|
responseContains(t, w, http.StatusOK, "Merge request cleaned successfully")
|
|
}
|
|
|
|
func setup(t *testing.T) (server.EventsController, *mocks.MockGithubRequestValidator, *mocks.MockGitlabRequestParser, *emocks.MockEventParsing, *emocks.MockCommandRunner, *emocks.MockPullCleaner, *vcsmocks.MockClientProxy, *emocks.MockCommentParsing) {
|
|
RegisterMockTestingT(t)
|
|
eventsReq, _ = http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
|
v := mocks.NewMockGithubRequestValidator()
|
|
gl := mocks.NewMockGitlabRequestParser()
|
|
p := emocks.NewMockEventParsing()
|
|
cp := emocks.NewMockCommentParsing()
|
|
cr := emocks.NewMockCommandRunner()
|
|
c := emocks.NewMockPullCleaner()
|
|
vcsmock := vcsmocks.NewMockClientProxy()
|
|
e := server.EventsController{
|
|
Logger: logging.NewNoopLogger(),
|
|
GithubRequestValidator: v,
|
|
Parser: p,
|
|
CommentParser: cp,
|
|
CommandRunner: cr,
|
|
PullCleaner: c,
|
|
GithubWebHookSecret: secret,
|
|
SupportedVCSHosts: []vcs.Host{vcs.Github, vcs.Gitlab},
|
|
GitlabWebHookSecret: secret,
|
|
GitlabRequestParser: gl,
|
|
VCSClient: vcsmock,
|
|
}
|
|
return e, v, gl, p, cr, c, vcsmock, cp
|
|
}
|