mirror of
https://git.vectorsigma.ru/public/atlantis.git
synced 2026-08-03 07:58:32 +00:00
Add hostname to Repo model.
- Ended up changing how we parse the json so we do the validation in the constructor of the Repo so it's the same everywhere. - This is a preliminary commit to finish the repo whitelisting feature
This commit is contained in:
@@ -1,13 +1,11 @@
|
||||
package events
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/google/go-github/github"
|
||||
"github.com/lkysow/go-gitlab"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/runatlantis/atlantis/server/events/models"
|
||||
)
|
||||
|
||||
@@ -35,8 +33,8 @@ type EventParsing interface {
|
||||
ParseGithubIssueCommentEvent(comment *github.IssueCommentEvent) (baseRepo models.Repo, user models.User, pullNum int, err error)
|
||||
ParseGithubPull(pull *github.PullRequest) (models.PullRequest, models.Repo, error)
|
||||
ParseGithubRepo(ghRepo *github.Repository) (models.Repo, error)
|
||||
ParseGitlabMergeEvent(event gitlab.MergeEvent) (models.PullRequest, models.Repo)
|
||||
ParseGitlabMergeCommentEvent(event gitlab.MergeCommentEvent) (baseRepo models.Repo, headRepo models.Repo, user models.User)
|
||||
ParseGitlabMergeEvent(event gitlab.MergeEvent) (models.PullRequest, models.Repo, error)
|
||||
ParseGitlabMergeCommentEvent(event gitlab.MergeCommentEvent) (baseRepo models.Repo, headRepo models.Repo, user models.User, err error)
|
||||
ParseGitlabMergeRequest(mr *gitlab.MergeRequest) models.PullRequest
|
||||
}
|
||||
|
||||
@@ -114,37 +112,10 @@ func (e *EventParser) ParseGithubPull(pull *github.PullRequest) (models.PullRequ
|
||||
}
|
||||
|
||||
func (e *EventParser) ParseGithubRepo(ghRepo *github.Repository) (models.Repo, error) {
|
||||
var repo models.Repo
|
||||
repoFullName := ghRepo.GetFullName()
|
||||
if repoFullName == "" {
|
||||
return repo, errors.New("repository.full_name is null")
|
||||
}
|
||||
repoOwner := ghRepo.Owner.GetLogin()
|
||||
if repoOwner == "" {
|
||||
return repo, errors.New("repository.owner.login is null")
|
||||
}
|
||||
repoName := ghRepo.GetName()
|
||||
if repoName == "" {
|
||||
return repo, errors.New("repository.name is null")
|
||||
}
|
||||
repoSanitizedCloneURL := ghRepo.GetCloneURL()
|
||||
if repoSanitizedCloneURL == "" {
|
||||
return repo, errors.New("repository.clone_url is null")
|
||||
}
|
||||
|
||||
// Construct HTTPS repo clone url string with username and password.
|
||||
repoCloneURL := strings.Replace(repoSanitizedCloneURL, "https://", fmt.Sprintf("https://%s:%s@", e.GithubUser, e.GithubToken), -1)
|
||||
|
||||
return models.Repo{
|
||||
Owner: repoOwner,
|
||||
FullName: repoFullName,
|
||||
CloneURL: repoCloneURL,
|
||||
SanitizedCloneURL: repoSanitizedCloneURL,
|
||||
Name: repoName,
|
||||
}, nil
|
||||
return models.NewRepo(ghRepo.GetFullName(), ghRepo.GetCloneURL(), e.GithubUser, e.GithubToken)
|
||||
}
|
||||
|
||||
func (e *EventParser) ParseGitlabMergeEvent(event gitlab.MergeEvent) (models.PullRequest, models.Repo) {
|
||||
func (e *EventParser) ParseGitlabMergeEvent(event gitlab.MergeEvent) (models.PullRequest, models.Repo, error) {
|
||||
modelState := models.Closed
|
||||
if event.ObjectAttributes.State == gitlabPullOpened {
|
||||
modelState = models.Open
|
||||
@@ -161,62 +132,27 @@ func (e *EventParser) ParseGitlabMergeEvent(event gitlab.MergeEvent) (models.Pul
|
||||
State: modelState,
|
||||
}
|
||||
|
||||
cloneURL := e.addGitlabAuth(event.Project.GitHTTPURL)
|
||||
// Get owner and name from PathWithNamespace because the fields
|
||||
// event.Project.Name and event.Project.Owner can have capitals.
|
||||
owner, name := e.getOwnerAndName(event.Project.PathWithNamespace)
|
||||
repo := models.Repo{
|
||||
FullName: event.Project.PathWithNamespace,
|
||||
Name: name,
|
||||
SanitizedCloneURL: event.Project.GitHTTPURL,
|
||||
Owner: owner,
|
||||
CloneURL: cloneURL,
|
||||
}
|
||||
return pull, repo
|
||||
}
|
||||
|
||||
// addGitlabAuth adds gitlab username/password to the cloneURL.
|
||||
// We support http and https URLs because GitLab's docs have http:// URLs whereas
|
||||
// their API responses have https://.
|
||||
// Ex. https://gitlab.com/owner/repo.git => https://uname:pass@gitlab.com/owner/repo.git
|
||||
func (e *EventParser) addGitlabAuth(cloneURL string) string {
|
||||
httpsReplaced := strings.Replace(cloneURL, "https://", fmt.Sprintf("https://%s:%s@", e.GitlabUser, e.GitlabToken), -1)
|
||||
return strings.Replace(httpsReplaced, "http://", fmt.Sprintf("http://%s:%s@", e.GitlabUser, e.GitlabToken), -1)
|
||||
}
|
||||
|
||||
// getOwnerAndName takes pathWithNamespace that should look like "owner/repo"
|
||||
// and returns "owner", "repo"
|
||||
func (e *EventParser) getOwnerAndName(pathWithNamespace string) (string, string) {
|
||||
pathSplit := strings.Split(pathWithNamespace, "/")
|
||||
if len(pathSplit) > 1 {
|
||||
return pathSplit[0], pathSplit[1]
|
||||
}
|
||||
return "", ""
|
||||
repo, err := models.NewRepo(event.Project.PathWithNamespace, event.Project.GitHTTPURL, e.GitlabUser, e.GitlabToken)
|
||||
return pull, repo, err
|
||||
}
|
||||
|
||||
// ParseGitlabMergeCommentEvent creates Atlantis models out of a GitLab event.
|
||||
func (e *EventParser) ParseGitlabMergeCommentEvent(event gitlab.MergeCommentEvent) (baseRepo models.Repo, headRepo models.Repo, user models.User) {
|
||||
// Get owner and name from PathWithNamespace because the fields
|
||||
// event.Project.Name and event.Project.Owner can have capitals.
|
||||
owner, name := e.getOwnerAndName(event.Project.PathWithNamespace)
|
||||
baseRepo = models.Repo{
|
||||
FullName: event.Project.PathWithNamespace,
|
||||
Name: name,
|
||||
SanitizedCloneURL: event.Project.GitHTTPURL,
|
||||
Owner: owner,
|
||||
CloneURL: e.addGitlabAuth(event.Project.GitHTTPURL),
|
||||
func (e *EventParser) ParseGitlabMergeCommentEvent(event gitlab.MergeCommentEvent) (baseRepo models.Repo, headRepo models.Repo, user models.User, err error) {
|
||||
// Parse the base repo first.
|
||||
repoFullName := event.Project.PathWithNamespace
|
||||
cloneURL := event.Project.GitHTTPURL
|
||||
baseRepo, err = models.NewRepo(repoFullName, cloneURL, e.GitlabUser, e.GitlabToken)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
user = models.User{
|
||||
Username: event.User.Username,
|
||||
}
|
||||
owner, name = e.getOwnerAndName(event.MergeRequest.Source.PathWithNamespace)
|
||||
headRepo = models.Repo{
|
||||
FullName: event.MergeRequest.Source.PathWithNamespace,
|
||||
Name: name,
|
||||
SanitizedCloneURL: event.MergeRequest.Source.GitHTTPURL,
|
||||
Owner: owner,
|
||||
CloneURL: e.addGitlabAuth(event.MergeRequest.Source.GitHTTPURL),
|
||||
}
|
||||
|
||||
// Now parse the head repo.
|
||||
headRepoFullName := event.MergeRequest.Source.PathWithNamespace
|
||||
headCloneURL := event.MergeRequest.Source.GitHTTPURL
|
||||
headRepo, err = models.NewRepo(headRepoFullName, headCloneURL, e.GitlabUser, e.GitlabToken)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package events_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-github/github"
|
||||
@@ -22,38 +21,16 @@ var parser = events.EventParser{
|
||||
}
|
||||
|
||||
func TestParseGithubRepo(t *testing.T) {
|
||||
testRepo := Repo
|
||||
testRepo.FullName = nil
|
||||
_, err := parser.ParseGithubRepo(&testRepo)
|
||||
Equals(t, errors.New("repository.full_name is null"), err)
|
||||
|
||||
testRepo = Repo
|
||||
testRepo.Owner = nil
|
||||
_, err = parser.ParseGithubRepo(&testRepo)
|
||||
Equals(t, errors.New("repository.owner.login is null"), err)
|
||||
|
||||
testRepo = Repo
|
||||
testRepo.Name = nil
|
||||
_, err = parser.ParseGithubRepo(&testRepo)
|
||||
Equals(t, errors.New("repository.name is null"), err)
|
||||
|
||||
testRepo = Repo
|
||||
testRepo.CloneURL = nil
|
||||
_, err = parser.ParseGithubRepo(&testRepo)
|
||||
Equals(t, errors.New("repository.clone_url is null"), err)
|
||||
|
||||
t.Log("should replace https clone with user/pass")
|
||||
{
|
||||
r, err := parser.ParseGithubRepo(&Repo)
|
||||
Ok(t, err)
|
||||
Equals(t, models.Repo{
|
||||
Owner: "owner",
|
||||
FullName: "owner/repo",
|
||||
CloneURL: "https://github-user:github-token@github.com/lkysow/atlantis-example.git",
|
||||
SanitizedCloneURL: Repo.GetCloneURL(),
|
||||
Name: "repo",
|
||||
}, r)
|
||||
}
|
||||
r, err := parser.ParseGithubRepo(&Repo)
|
||||
Ok(t, err)
|
||||
Equals(t, models.Repo{
|
||||
Owner: "owner",
|
||||
FullName: "owner/repo",
|
||||
CloneURL: "https://github-user:github-token@github.com/owner/repo.git",
|
||||
SanitizedCloneURL: Repo.GetCloneURL(),
|
||||
Name: "repo",
|
||||
Hostname: "github.com",
|
||||
}, r)
|
||||
}
|
||||
|
||||
func TestParseGithubIssueCommentEvent(t *testing.T) {
|
||||
@@ -68,30 +45,26 @@ func TestParseGithubIssueCommentEvent(t *testing.T) {
|
||||
User: &github.User{Login: github.String("comment_user")},
|
||||
},
|
||||
}
|
||||
testComment := deepcopy.Copy(comment).(github.IssueCommentEvent)
|
||||
testComment.Repo = nil
|
||||
_, _, _, err := parser.ParseGithubIssueCommentEvent(&testComment)
|
||||
Equals(t, errors.New("repository.full_name is null"), err)
|
||||
|
||||
testComment = deepcopy.Copy(comment).(github.IssueCommentEvent)
|
||||
testComment := deepcopy.Copy(comment).(github.IssueCommentEvent)
|
||||
testComment.Comment = nil
|
||||
_, _, _, err = parser.ParseGithubIssueCommentEvent(&testComment)
|
||||
Equals(t, errors.New("comment.user.login is null"), err)
|
||||
_, _, _, err := parser.ParseGithubIssueCommentEvent(&testComment)
|
||||
ErrEquals(t, "comment.user.login is null", err)
|
||||
|
||||
testComment = deepcopy.Copy(comment).(github.IssueCommentEvent)
|
||||
testComment.Comment.User = nil
|
||||
_, _, _, err = parser.ParseGithubIssueCommentEvent(&testComment)
|
||||
Equals(t, errors.New("comment.user.login is null"), err)
|
||||
ErrEquals(t, "comment.user.login is null", err)
|
||||
|
||||
testComment = deepcopy.Copy(comment).(github.IssueCommentEvent)
|
||||
testComment.Comment.User.Login = nil
|
||||
_, _, _, err = parser.ParseGithubIssueCommentEvent(&testComment)
|
||||
Equals(t, errors.New("comment.user.login is null"), err)
|
||||
ErrEquals(t, "comment.user.login is null", err)
|
||||
|
||||
testComment = deepcopy.Copy(comment).(github.IssueCommentEvent)
|
||||
testComment.Issue = nil
|
||||
_, _, _, err = parser.ParseGithubIssueCommentEvent(&testComment)
|
||||
Equals(t, errors.New("issue.number is null"), err)
|
||||
ErrEquals(t, "issue.number is null", err)
|
||||
|
||||
// this should be successful
|
||||
repo, user, pullNum, err := parser.ParseGithubIssueCommentEvent(&comment)
|
||||
@@ -99,9 +72,10 @@ func TestParseGithubIssueCommentEvent(t *testing.T) {
|
||||
Equals(t, models.Repo{
|
||||
Owner: *comment.Repo.Owner.Login,
|
||||
FullName: *comment.Repo.FullName,
|
||||
CloneURL: "https://github-user:github-token@github.com/lkysow/atlantis-example.git",
|
||||
CloneURL: "https://github-user:github-token@github.com/owner/repo.git",
|
||||
SanitizedCloneURL: *comment.Repo.CloneURL,
|
||||
Name: "repo",
|
||||
Hostname: "github.com",
|
||||
}, repo)
|
||||
Equals(t, models.User{
|
||||
Username: *comment.Comment.User.Login,
|
||||
@@ -113,32 +87,27 @@ func TestParseGithubPull(t *testing.T) {
|
||||
testPull := deepcopy.Copy(Pull).(github.PullRequest)
|
||||
testPull.Head.SHA = nil
|
||||
_, _, err := parser.ParseGithubPull(&testPull)
|
||||
Equals(t, errors.New("head.sha is null"), err)
|
||||
ErrEquals(t, "head.sha is null", err)
|
||||
|
||||
testPull = deepcopy.Copy(Pull).(github.PullRequest)
|
||||
testPull.HTMLURL = nil
|
||||
_, _, err = parser.ParseGithubPull(&testPull)
|
||||
Equals(t, errors.New("html_url is null"), err)
|
||||
ErrEquals(t, "html_url is null", err)
|
||||
|
||||
testPull = deepcopy.Copy(Pull).(github.PullRequest)
|
||||
testPull.Head.Ref = nil
|
||||
_, _, err = parser.ParseGithubPull(&testPull)
|
||||
Equals(t, errors.New("head.ref is null"), err)
|
||||
ErrEquals(t, "head.ref is null", err)
|
||||
|
||||
testPull = deepcopy.Copy(Pull).(github.PullRequest)
|
||||
testPull.User.Login = nil
|
||||
_, _, err = parser.ParseGithubPull(&testPull)
|
||||
Equals(t, errors.New("user.login is null"), err)
|
||||
ErrEquals(t, "user.login is null", err)
|
||||
|
||||
testPull = deepcopy.Copy(Pull).(github.PullRequest)
|
||||
testPull.Number = nil
|
||||
_, _, err = parser.ParseGithubPull(&testPull)
|
||||
Equals(t, errors.New("number is null"), err)
|
||||
|
||||
testPull = deepcopy.Copy(Pull).(github.PullRequest)
|
||||
testPull.Head.Repo = nil
|
||||
_, _, err = parser.ParseGithubPull(&testPull)
|
||||
Equals(t, errors.New("repository.full_name is null"), err)
|
||||
ErrEquals(t, "number is null", err)
|
||||
|
||||
pullRes, repoRes, err := parser.ParseGithubPull(&Pull)
|
||||
Ok(t, err)
|
||||
@@ -154,9 +123,10 @@ func TestParseGithubPull(t *testing.T) {
|
||||
Equals(t, models.Repo{
|
||||
Owner: "owner",
|
||||
FullName: "owner/repo",
|
||||
CloneURL: "https://github-user:github-token@github.com/lkysow/atlantis-example.git",
|
||||
CloneURL: "https://github-user:github-token@github.com/owner/repo.git",
|
||||
SanitizedCloneURL: Repo.GetCloneURL(),
|
||||
Name: "repo",
|
||||
Hostname: "github.com",
|
||||
}, repoRes)
|
||||
}
|
||||
|
||||
@@ -165,7 +135,8 @@ func TestParseGitlabMergeEvent(t *testing.T) {
|
||||
var event *gitlab.MergeEvent
|
||||
err := json.Unmarshal([]byte(mergeEventJSON), &event)
|
||||
Ok(t, err)
|
||||
pull, repo := parser.ParseGitlabMergeEvent(*event)
|
||||
pull, repo, err := parser.ParseGitlabMergeEvent(*event)
|
||||
Ok(t, err)
|
||||
Equals(t, models.PullRequest{
|
||||
URL: "http://example.com/diaspora/merge_requests/1",
|
||||
Author: "root",
|
||||
@@ -181,11 +152,13 @@ func TestParseGitlabMergeEvent(t *testing.T) {
|
||||
SanitizedCloneURL: "https://example.com/gitlabhq/gitlab-test.git",
|
||||
Owner: "gitlabhq",
|
||||
CloneURL: "https://gitlab-user:gitlab-token@example.com/gitlabhq/gitlab-test.git",
|
||||
Hostname: "example.com",
|
||||
}, repo)
|
||||
|
||||
t.Log("If the state is closed, should set field correctly.")
|
||||
event.ObjectAttributes.State = "closed"
|
||||
pull, _ = parser.ParseGitlabMergeEvent(*event)
|
||||
pull, _, err = parser.ParseGitlabMergeEvent(*event)
|
||||
Ok(t, err)
|
||||
Equals(t, models.Closed, pull.State)
|
||||
}
|
||||
|
||||
@@ -215,13 +188,15 @@ func TestParseGitlabMergeCommentEvent(t *testing.T) {
|
||||
var event *gitlab.MergeCommentEvent
|
||||
err := json.Unmarshal([]byte(mergeCommentEventJSON), &event)
|
||||
Ok(t, err)
|
||||
baseRepo, headRepo, user := parser.ParseGitlabMergeCommentEvent(*event)
|
||||
baseRepo, headRepo, user, err := parser.ParseGitlabMergeCommentEvent(*event)
|
||||
Ok(t, err)
|
||||
Equals(t, models.Repo{
|
||||
FullName: "gitlabhq/gitlab-test",
|
||||
Name: "gitlab-test",
|
||||
SanitizedCloneURL: "https://example.com/gitlabhq/gitlab-test.git",
|
||||
Owner: "gitlabhq",
|
||||
CloneURL: "https://gitlab-user:gitlab-token@example.com/gitlabhq/gitlab-test.git",
|
||||
Hostname: "example.com",
|
||||
}, baseRepo)
|
||||
Equals(t, models.Repo{
|
||||
FullName: "gitlab-org/gitlab-test",
|
||||
@@ -229,6 +204,7 @@ func TestParseGitlabMergeCommentEvent(t *testing.T) {
|
||||
SanitizedCloneURL: "https://example.com/gitlab-org/gitlab-test.git",
|
||||
Owner: "gitlab-org",
|
||||
CloneURL: "https://gitlab-user:gitlab-token@example.com/gitlab-org/gitlab-test.git",
|
||||
Hostname: "example.com",
|
||||
}, headRepo)
|
||||
Equals(t, models.User{
|
||||
Username: "root",
|
||||
|
||||
@@ -80,11 +80,12 @@ func (mock *MockEventParsing) ParseGithubRepo(ghRepo *github.Repository) (models
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
func (mock *MockEventParsing) ParseGitlabMergeEvent(event go_gitlab.MergeEvent) (models.PullRequest, models.Repo) {
|
||||
func (mock *MockEventParsing) ParseGitlabMergeEvent(event go_gitlab.MergeEvent) (models.PullRequest, models.Repo, error) {
|
||||
params := []pegomock.Param{event}
|
||||
result := pegomock.GetGenericMockFrom(mock).Invoke("ParseGitlabMergeEvent", params, []reflect.Type{reflect.TypeOf((*models.PullRequest)(nil)).Elem(), reflect.TypeOf((*models.Repo)(nil)).Elem()})
|
||||
result := pegomock.GetGenericMockFrom(mock).Invoke("ParseGitlabMergeEvent", params, []reflect.Type{reflect.TypeOf((*models.PullRequest)(nil)).Elem(), reflect.TypeOf((*models.Repo)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
|
||||
var ret0 models.PullRequest
|
||||
var ret1 models.Repo
|
||||
var ret2 error
|
||||
if len(result) != 0 {
|
||||
if result[0] != nil {
|
||||
ret0 = result[0].(models.PullRequest)
|
||||
@@ -92,16 +93,20 @@ func (mock *MockEventParsing) ParseGitlabMergeEvent(event go_gitlab.MergeEvent)
|
||||
if result[1] != nil {
|
||||
ret1 = result[1].(models.Repo)
|
||||
}
|
||||
if result[2] != nil {
|
||||
ret2 = result[2].(error)
|
||||
}
|
||||
}
|
||||
return ret0, ret1
|
||||
return ret0, ret1, ret2
|
||||
}
|
||||
|
||||
func (mock *MockEventParsing) ParseGitlabMergeCommentEvent(event go_gitlab.MergeCommentEvent) (models.Repo, models.Repo, models.User) {
|
||||
func (mock *MockEventParsing) ParseGitlabMergeCommentEvent(event go_gitlab.MergeCommentEvent) (models.Repo, models.Repo, models.User, error) {
|
||||
params := []pegomock.Param{event}
|
||||
result := pegomock.GetGenericMockFrom(mock).Invoke("ParseGitlabMergeCommentEvent", params, []reflect.Type{reflect.TypeOf((*models.Repo)(nil)).Elem(), reflect.TypeOf((*models.Repo)(nil)).Elem(), reflect.TypeOf((*models.User)(nil)).Elem()})
|
||||
result := pegomock.GetGenericMockFrom(mock).Invoke("ParseGitlabMergeCommentEvent", params, []reflect.Type{reflect.TypeOf((*models.Repo)(nil)).Elem(), reflect.TypeOf((*models.Repo)(nil)).Elem(), reflect.TypeOf((*models.User)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
|
||||
var ret0 models.Repo
|
||||
var ret1 models.Repo
|
||||
var ret2 models.User
|
||||
var ret3 error
|
||||
if len(result) != 0 {
|
||||
if result[0] != nil {
|
||||
ret0 = result[0].(models.Repo)
|
||||
@@ -112,8 +117,11 @@ func (mock *MockEventParsing) ParseGitlabMergeCommentEvent(event go_gitlab.Merge
|
||||
if result[2] != nil {
|
||||
ret2 = result[2].(models.User)
|
||||
}
|
||||
if result[3] != nil {
|
||||
ret3 = result[3].(error)
|
||||
}
|
||||
}
|
||||
return ret0, ret1, ret2
|
||||
return ret0, ret1, ret2, ret3
|
||||
}
|
||||
|
||||
func (mock *MockEventParsing) ParseGitlabMergeRequest(mr *go_gitlab.MergeRequest) models.PullRequest {
|
||||
|
||||
@@ -4,8 +4,13 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
paths "path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Repo is a VCS repository.
|
||||
@@ -23,6 +28,52 @@ type Repo struct {
|
||||
// SanitizedCloneURL is the full HTTPS url for cloning without the username and password.
|
||||
// ex. "https://github.com/atlantis/atlantis.git".
|
||||
SanitizedCloneURL string
|
||||
// Hostname of the VCS provider this repo is hosted on.
|
||||
Hostname string
|
||||
}
|
||||
|
||||
func NewRepo(repoFullName string, cloneURL string, vcsUser string, vcsToken string) (Repo, error) {
|
||||
if repoFullName == "" {
|
||||
return Repo{}, errors.New("repoFullName can't be empty")
|
||||
}
|
||||
if cloneURL == "" {
|
||||
return Repo{}, errors.New("cloneURL can't be empty")
|
||||
}
|
||||
|
||||
// Ensure the Clone URL is for the same repo to avoid something malicious.
|
||||
cloneURLParsed, err := url.Parse(cloneURL)
|
||||
if err != nil {
|
||||
return Repo{}, errors.Wrap(err, "invalid clone url")
|
||||
}
|
||||
expClonePath := fmt.Sprintf("/%s.git", repoFullName)
|
||||
if expClonePath != cloneURLParsed.Path {
|
||||
return Repo{}, fmt.Errorf("expected clone url to have path %q but had %q", expClonePath, cloneURLParsed.Path)
|
||||
}
|
||||
|
||||
// Construct clone urls with http auth. Need to do both https and http
|
||||
// because in GitLab's docs they have some http urls.
|
||||
auth := fmt.Sprintf("%s:%s@", vcsUser, vcsToken)
|
||||
authedCloneURL := strings.Replace(cloneURL, "https://", "https://"+auth, -1)
|
||||
authedCloneURL = strings.Replace(authedCloneURL, "http://", "http://"+auth, -1)
|
||||
|
||||
// Get the owner and repo names from the full name.
|
||||
var owner string
|
||||
var repo string
|
||||
pathSplit := strings.Split(repoFullName, "/")
|
||||
if len(pathSplit) != 2 || pathSplit[0] == "" || pathSplit[1] == "" {
|
||||
return Repo{}, fmt.Errorf("invalid repo format %q", repoFullName)
|
||||
}
|
||||
owner = pathSplit[0]
|
||||
repo = pathSplit[1]
|
||||
|
||||
return Repo{
|
||||
FullName: repoFullName,
|
||||
Owner: owner,
|
||||
Name: repo,
|
||||
CloneURL: authedCloneURL,
|
||||
SanitizedCloneURL: cloneURL,
|
||||
Hostname: cloneURLParsed.Hostname(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// PullRequest is a VCS pull request.
|
||||
|
||||
76
server/events/models/models_test.go
Normal file
76
server/events/models/models_test.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package models_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"fmt"
|
||||
|
||||
"github.com/runatlantis/atlantis/server/events/models"
|
||||
. "github.com/runatlantis/atlantis/testing"
|
||||
)
|
||||
|
||||
func TestNewRepo_EmptyRepoFullName(t *testing.T) {
|
||||
_, err := models.NewRepo("", "https://github.com/notowner/repo.git", "u", "p")
|
||||
ErrEquals(t, "repoFullName can't be empty", err)
|
||||
}
|
||||
|
||||
func TestNewRepo_EmptyCloneURL(t *testing.T) {
|
||||
_, err := models.NewRepo("owner/repo", "", "u", "p")
|
||||
ErrEquals(t, "cloneURL can't be empty", err)
|
||||
}
|
||||
|
||||
func TestNewRepo_InvalidCloneURL(t *testing.T) {
|
||||
_, err := models.NewRepo("owner/repo", ":", "u", "p")
|
||||
ErrEquals(t, "invalid clone url: parse :: missing protocol scheme", err)
|
||||
}
|
||||
|
||||
func TestNewRepo_CloneURLWrongRepo(t *testing.T) {
|
||||
_, err := models.NewRepo("owner/repo", "https://github.com/notowner/repo.git", "u", "p")
|
||||
ErrEquals(t, `expected clone url to have path "/owner/repo.git" but had "/notowner/repo.git"`, err)
|
||||
}
|
||||
|
||||
func TestNewRepo_FullNameWrongFormat(t *testing.T) {
|
||||
cases := []string{
|
||||
"owner/repo/extra",
|
||||
"/",
|
||||
"//",
|
||||
"///",
|
||||
"a/",
|
||||
"/b",
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c, func(t *testing.T) {
|
||||
cloneURL := fmt.Sprintf("https://github.com/%s.git", c)
|
||||
_, err := models.NewRepo(c, cloneURL, "u", "p")
|
||||
ErrEquals(t, fmt.Sprintf(`invalid repo format "%s"`, c), err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewRepo_HTTPAuth(t *testing.T) {
|
||||
// When the url has http the auth should be added.
|
||||
repo, err := models.NewRepo("owner/repo", "http://github.com/owner/repo.git", "u", "p")
|
||||
Ok(t, err)
|
||||
Equals(t, models.Repo{
|
||||
Hostname: "github.com",
|
||||
SanitizedCloneURL: "http://github.com/owner/repo.git",
|
||||
CloneURL: "http://u:p@github.com/owner/repo.git",
|
||||
FullName: "owner/repo",
|
||||
Owner: "owner",
|
||||
Name: "repo",
|
||||
}, repo)
|
||||
}
|
||||
|
||||
func TestNewRepo_HTTPSAuth(t *testing.T) {
|
||||
// When the url has https the auth should be added.
|
||||
repo, err := models.NewRepo("owner/repo", "https://github.com/owner/repo.git", "u", "p")
|
||||
Ok(t, err)
|
||||
Equals(t, models.Repo{
|
||||
Hostname: "github.com",
|
||||
SanitizedCloneURL: "https://github.com/owner/repo.git",
|
||||
CloneURL: "https://u:p@github.com/owner/repo.git",
|
||||
FullName: "owner/repo",
|
||||
Owner: "owner",
|
||||
Name: "repo",
|
||||
}, repo)
|
||||
}
|
||||
Reference in New Issue
Block a user