mirror of
https://git.vectorsigma.ru/public/atlantis.git
synced 2026-07-29 04:08:35 +00:00
- Need to use the mergeable_state field in GitHub to know if a pull request is mergeable. - Add tests. - Since we updated our vendored go-github library, fix how we were creating webhooks in testdrive.
244 lines
6.2 KiB
Go
244 lines
6.2 KiB
Go
package vcs_test
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/runatlantis/atlantis/server/events/models"
|
|
"github.com/runatlantis/atlantis/server/events/vcs"
|
|
. "github.com/runatlantis/atlantis/testing"
|
|
)
|
|
|
|
// GetModifiedFiles should make multiple requests if more than one page
|
|
// and concat results.
|
|
func TestGithubClient_GetModifiedFiles(t *testing.T) {
|
|
respTemplate := `[
|
|
{
|
|
"sha": "bbcd538c8e72b8c175046e27cc8f907076331401",
|
|
"filename": "%s",
|
|
"status": "added",
|
|
"additions": 103,
|
|
"deletions": 21,
|
|
"changes": 124,
|
|
"blob_url": "https://github.com/octocat/Hello-World/blob/6dcb09b5b57875f334f61aebed695e2e4193db5e/file1.txt",
|
|
"raw_url": "https://github.com/octocat/Hello-World/raw/6dcb09b5b57875f334f61aebed695e2e4193db5e/file1.txt",
|
|
"contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/file1.txt?ref=6dcb09b5b57875f334f61aebed695e2e4193db5e",
|
|
"patch": "@@ -132,7 +132,7 @@ module Test @@ -1000,7 +1000,7 @@ module Test"
|
|
}
|
|
]`
|
|
firstResp := fmt.Sprintf(respTemplate, "file1.txt")
|
|
secondResp := fmt.Sprintf(respTemplate, "file2.txt")
|
|
testServer := httptest.NewTLSServer(
|
|
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
switch r.RequestURI {
|
|
// The first request should hit this URL.
|
|
case "/api/v3/repos/owner/repo/pulls/1/files?per_page=300":
|
|
// We write a header that means there's an additional page.
|
|
w.Header().Add("Link", `<https://api.github.com/resource?page=2>; rel="next",
|
|
<https://api.github.com/resource?page=2>; rel="last"`)
|
|
w.Write([]byte(firstResp)) // nolint: errcheck
|
|
return
|
|
// The second should hit this URL.
|
|
case "/api/v3/repos/owner/repo/pulls/1/files?page=2&per_page=300":
|
|
w.Write([]byte(secondResp)) // nolint: errcheck
|
|
default:
|
|
t.Errorf("got unexpected request at %q", r.RequestURI)
|
|
http.Error(w, "not found", http.StatusNotFound)
|
|
return
|
|
}
|
|
}))
|
|
|
|
testServerURL, err := url.Parse(testServer.URL)
|
|
Ok(t, err)
|
|
client, err := vcs.NewGithubClient(testServerURL.Host, "user", "pass")
|
|
Ok(t, err)
|
|
defer disableSSLVerification()()
|
|
|
|
files, err := client.GetModifiedFiles(models.Repo{
|
|
FullName: "owner/repo",
|
|
Owner: "owner",
|
|
Name: "repo",
|
|
CloneURL: "",
|
|
SanitizedCloneURL: "",
|
|
VCSHost: models.VCSHost{
|
|
Type: models.Github,
|
|
Hostname: "github.com",
|
|
},
|
|
}, models.PullRequest{
|
|
Num: 1,
|
|
})
|
|
Ok(t, err)
|
|
Equals(t, []string{"file1.txt", "file2.txt"}, files)
|
|
}
|
|
|
|
func TestGithubClient_UpdateStatus(t *testing.T) {
|
|
cases := []struct {
|
|
status models.CommitStatus
|
|
expState string
|
|
}{
|
|
{
|
|
models.PendingCommitStatus,
|
|
"pending",
|
|
},
|
|
{
|
|
models.SuccessCommitStatus,
|
|
"success",
|
|
},
|
|
{
|
|
models.FailedCommitStatus,
|
|
"failure",
|
|
},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
t.Run(c.status.String(), func(t *testing.T) {
|
|
testServer := httptest.NewTLSServer(
|
|
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
switch r.RequestURI {
|
|
case "/api/v3/repos/owner/repo/statuses/":
|
|
body, err := ioutil.ReadAll(r.Body)
|
|
Ok(t, err)
|
|
exp := fmt.Sprintf(`{"state":"%s","description":"description","context":"Atlantis"}%s`, c.expState, "\n")
|
|
Equals(t, exp, string(body))
|
|
defer r.Body.Close() // nolint: errcheck
|
|
w.WriteHeader(http.StatusOK)
|
|
default:
|
|
t.Errorf("got unexpected request at %q", r.RequestURI)
|
|
http.Error(w, "not found", http.StatusNotFound)
|
|
return
|
|
}
|
|
}))
|
|
|
|
testServerURL, err := url.Parse(testServer.URL)
|
|
Ok(t, err)
|
|
client, err := vcs.NewGithubClient(testServerURL.Host, "user", "pass")
|
|
Ok(t, err)
|
|
defer disableSSLVerification()()
|
|
|
|
err = client.UpdateStatus(models.Repo{
|
|
FullName: "owner/repo",
|
|
Owner: "owner",
|
|
Name: "repo",
|
|
CloneURL: "",
|
|
SanitizedCloneURL: "",
|
|
VCSHost: models.VCSHost{
|
|
Type: models.Github,
|
|
Hostname: "github.com",
|
|
},
|
|
}, models.PullRequest{
|
|
Num: 1,
|
|
}, c.status, "description")
|
|
Ok(t, err)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGithubClient_PullIsMergeable(t *testing.T) {
|
|
cases := []struct {
|
|
state string
|
|
expMergeable bool
|
|
}{
|
|
{
|
|
"dirty",
|
|
false,
|
|
},
|
|
{
|
|
"unknown",
|
|
false,
|
|
},
|
|
{
|
|
"blocked",
|
|
false,
|
|
},
|
|
{
|
|
"behind",
|
|
false,
|
|
},
|
|
{
|
|
"random",
|
|
false,
|
|
},
|
|
{
|
|
"unstable",
|
|
true,
|
|
},
|
|
{
|
|
"has_hooks",
|
|
true,
|
|
},
|
|
{
|
|
"clean",
|
|
true,
|
|
},
|
|
{
|
|
"",
|
|
false,
|
|
},
|
|
}
|
|
|
|
// Use a real GitHub json response and edit the mergeable_state field.
|
|
jsBytes, err := ioutil.ReadFile("fixtures/github-pull-request.json")
|
|
Ok(t, err)
|
|
json := string(jsBytes)
|
|
|
|
for _, c := range cases {
|
|
t.Run(c.state, func(t *testing.T) {
|
|
response := strings.Replace(json,
|
|
`"mergeable_state": "clean"`,
|
|
fmt.Sprintf(`"mergeable_state": "%s"`, c.state),
|
|
1,
|
|
)
|
|
|
|
testServer := httptest.NewTLSServer(
|
|
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
switch r.RequestURI {
|
|
case "/api/v3/repos/owner/repo/pulls/1":
|
|
w.Write([]byte(response)) // nolint: errcheck
|
|
return
|
|
default:
|
|
t.Errorf("got unexpected request at %q", r.RequestURI)
|
|
http.Error(w, "not found", http.StatusNotFound)
|
|
return
|
|
}
|
|
}))
|
|
testServerURL, err := url.Parse(testServer.URL)
|
|
Ok(t, err)
|
|
client, err := vcs.NewGithubClient(testServerURL.Host, "user", "pass")
|
|
Ok(t, err)
|
|
defer disableSSLVerification()()
|
|
|
|
actMergeable, err := client.PullIsMergeable(models.Repo{
|
|
FullName: "owner/repo",
|
|
Owner: "owner",
|
|
Name: "repo",
|
|
CloneURL: "",
|
|
SanitizedCloneURL: "",
|
|
VCSHost: models.VCSHost{
|
|
Type: models.Github,
|
|
Hostname: "github.com",
|
|
},
|
|
}, models.PullRequest{
|
|
Num: 1,
|
|
})
|
|
Ok(t, err)
|
|
Equals(t, c.expMergeable, actMergeable)
|
|
})
|
|
}
|
|
}
|
|
|
|
// disableSSLVerification disables ssl verification for the global http client
|
|
// and returns a function to be called in a defer that will re-enable it.
|
|
func disableSSLVerification() func() {
|
|
orig := http.DefaultTransport.(*http.Transport).TLSClientConfig
|
|
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
|
return func() {
|
|
http.DefaultTransport.(*http.Transport).TLSClientConfig = orig
|
|
}
|
|
}
|