diff --git a/server/events/event_parser.go b/server/events/event_parser.go index 3aa1e4675..c552309c2 100644 --- a/server/events/event_parser.go +++ b/server/events/event_parser.go @@ -414,9 +414,9 @@ func (e *EventParser) ParseGitlabMergeCommentEvent(event gitlab.MergeCommentEven } // ParseGitlabMergeRequest parses the merge requests and returns a pull request -// model. We require passing in baseRepo because although can't get this information -// from the merge request, the only caller of this function already has that -// data. This means we can construct the pull request object correctly. +// model. We require passing in baseRepo because we can't get this information +// from the merge request. The only caller of this function already has that +// data so we can construct the pull request object correctly. func (e *EventParser) ParseGitlabMergeRequest(mr *gitlab.MergeRequest, baseRepo models.Repo) models.PullRequest { pullState := models.ClosedPullState if mr.State == gitlabPullOpened { diff --git a/server/events/event_parser_test.go b/server/events/event_parser_test.go index 531d2c959..36f6a3825 100644 --- a/server/events/event_parser_test.go +++ b/server/events/event_parser_test.go @@ -268,8 +268,11 @@ func TestParseGithubPull(t *testing.T) { func TestParseGitlabMergeEvent(t *testing.T) { t.Log("should properly parse a gitlab merge event") + path := filepath.Join("testdata", "gitlab-merge-request-event.json") + bytes, err := ioutil.ReadFile(path) + Ok(t, err) var event *gitlab.MergeEvent - err := json.Unmarshal([]byte(mergeEventJSON), &event) + err = json.Unmarshal(bytes, &event) Ok(t, err) pull, evType, actBaseRepo, actHeadRepo, actUser, err := parser.ParseGitlabMergeEvent(*event) Ok(t, err) @@ -318,6 +321,56 @@ func TestParseGitlabMergeEvent(t *testing.T) { Equals(t, models.ClosedPullState, pull.State) } +// Should be able to parse a merge event from a repo that is in a subgroup, +// i.e. instead of under an owner/repo it's under an owner/group/subgroup/repo. +func TestParseGitlabMergeEvent_Subgroup(t *testing.T) { + path := filepath.Join("testdata", "gitlab-merge-request-event-subgroup.json") + bytes, err := ioutil.ReadFile(path) + Ok(t, err) + var event *gitlab.MergeEvent + err = json.Unmarshal(bytes, &event) + Ok(t, err) + pull, evType, actBaseRepo, actHeadRepo, actUser, err := parser.ParseGitlabMergeEvent(*event) + Ok(t, err) + + expBaseRepo := models.Repo{ + FullName: "lkysow-test/subgroup/sub-subgroup/atlantis-example", + Name: "atlantis-example", + SanitizedCloneURL: "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + Owner: "lkysow-test/subgroup/sub-subgroup", + CloneURL: "https://gitlab-user:gitlab-token@gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + VCSHost: models.VCSHost{ + Hostname: "gitlab.com", + Type: models.Gitlab, + }, + } + + Equals(t, models.PullRequest{ + URL: "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example/merge_requests/2", + Author: "lkysow", + Num: 2, + HeadCommit: "901d9770ef1a6862e2a73ec1bacc73590abb9aff", + Branch: "patch", + State: models.OpenPullState, + BaseRepo: expBaseRepo, + }, pull) + Equals(t, models.OpenedPullEvent, evType) + + Equals(t, expBaseRepo, actBaseRepo) + Equals(t, models.Repo{ + FullName: "lkysow-test/subgroup/sub-subgroup/atlantis-example", + Name: "atlantis-example", + SanitizedCloneURL: "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + Owner: "lkysow-test/subgroup/sub-subgroup", + CloneURL: "https://gitlab-user:gitlab-token@gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + VCSHost: models.VCSHost{ + Hostname: "gitlab.com", + Type: models.Gitlab, + }, + }, actHeadRepo) + Equals(t, models.User{Username: "lkysow"}, actUser) +} + func TestParseGitlabMergeEvent_ActionType(t *testing.T) { cases := []struct { action string @@ -345,9 +398,16 @@ func TestParseGitlabMergeEvent_ActionType(t *testing.T) { }, } + path := filepath.Join("testdata", "gitlab-merge-request-event.json") + bytes, err := ioutil.ReadFile(path) + Ok(t, err) + mergeEventJSON := string(bytes) + for _, c := range cases { t.Run(c.action, func(t *testing.T) { var event *gitlab.MergeEvent + err = json.Unmarshal(bytes, &event) + Ok(t, err) eventJSON := strings.Replace(mergeEventJSON, `"action": "open"`, fmt.Sprintf(`"action": %q`, c.action), 1) err := json.Unmarshal([]byte(eventJSON), &event) Ok(t, err) @@ -360,8 +420,13 @@ func TestParseGitlabMergeEvent_ActionType(t *testing.T) { func TestParseGitlabMergeRequest(t *testing.T) { t.Log("should properly parse a gitlab merge request") + path := filepath.Join("testdata", "gitlab-get-merge-request.json") + bytes, err := ioutil.ReadFile(path) + if err != nil { + Ok(t, err) + } var event *gitlab.MergeRequest - err := json.Unmarshal([]byte(mergeRequestJSON), &event) + err = json.Unmarshal(bytes, &event) Ok(t, err) repo := models.Repo{ FullName: "gitlabhq/gitlab-test", @@ -391,10 +456,46 @@ func TestParseGitlabMergeRequest(t *testing.T) { Equals(t, models.ClosedPullState, pull.State) } +func TestParseGitlabMergeRequest_Subgroup(t *testing.T) { + path := filepath.Join("testdata", "gitlab-get-merge-request-subgroup.json") + bytes, err := ioutil.ReadFile(path) + if err != nil { + Ok(t, err) + } + var event *gitlab.MergeRequest + err = json.Unmarshal(bytes, &event) + Ok(t, err) + + repo := models.Repo{ + FullName: "lkysow-test/subgroup/sub-subgroup/atlantis-example", + Name: "atlantis-example", + SanitizedCloneURL: "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + Owner: "lkysow-test/subgroup/sub-subgroup", + CloneURL: "https://gitlab-user:gitlab-token@gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + VCSHost: models.VCSHost{ + Hostname: "gitlab.com", + Type: models.Gitlab, + }, + } + pull := parser.ParseGitlabMergeRequest(event, repo) + Equals(t, models.PullRequest{ + URL: "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example/merge_requests/2", + Author: "lkysow", + Num: 2, + HeadCommit: "901d9770ef1a6862e2a73ec1bacc73590abb9aff", + Branch: "patch", + State: models.OpenPullState, + BaseRepo: repo, + }, pull) +} + func TestParseGitlabMergeCommentEvent(t *testing.T) { t.Log("should properly parse a gitlab merge comment event") + path := filepath.Join("testdata", "gitlab-merge-request-comment-event.json") + bytes, err := ioutil.ReadFile(path) + Ok(t, err) var event *gitlab.MergeCommentEvent - err := json.Unmarshal([]byte(mergeCommentEventJSON), &event) + err = json.Unmarshal(bytes, &event) Ok(t, err) baseRepo, headRepo, user, err := parser.ParseGitlabMergeCommentEvent(*event) Ok(t, err) @@ -425,6 +526,44 @@ func TestParseGitlabMergeCommentEvent(t *testing.T) { }, user) } +// Should properly parse a gitlab merge comment event from a subgroup repo. +func TestParseGitlabMergeCommentEvent_Subgroup(t *testing.T) { + path := filepath.Join("testdata", "gitlab-merge-request-comment-event-subgroup.json") + bytes, err := ioutil.ReadFile(path) + Ok(t, err) + var event *gitlab.MergeCommentEvent + err = json.Unmarshal(bytes, &event) + Ok(t, err) + baseRepo, headRepo, user, err := parser.ParseGitlabMergeCommentEvent(*event) + Ok(t, err) + + Equals(t, models.Repo{ + FullName: "lkysow-test/subgroup/sub-subgroup/atlantis-example", + Name: "atlantis-example", + SanitizedCloneURL: "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + Owner: "lkysow-test/subgroup/sub-subgroup", + CloneURL: "https://gitlab-user:gitlab-token@gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + VCSHost: models.VCSHost{ + Hostname: "gitlab.com", + Type: models.Gitlab, + }, + }, baseRepo) + Equals(t, models.Repo{ + FullName: "lkysow-test/subgroup/sub-subgroup/atlantis-example", + Name: "atlantis-example", + SanitizedCloneURL: "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + Owner: "lkysow-test/subgroup/sub-subgroup", + CloneURL: "https://gitlab-user:gitlab-token@gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + VCSHost: models.VCSHost{ + Hostname: "gitlab.com", + Type: models.Gitlab, + }, + }, headRepo) + Equals(t, models.User{ + Username: "lkysow", + }, user) +} + func TestNewCommand_CleansDir(t *testing.T) { cases := []struct { RepoRelDir string @@ -540,9 +679,7 @@ func TestParseBitbucketCloudCommentEvent_EmptyObject(t *testing.T) { func TestParseBitbucketCloudCommentEvent_CommitHashMissing(t *testing.T) { path := filepath.Join("testdata", "bitbucket-cloud-comment-event.json") bytes, err := ioutil.ReadFile(path) - if err != nil { - Ok(t, err) - } + Ok(t, err) emptyCommitHash := strings.Replace(string(bytes), ` "hash": "e0624da46d3a",`, "", -1) _, _, _, _, _, err = parser.ParseBitbucketCloudCommentEvent([]byte(emptyCommitHash)) ErrContains(t, "Key: 'CommentEvent.CommonEventData.PullRequest.Source.Commit.Hash' Error:Field validation for 'Hash' failed on the 'required' tag", err) @@ -551,9 +688,7 @@ func TestParseBitbucketCloudCommentEvent_CommitHashMissing(t *testing.T) { func TestParseBitbucketCloudCommentEvent_ValidEvent(t *testing.T) { path := filepath.Join("testdata", "bitbucket-cloud-comment-event.json") bytes, err := ioutil.ReadFile(path) - if err != nil { - Ok(t, err) - } + Ok(t, err) pull, baseRepo, headRepo, user, comment, err := parser.ParseBitbucketCloudCommentEvent(bytes) Ok(t, err) expBaseRepo := models.Repo{ @@ -888,310 +1023,3 @@ func TestGetBitbucketServerEventType(t *testing.T) { }) } } - -var mergeEventJSON = `{ - "object_kind": "merge_request", - "user": { - "name": "Administrator", - "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" - }, - "project": { - "id": 1, - "name":"Gitlab Test", - "description":"Aut reprehenderit ut est.", - "web_url":"http://example.com/gitlabhq/gitlab-test", - "avatar_url":null, - "git_ssh_url":"git@example.com:gitlabhq/gitlab-test.git", - "git_http_url":"https://example.com/gitlabhq/gitlab-test.git", - "namespace":"GitlabHQ", - "visibility_level":20, - "path_with_namespace":"gitlabhq/gitlab-test", - "default_branch":"master", - "homepage":"http://example.com/gitlabhq/gitlab-test", - "url":"https://example.com/gitlabhq/gitlab-test.git", - "ssh_url":"git@example.com:gitlabhq/gitlab-test.git", - "http_url":"https://example.com/gitlabhq/gitlab-test.git" - }, - "repository": { - "name": "Gitlab Test", - "url": "https://example.com/gitlabhq/gitlab-test.git", - "description": "Aut reprehenderit ut est.", - "homepage": "http://example.com/gitlabhq/gitlab-test" - }, - "object_attributes": { - "id": 99, - "target_branch": "master", - "source_branch": "ms-viewport", - "source_project_id": 14, - "author_id": 51, - "assignee_id": 6, - "title": "MS-Viewport", - "created_at": "2013-12-03T17:23:34Z", - "updated_at": "2013-12-03T17:23:34Z", - "st_commits": null, - "st_diffs": null, - "milestone_id": null, - "state": "opened", - "merge_status": "unchecked", - "target_project_id": 14, - "iid": 1, - "description": "", - "source": { - "name":"Awesome Project", - "description":"Aut reprehenderit ut est.", - "web_url":"http://example.com/awesome_space/awesome_project", - "avatar_url":null, - "git_ssh_url":"git@example.com:awesome_space/awesome_project.git", - "git_http_url":"http://example.com/awesome_space/awesome_project.git", - "namespace":"Awesome Space", - "visibility_level":20, - "path_with_namespace":"awesome_space/awesome_project", - "default_branch":"master", - "homepage":"http://example.com/awesome_space/awesome_project", - "url":"http://example.com/awesome_space/awesome_project.git", - "ssh_url":"git@example.com:awesome_space/awesome_project.git", - "http_url":"http://example.com/awesome_space/awesome_project.git" - }, - "target": { - "name":"Awesome Project", - "description":"Aut reprehenderit ut est.", - "web_url":"http://example.com/awesome_space/awesome_project", - "avatar_url":null, - "git_ssh_url":"git@example.com:awesome_space/awesome_project.git", - "git_http_url":"http://example.com/awesome_space/awesome_project.git", - "namespace":"Awesome Space", - "visibility_level":20, - "path_with_namespace":"awesome_space/awesome_project", - "default_branch":"master", - "homepage":"http://example.com/awesome_space/awesome_project", - "url":"http://example.com/awesome_space/awesome_project.git", - "ssh_url":"git@example.com:awesome_space/awesome_project.git", - "http_url":"http://example.com/awesome_space/awesome_project.git" - }, - "last_commit": { - "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", - "message": "fixed readme", - "timestamp": "2012-01-03T23:36:29+02:00", - "url": "http://example.com/awesome_space/awesome_project/commits/da1560886d4f094c3e6c9ef40349f7d38b5d27d7", - "author": { - "name": "GitLab dev user", - "email": "gitlabdev@dv6700.(none)" - } - }, - "work_in_progress": false, - "url": "http://example.com/diaspora/merge_requests/1", - "action": "open", - "assignee": { - "name": "User1", - "username": "user1", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" - } - }, - "labels": [{ - "id": 206, - "title": "API", - "color": "#ffffff", - "project_id": 14, - "created_at": "2013-12-03T17:15:43Z", - "updated_at": "2013-12-03T17:15:43Z", - "template": false, - "description": "API related issues", - "type": "ProjectLabel", - "group_id": 41 - }], - "changes": { - "updated_by_id": [null, 1], - "updated_at": ["2017-09-15 16:50:55 UTC", "2017-09-15 16:52:00 UTC"], - "labels": { - "previous": [{ - "id": 206, - "title": "API", - "color": "#ffffff", - "project_id": 14, - "created_at": "2013-12-03T17:15:43Z", - "updated_at": "2013-12-03T17:15:43Z", - "template": false, - "description": "API related issues", - "type": "ProjectLabel", - "group_id": 41 - }], - "current": [{ - "id": 205, - "title": "Platform", - "color": "#123123", - "project_id": 14, - "created_at": "2013-12-03T17:15:43Z", - "updated_at": "2013-12-03T17:15:43Z", - "template": false, - "description": "Platform related issues", - "type": "ProjectLabel", - "group_id": 41 - }] - } - } -}` - -var mergeCommentEventJSON = `{ - "object_kind": "note", - "user": { - "name": "Administrator", - "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" - }, - "project_id": 5, - "project":{ - "id": 5, - "name":"Gitlab Test", - "description":"Aut reprehenderit ut est.", - "web_url":"http://example.com/gitlabhq/gitlab-test", - "avatar_url":null, - "git_ssh_url":"git@example.com:gitlabhq/gitlab-test.git", - "git_http_url":"https://example.com/gitlabhq/gitlab-test.git", - "namespace":"Gitlab Org", - "visibility_level":10, - "path_with_namespace":"gitlabhq/gitlab-test", - "default_branch":"master", - "homepage":"http://example.com/gitlabhq/gitlab-test", - "url":"https://example.com/gitlabhq/gitlab-test.git", - "ssh_url":"git@example.com:gitlabhq/gitlab-test.git", - "http_url":"https://example.com/gitlabhq/gitlab-test.git" - }, - "repository":{ - "name": "Gitlab Test", - "url": "http://localhost/gitlab-org/gitlab-test.git", - "description": "Aut reprehenderit ut est.", - "homepage": "http://example.com/gitlab-org/gitlab-test" - }, - "object_attributes": { - "id": 1244, - "note": "This MR needs work.", - "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2015-05-17", - "updated_at": "2015-05-17", - "project_id": 5, - "attachment": null, - "line_code": null, - "commit_id": "", - "noteable_id": 7, - "system": false, - "st_diff": null, - "url": "http://example.com/gitlab-org/gitlab-test/merge_requests/1#note_1244" - }, - "merge_request": { - "id": 7, - "target_branch": "markdown", - "source_branch": "master", - "source_project_id": 5, - "author_id": 8, - "assignee_id": 28, - "title": "Tempora et eos debitis quae laborum et.", - "created_at": "2015-03-01 20:12:53 UTC", - "updated_at": "2015-03-21 18:27:27 UTC", - "milestone_id": 11, - "state": "opened", - "merge_status": "cannot_be_merged", - "target_project_id": 5, - "iid": 1, - "description": "Et voluptas corrupti assumenda temporibus. Architecto cum animi eveniet amet asperiores. Vitae numquam voluptate est natus sit et ad id.", - "position": 0, - "source":{ - "name":"Gitlab Test", - "description":"Aut reprehenderit ut est.", - "web_url":"http://example.com/gitlab-org/gitlab-test", - "avatar_url":null, - "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git", - "git_http_url":"https://example.com/gitlab-org/gitlab-test.git", - "namespace":"Gitlab Org", - "visibility_level":10, - "path_with_namespace":"gitlab-org/gitlab-test", - "default_branch":"master", - "homepage":"http://example.com/gitlab-org/gitlab-test", - "url":"https://example.com/gitlab-org/gitlab-test.git", - "ssh_url":"git@example.com:gitlab-org/gitlab-test.git", - "http_url":"https://example.com/gitlab-org/gitlab-test.git", - "git_http_url":"https://example.com/gitlab-org/gitlab-test.git" - }, - "target": { - "name":"Gitlab Test", - "description":"Aut reprehenderit ut est.", - "web_url":"http://example.com/gitlabhq/gitlab-test", - "avatar_url":null, - "git_ssh_url":"git@example.com:gitlabhq/gitlab-test.git", - "git_http_url":"https://example.com/gitlabhq/gitlab-test.git", - "namespace":"Gitlab Org", - "visibility_level":10, - "path_with_namespace":"gitlabhq/gitlab-test", - "default_branch":"master", - "homepage":"http://example.com/gitlabhq/gitlab-test", - "url":"https://example.com/gitlabhq/gitlab-test.git", - "ssh_url":"git@example.com:gitlabhq/gitlab-test.git", - "http_url":"https://example.com/gitlabhq/gitlab-test.git" - }, - "last_commit": { - "id": "562e173be03b8ff2efb05345d12df18815438a4b", - "message": "Merge branch 'another-branch' into 'master'\n\nCheck in this test\n", - "timestamp": "2002-10-02T10:00:00-05:00", - "url": "http://example.com/gitlab-org/gitlab-test/commit/562e173be03b8ff2efb05345d12df18815438a4b", - "author": { - "name": "John Smith", - "email": "john@example.com" - } - }, - "work_in_progress": false, - "assignee": { - "name": "User1", - "username": "user1", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" - } - } -}` - -var mergeRequestJSON = `{ - "id":6056811, - "iid":8, - "project_id":4580910, - "title":"Update main.tf", - "description":"", - "state":"opened", - "created_at":"2017-11-13T19:33:42.704Z", - "updated_at":"2017-11-13T23:35:26.200Z", - "target_branch":"master", - "source_branch":"abc", - "upvotes":0, - "downvotes":0, - "author":{ - "id":1755902, - "name":"Luke Kysow", - "username":"lkysow", - "state":"active", - "avatar_url":"https://secure.gravatar.com/avatar/25fd57e71590fe28736624ff24d41c5f?s=80\u0026d=identicon", - "web_url":"https://gitlab.com/lkysow" - }, - "assignee":null, - "source_project_id":4580910, - "target_project_id":4580910, - "labels":[ - - ], - "work_in_progress":false, - "milestone":null, - "merge_when_pipeline_succeeds":false, - "merge_status":"can_be_merged", - "sha":"0b4ac85ea3063ad5f2974d10cd68dd1f937aaac2", - "merge_commit_sha":null, - "user_notes_count":10, - "approvals_before_merge":null, - "discussion_locked":null, - "should_remove_source_branch":null, - "force_remove_source_branch":false, - "squash":false, - "web_url":"https://gitlab.com/lkysow/atlantis-example/merge_requests/8", - "time_stats":{ - "time_estimate":0, - "total_time_spent":0, - "human_time_estimate":null, - "human_total_time_spent":null - } -}` diff --git a/server/events/models/models.go b/server/events/models/models.go index 8ea8908d3..f1c255241 100644 --- a/server/events/models/models.go +++ b/server/events/models/models.go @@ -31,11 +31,13 @@ import ( // Repo is a VCS repository. type Repo struct { // FullName is the owner and repo name separated - // by a "/", ex. "runatlantis/atlantis". + // by a "/", ex. "runatlantis/atlantis" or "gitlab/subgroup/atlantis" FullName string - // Owner is just the repo owner, ex. "runatlantis". + // Owner is just the repo owner, ex. "runatlantis" or "gitlab/subgroup". + // This may contain /'s in the case of GitLab subgroups. Owner string - // Name is just the repo name, ex. "atlantis". + // Name is just the repo name, ex. "atlantis". This will never have + // /'s in it. Name string // CloneURL is the full HTTPS url for cloning with username and token string // ex. "https://username:token@github.com/atlantis/atlantis.git". @@ -91,14 +93,18 @@ func NewRepo(vcsHostType VCSHostType, repoFullName string, cloneURL string, vcsU 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, repo := SplitRepoFullName(repoFullName) + if owner == "" || repo == "" { + return Repo{}, fmt.Errorf("invalid repo format %q, owner %q or repo %q was empty", repoFullName, owner, repo) + } + // Only GitLab repos can have /'s in their owners. This is for GitLab + // subgroups. + if strings.Contains(owner, "/") && vcsHostType != Gitlab { + return Repo{}, fmt.Errorf("invalid repo format %q, owner %q should not contain any /'s", repoFullName, owner) + } + if strings.Contains(repo, "/") { + return Repo{}, fmt.Errorf("invalid repo format %q, repo %q should not contain any /'s", repoFullName, owner) } - owner = pathSplit[0] - repo = pathSplit[1] return Repo{ FullName: repoFullName, @@ -295,3 +301,16 @@ type ProjectCommandContext struct { // this is an apply then this will be empty. ApplyCmd string } + +// SplitRepoFullName splits a repo full name up into its owner and repo name +// segments. If the repoFullName is malformed, may return empty strings +// for owner or repo. +// Ex. runatlantis/atlantis => (runatlantis, atlantis) +// gitlab/subgroup/runatlantis/atlantis => (gitlab/subgroup/runatlantis, atlantis) +func SplitRepoFullName(repoFullName string) (owner string, repo string) { + lastSlashIdx := strings.LastIndex(repoFullName, "/") + if lastSlashIdx == -1 || lastSlashIdx == len(repoFullName)-1 { + return "", "" + } + return repoFullName[:lastSlashIdx], repoFullName[lastSlashIdx+1:] +} diff --git a/server/events/models/models_test.go b/server/events/models/models_test.go index dee8b1f3f..2a070dea4 100644 --- a/server/events/models/models_test.go +++ b/server/events/models/models_test.go @@ -60,19 +60,40 @@ func TestNewRepo_CloneURLBitbucketServer(t *testing.T) { } func TestNewRepo_FullNameWrongFormat(t *testing.T) { - cases := []string{ - "owner/repo/extra", - "/", - "//", - "///", - "a/", - "/b", + cases := []struct { + repoFullName string + expErr string + }{ + { + "owner/repo/extra", + `invalid repo format "owner/repo/extra", owner "owner/repo" should not contain any /'s`, + }, + { + "/", + `invalid repo format "/", owner "" or repo "" was empty`, + }, + { + "//", + `invalid repo format "//", owner "" or repo "" was empty`, + }, + { + "///", + `invalid repo format "///", owner "" or repo "" was empty`, + }, + { + "a/", + `invalid repo format "a/", owner "" or repo "" was empty`, + }, + { + "/b", + `invalid repo format "/b", owner "" or repo "b" was empty`, + }, } for _, c := range cases { - t.Run(c, func(t *testing.T) { - cloneURL := fmt.Sprintf("https://github.com/%s.git", c) - _, err := models.NewRepo(models.Github, c, cloneURL, "u", "p") - ErrEquals(t, fmt.Sprintf(`invalid repo format "%s"`, c), err) + t.Run(c.repoFullName, func(t *testing.T) { + cloneURL := fmt.Sprintf("https://github.com/%s.git", c.repoFullName) + _, err := models.NewRepo(models.Github, c.repoFullName, cloneURL, "u", "p") + ErrEquals(t, c.expErr, err) }) } } @@ -182,3 +203,55 @@ func TestVCSHostType_ToString(t *testing.T) { }) } } + +func TestSplitRepoFullName(t *testing.T) { + cases := []struct { + input string + expOwner string + expRepo string + }{ + { + "owner/repo", + "owner", + "repo", + }, + { + "group/subgroup/owner/repo", + "group/subgroup/owner", + "repo", + }, + { + "", + "", + "", + }, + { + "/", + "", + "", + }, + { + "owner/", + "", + "", + }, + { + "/repo", + "", + "repo", + }, + { + "group/subgroup/", + "", + "", + }, + } + + for _, c := range cases { + t.Run(c.input, func(t *testing.T) { + owner, repo := models.SplitRepoFullName(c.input) + Equals(t, c.expOwner, owner) + Equals(t, c.expRepo, repo) + }) + } +} diff --git a/server/events/testdata/gitlab-get-merge-request-subgroup.json b/server/events/testdata/gitlab-get-merge-request-subgroup.json new file mode 100644 index 000000000..c1e4639fa --- /dev/null +++ b/server/events/testdata/gitlab-get-merge-request-subgroup.json @@ -0,0 +1,66 @@ +{ + "id": 15372654, + "iid": 2, + "project_id": 7804027, + "title": "Update main.tf", + "description": "", + "state": "opened", + "created_at": "2018-08-22T06:14:20.946Z", + "updated_at": "2018-08-22T06:14:20.946Z", + "target_branch": "master", + "source_branch": "patch", + "upvotes": 0, + "downvotes": 0, + "author": { + "id": 1755902, + "name": "Luke Kysow", + "username": "lkysow", + "state": "active", + "avatar_url": "https://secure.gravatar.com/avatar/25fd57e71590fe28736624ff24d41c5f?s=80\u0026d=identicon", + "web_url": "https://gitlab.com/lkysow" + }, + "assignee": null, + "source_project_id": 7804027, + "target_project_id": 7804027, + "labels": [], + "work_in_progress": false, + "milestone": null, + "merge_when_pipeline_succeeds": false, + "merge_status": "can_be_merged", + "sha": "901d9770ef1a6862e2a73ec1bacc73590abb9aff", + "merge_commit_sha": null, + "user_notes_count": 1, + "discussion_locked": null, + "should_remove_source_branch": null, + "force_remove_source_branch": false, + "web_url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example/merge_requests/2", + "time_stats": { + "time_estimate": 0, + "total_time_spent": 0, + "human_time_estimate": null, + "human_total_time_spent": null + }, + "squash": false, + "subscribed": false, + "changes_count": "1", + "merged_by": null, + "merged_at": null, + "closed_by": null, + "closed_at": null, + "latest_build_started_at": null, + "latest_build_finished_at": "2018-08-22T06:14:24.003Z", + "first_deployed_to_production_at": null, + "pipeline": { + "id": 28408568, + "sha": "901d9770ef1a6862e2a73ec1bacc73590abb9aff", + "ref": "patch", + "status": "success", + "web_url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example/pipelines/28408568" + }, + "diff_refs": { + "base_sha": "cdf3f0f8aad6abc3c4700ad6e28936a2278a309b", + "head_sha": "901d9770ef1a6862e2a73ec1bacc73590abb9aff", + "start_sha": "cdf3f0f8aad6abc3c4700ad6e28936a2278a309b" + }, + "approvals_before_merge": null +} \ No newline at end of file diff --git a/server/events/testdata/gitlab-get-merge-request.json b/server/events/testdata/gitlab-get-merge-request.json new file mode 100644 index 000000000..f7506ec04 --- /dev/null +++ b/server/events/testdata/gitlab-get-merge-request.json @@ -0,0 +1,47 @@ +{ + "id":6056811, + "iid":8, + "project_id":4580910, + "title":"Update main.tf", + "description":"", + "state":"opened", + "created_at":"2017-11-13T19:33:42.704Z", + "updated_at":"2017-11-13T23:35:26.200Z", + "target_branch":"master", + "source_branch":"abc", + "upvotes":0, + "downvotes":0, + "author":{ + "id":1755902, + "name":"Luke Kysow", + "username":"lkysow", + "state":"active", + "avatar_url":"https://secure.gravatar.com/avatar/25fd57e71590fe28736624ff24d41c5f?s=80\u0026d=identicon", + "web_url":"https://gitlab.com/lkysow" + }, + "assignee":null, + "source_project_id":4580910, + "target_project_id":4580910, + "labels":[ + + ], + "work_in_progress":false, + "milestone":null, + "merge_when_pipeline_succeeds":false, + "merge_status":"can_be_merged", + "sha":"0b4ac85ea3063ad5f2974d10cd68dd1f937aaac2", + "merge_commit_sha":null, + "user_notes_count":10, + "approvals_before_merge":null, + "discussion_locked":null, + "should_remove_source_branch":null, + "force_remove_source_branch":false, + "squash":false, + "web_url":"https://gitlab.com/lkysow/atlantis-example/merge_requests/8", + "time_stats":{ + "time_estimate":0, + "total_time_spent":0, + "human_time_estimate":null, + "human_total_time_spent":null + } +} \ No newline at end of file diff --git a/server/events/testdata/gitlab-merge-request-comment-event-subgroup.json b/server/events/testdata/gitlab-merge-request-comment-event-subgroup.json new file mode 100644 index 000000000..03aaff4c8 --- /dev/null +++ b/server/events/testdata/gitlab-merge-request-comment-event-subgroup.json @@ -0,0 +1,140 @@ +{ + "object_kind": "note", + "event_type": "note", + "user": { + "name": "Luke Kysow", + "username": "lkysow", + "avatar_url": "https://secure.gravatar.com/avatar/25fd57e71590fe28736624ff24d41c5f?s=80&d=identicon" + }, + "project_id": 7804027, + "project": { + "id": 7804027, + "name": "atlantis-example", + "description": "", + "web_url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example", + "avatar_url": null, + "git_ssh_url": "git@gitlab.com:lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "git_http_url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "namespace": "sub-subgroup", + "visibility_level": 20, + "path_with_namespace": "lkysow-test/subgroup/sub-subgroup/atlantis-example", + "default_branch": "master", + "ci_config_path": null, + "homepage": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example", + "url": "git@gitlab.com:lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "ssh_url": "git@gitlab.com:lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "http_url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example.git" + }, + "object_attributes": { + "attachment": null, + "author_id": 1755902, + "change_position": null, + "commit_id": null, + "created_at": "2018-08-22 06:14:24 UTC", + "discussion_id": "cb2e85b8972c533d83457fc2851c17969c6417d0", + "id": 96056916, + "line_code": null, + "note": "atlantis plan", + "noteable_id": 15372654, + "noteable_type": "MergeRequest", + "original_position": null, + "position": null, + "project_id": 7804027, + "resolved_at": null, + "resolved_by_id": null, + "resolved_by_push": null, + "st_diff": null, + "system": false, + "type": null, + "updated_at": "2018-08-22 06:14:24 UTC", + "updated_by_id": null, + "description": "Ran Plan in dir: `.` workspace: `default`\n\n```diff\nRefreshing Terraform state in-memory prior to plan...\nThe refreshed state will be used to calculate this plan, but will not be\npersisted to local or remote state storage.\n\n\n------------------------------------------------------------------------\n\nAn execution plan has been generated and is shown below.\nResource actions are indicated with the following symbols:\n + create\n\nTerraform will perform the following actions:\n\n+ null_resource.test\n id: \nPlan: 1 to add, 0 to change, 0 to destroy.\n\n```\n\n* :arrow_forward: To **apply** this plan, comment:\n * `atlantis apply -d .`\n* :put_litter_in_its_place: To **delete** this plan click [here](http://Lukes-Macbook-Pro.local:4141/lock?id=lkysow-test%252Fsubgroup%252Fsub-subgroup%252Fatlantis-example%252F.%252Fdefault)\n* :repeat: To **plan** this project again, comment:\n * `atlantis plan -d .`\n\n---\n* :fast_forward: To **apply** all unapplied plans, comment:\n * `atlantis apply`", + "url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example/merge_requests/2#note_96056916" + }, + "repository": { + "name": "atlantis-example", + "url": "git@gitlab.com:lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "description": "", + "homepage": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example" + }, + "merge_request": { + "assignee_id": null, + "author_id": 1755902, + "created_at": "2018-08-22 06:14:20 UTC", + "description": "", + "head_pipeline_id": 28408568, + "id": 15372654, + "iid": 2, + "last_edited_at": null, + "last_edited_by_id": null, + "merge_commit_sha": null, + "merge_error": null, + "merge_params": { + "force_remove_source_branch": "0" + }, + "merge_status": "can_be_merged", + "merge_user_id": null, + "merge_when_pipeline_succeeds": false, + "milestone_id": null, + "source_branch": "patch", + "source_project_id": 7804027, + "state": "opened", + "target_branch": "master", + "target_project_id": 7804027, + "time_estimate": 0, + "title": "Update main.tf", + "updated_at": "2018-08-22 06:14:20 UTC", + "updated_by_id": null, + "url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example/merge_requests/2", + "source": { + "id": 7804027, + "name": "atlantis-example", + "description": "", + "web_url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example", + "avatar_url": null, + "git_ssh_url": "git@gitlab.com:lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "git_http_url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "namespace": "sub-subgroup", + "visibility_level": 20, + "path_with_namespace": "lkysow-test/subgroup/sub-subgroup/atlantis-example", + "default_branch": "master", + "ci_config_path": null, + "homepage": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example", + "url": "git@gitlab.com:lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "ssh_url": "git@gitlab.com:lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "http_url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example.git" + }, + "target": { + "id": 7804027, + "name": "atlantis-example", + "description": "", + "web_url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example", + "avatar_url": null, + "git_ssh_url": "git@gitlab.com:lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "git_http_url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "namespace": "sub-subgroup", + "visibility_level": 20, + "path_with_namespace": "lkysow-test/subgroup/sub-subgroup/atlantis-example", + "default_branch": "master", + "ci_config_path": null, + "homepage": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example", + "url": "git@gitlab.com:lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "ssh_url": "git@gitlab.com:lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "http_url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example.git" + }, + "last_commit": { + "id": "901d9770ef1a6862e2a73ec1bacc73590abb9aff", + "message": "Update main.tf", + "timestamp": "2018-08-22T06:14:12Z", + "url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example/commit/901d9770ef1a6862e2a73ec1bacc73590abb9aff", + "author": { + "name": "Luke Kysow", + "email": "lkysow@gmail.com" + } + }, + "work_in_progress": false, + "total_time_spent": 0, + "human_total_time_spent": null, + "human_time_estimate": null + } +} \ No newline at end of file diff --git a/server/events/testdata/gitlab-merge-request-comment-event.json b/server/events/testdata/gitlab-merge-request-comment-event.json new file mode 100644 index 000000000..d92bc4d45 --- /dev/null +++ b/server/events/testdata/gitlab-merge-request-comment-event.json @@ -0,0 +1,115 @@ +{ + "object_kind": "note", + "user": { + "name": "Administrator", + "username": "root", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" + }, + "project_id": 5, + "project":{ + "id": 5, + "name":"Gitlab Test", + "description":"Aut reprehenderit ut est.", + "web_url":"http://example.com/gitlabhq/gitlab-test", + "avatar_url":null, + "git_ssh_url":"git@example.com:gitlabhq/gitlab-test.git", + "git_http_url":"https://example.com/gitlabhq/gitlab-test.git", + "namespace":"Gitlab Org", + "visibility_level":10, + "path_with_namespace":"gitlabhq/gitlab-test", + "default_branch":"master", + "homepage":"http://example.com/gitlabhq/gitlab-test", + "url":"https://example.com/gitlabhq/gitlab-test.git", + "ssh_url":"git@example.com:gitlabhq/gitlab-test.git", + "http_url":"https://example.com/gitlabhq/gitlab-test.git" + }, + "repository":{ + "name": "Gitlab Test", + "url": "http://localhost/gitlab-org/gitlab-test.git", + "description": "Aut reprehenderit ut est.", + "homepage": "http://example.com/gitlab-org/gitlab-test" + }, + "object_attributes": { + "id": 1244, + "note": "This MR needs work.", + "noteable_type": "MergeRequest", + "author_id": 1, + "created_at": "2015-05-17", + "updated_at": "2015-05-17", + "project_id": 5, + "attachment": null, + "line_code": null, + "commit_id": "", + "noteable_id": 7, + "system": false, + "st_diff": null, + "url": "http://example.com/gitlab-org/gitlab-test/merge_requests/1#note_1244" + }, + "merge_request": { + "id": 7, + "target_branch": "markdown", + "source_branch": "master", + "source_project_id": 5, + "author_id": 8, + "assignee_id": 28, + "title": "Tempora et eos debitis quae laborum et.", + "created_at": "2015-03-01 20:12:53 UTC", + "updated_at": "2015-03-21 18:27:27 UTC", + "milestone_id": 11, + "state": "opened", + "merge_status": "cannot_be_merged", + "target_project_id": 5, + "iid": 1, + "description": "Et voluptas corrupti assumenda temporibus. Architecto cum animi eveniet amet asperiores. Vitae numquam voluptate est natus sit et ad id.", + "position": 0, + "source":{ + "name":"Gitlab Test", + "description":"Aut reprehenderit ut est.", + "web_url":"http://example.com/gitlab-org/gitlab-test", + "avatar_url":null, + "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git", + "git_http_url":"https://example.com/gitlab-org/gitlab-test.git", + "namespace":"Gitlab Org", + "visibility_level":10, + "path_with_namespace":"gitlab-org/gitlab-test", + "default_branch":"master", + "homepage":"http://example.com/gitlab-org/gitlab-test", + "url":"https://example.com/gitlab-org/gitlab-test.git", + "ssh_url":"git@example.com:gitlab-org/gitlab-test.git", + "http_url":"https://example.com/gitlab-org/gitlab-test.git", + "git_http_url":"https://example.com/gitlab-org/gitlab-test.git" + }, + "target": { + "name":"Gitlab Test", + "description":"Aut reprehenderit ut est.", + "web_url":"http://example.com/gitlabhq/gitlab-test", + "avatar_url":null, + "git_ssh_url":"git@example.com:gitlabhq/gitlab-test.git", + "git_http_url":"https://example.com/gitlabhq/gitlab-test.git", + "namespace":"Gitlab Org", + "visibility_level":10, + "path_with_namespace":"gitlabhq/gitlab-test", + "default_branch":"master", + "homepage":"http://example.com/gitlabhq/gitlab-test", + "url":"https://example.com/gitlabhq/gitlab-test.git", + "ssh_url":"git@example.com:gitlabhq/gitlab-test.git", + "http_url":"https://example.com/gitlabhq/gitlab-test.git" + }, + "last_commit": { + "id": "562e173be03b8ff2efb05345d12df18815438a4b", + "message": "Merge branch 'another-branch' into 'master'\n\nCheck in this test\n", + "timestamp": "2002-10-02T10:00:00-05:00", + "url": "http://example.com/gitlab-org/gitlab-test/commit/562e173be03b8ff2efb05345d12df18815438a4b", + "author": { + "name": "John Smith", + "email": "john@example.com" + } + }, + "work_in_progress": false, + "assignee": { + "name": "User1", + "username": "user1", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" + } + } +} \ No newline at end of file diff --git a/server/events/testdata/gitlab-merge-request-event-subgroup.json b/server/events/testdata/gitlab-merge-request-event-subgroup.json new file mode 100644 index 000000000..80059c1f2 --- /dev/null +++ b/server/events/testdata/gitlab-merge-request-event-subgroup.json @@ -0,0 +1,123 @@ +{ + "object_kind": "merge_request", + "event_type": "merge_request", + "user": { + "name": "Luke Kysow", + "username": "lkysow", + "avatar_url": "https://secure.gravatar.com/avatar/25fd57e71590fe28736624ff24d41c5f?s=80&d=identicon" + }, + "project": { + "id": 7804027, + "name": "atlantis-example", + "description": "", + "web_url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example", + "avatar_url": null, + "git_ssh_url": "git@gitlab.com:lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "git_http_url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "namespace": "sub-subgroup", + "visibility_level": 20, + "path_with_namespace": "lkysow-test/subgroup/sub-subgroup/atlantis-example", + "default_branch": "master", + "ci_config_path": null, + "homepage": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example", + "url": "git@gitlab.com:lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "ssh_url": "git@gitlab.com:lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "http_url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example.git" + }, + "object_attributes": { + "assignee_id": null, + "author_id": 1755902, + "created_at": "2018-08-22 06:14:20 UTC", + "description": "", + "head_pipeline_id": null, + "id": 15372654, + "iid": 2, + "last_edited_at": null, + "last_edited_by_id": null, + "merge_commit_sha": null, + "merge_error": null, + "merge_params": { + "force_remove_source_branch": "0" + }, + "merge_status": "unchecked", + "merge_user_id": null, + "merge_when_pipeline_succeeds": false, + "milestone_id": null, + "source_branch": "patch", + "source_project_id": 7804027, + "state": "opened", + "target_branch": "master", + "target_project_id": 7804027, + "time_estimate": 0, + "title": "Update main.tf", + "updated_at": "2018-08-22 06:14:20 UTC", + "updated_by_id": null, + "url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example/merge_requests/2", + "source": { + "id": 7804027, + "name": "atlantis-example", + "description": "", + "web_url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example", + "avatar_url": null, + "git_ssh_url": "git@gitlab.com:lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "git_http_url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "namespace": "sub-subgroup", + "visibility_level": 20, + "path_with_namespace": "lkysow-test/subgroup/sub-subgroup/atlantis-example", + "default_branch": "master", + "ci_config_path": null, + "homepage": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example", + "url": "git@gitlab.com:lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "ssh_url": "git@gitlab.com:lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "http_url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example.git" + }, + "target": { + "id": 7804027, + "name": "atlantis-example", + "description": "", + "web_url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example", + "avatar_url": null, + "git_ssh_url": "git@gitlab.com:lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "git_http_url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "namespace": "sub-subgroup", + "visibility_level": 20, + "path_with_namespace": "lkysow-test/subgroup/sub-subgroup/atlantis-example", + "default_branch": "master", + "ci_config_path": null, + "homepage": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example", + "url": "git@gitlab.com:lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "ssh_url": "git@gitlab.com:lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "http_url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example.git" + }, + "last_commit": { + "id": "901d9770ef1a6862e2a73ec1bacc73590abb9aff", + "message": "Update main.tf", + "timestamp": "2018-08-22T06:14:12Z", + "url": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example/commit/901d9770ef1a6862e2a73ec1bacc73590abb9aff", + "author": { + "name": "Luke Kysow", + "email": "lkysow@gmail.com" + } + }, + "work_in_progress": false, + "total_time_spent": 0, + "human_total_time_spent": null, + "human_time_estimate": null, + "action": "open" + }, + "labels": [ + + ], + "changes": { + "total_time_spent": { + "previous": null, + "current": 0 + } + }, + "repository": { + "name": "atlantis-example", + "url": "git@gitlab.com:lkysow-test/subgroup/sub-subgroup/atlantis-example.git", + "description": "", + "homepage": "https://gitlab.com/lkysow-test/subgroup/sub-subgroup/atlantis-example" + } +} \ No newline at end of file diff --git a/server/events/testdata/gitlab-merge-request-event.json b/server/events/testdata/gitlab-merge-request-event.json new file mode 100644 index 000000000..934929e2d --- /dev/null +++ b/server/events/testdata/gitlab-merge-request-event.json @@ -0,0 +1,154 @@ +{ + "object_kind": "merge_request", + "user": { + "name": "Administrator", + "username": "root", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" + }, + "project": { + "id": 1, + "name": "Gitlab Test", + "description": "Aut reprehenderit ut est.", + "web_url": "http://example.com/gitlabhq/gitlab-test", + "avatar_url": null, + "git_ssh_url": "git@example.com:gitlabhq/gitlab-test.git", + "git_http_url": "https://example.com/gitlabhq/gitlab-test.git", + "namespace": "GitlabHQ", + "visibility_level": 20, + "path_with_namespace": "gitlabhq/gitlab-test", + "default_branch": "master", + "homepage": "http://example.com/gitlabhq/gitlab-test", + "url": "https://example.com/gitlabhq/gitlab-test.git", + "ssh_url": "git@example.com:gitlabhq/gitlab-test.git", + "http_url": "https://example.com/gitlabhq/gitlab-test.git" + }, + "repository": { + "name": "Gitlab Test", + "url": "https://example.com/gitlabhq/gitlab-test.git", + "description": "Aut reprehenderit ut est.", + "homepage": "http://example.com/gitlabhq/gitlab-test" + }, + "object_attributes": { + "id": 99, + "target_branch": "master", + "source_branch": "ms-viewport", + "source_project_id": 14, + "author_id": 51, + "assignee_id": 6, + "title": "MS-Viewport", + "created_at": "2013-12-03T17:23:34Z", + "updated_at": "2013-12-03T17:23:34Z", + "st_commits": null, + "st_diffs": null, + "milestone_id": null, + "state": "opened", + "merge_status": "unchecked", + "target_project_id": 14, + "iid": 1, + "description": "", + "source": { + "name": "Awesome Project", + "description": "Aut reprehenderit ut est.", + "web_url": "http://example.com/awesome_space/awesome_project", + "avatar_url": null, + "git_ssh_url": "git@example.com:awesome_space/awesome_project.git", + "git_http_url": "http://example.com/awesome_space/awesome_project.git", + "namespace": "Awesome Space", + "visibility_level": 20, + "path_with_namespace": "awesome_space/awesome_project", + "default_branch": "master", + "homepage": "http://example.com/awesome_space/awesome_project", + "url": "http://example.com/awesome_space/awesome_project.git", + "ssh_url": "git@example.com:awesome_space/awesome_project.git", + "http_url": "http://example.com/awesome_space/awesome_project.git" + }, + "target": { + "name": "Awesome Project", + "description": "Aut reprehenderit ut est.", + "web_url": "http://example.com/awesome_space/awesome_project", + "avatar_url": null, + "git_ssh_url": "git@example.com:awesome_space/awesome_project.git", + "git_http_url": "http://example.com/awesome_space/awesome_project.git", + "namespace": "Awesome Space", + "visibility_level": 20, + "path_with_namespace": "awesome_space/awesome_project", + "default_branch": "master", + "homepage": "http://example.com/awesome_space/awesome_project", + "url": "http://example.com/awesome_space/awesome_project.git", + "ssh_url": "git@example.com:awesome_space/awesome_project.git", + "http_url": "http://example.com/awesome_space/awesome_project.git" + }, + "last_commit": { + "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", + "message": "fixed readme", + "timestamp": "2012-01-03T23:36:29+02:00", + "url": "http://example.com/awesome_space/awesome_project/commits/da1560886d4f094c3e6c9ef40349f7d38b5d27d7", + "author": { + "name": "GitLab dev user", + "email": "gitlabdev@dv6700.(none)" + } + }, + "work_in_progress": false, + "url": "http://example.com/diaspora/merge_requests/1", + "action": "open", + "assignee": { + "name": "User1", + "username": "user1", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" + } + }, + "labels": [ + { + "id": 206, + "title": "API", + "color": "#ffffff", + "project_id": 14, + "created_at": "2013-12-03T17:15:43Z", + "updated_at": "2013-12-03T17:15:43Z", + "template": false, + "description": "API related issues", + "type": "ProjectLabel", + "group_id": 41 + } + ], + "changes": { + "updated_by_id": [ + null, + 1 + ], + "updated_at": [ + "2017-09-15 16:50:55 UTC", + "2017-09-15 16:52:00 UTC" + ], + "labels": { + "previous": [ + { + "id": 206, + "title": "API", + "color": "#ffffff", + "project_id": 14, + "created_at": "2013-12-03T17:15:43Z", + "updated_at": "2013-12-03T17:15:43Z", + "template": false, + "description": "API related issues", + "type": "ProjectLabel", + "group_id": 41 + } + ], + "current": [ + { + "id": 205, + "title": "Platform", + "color": "#123123", + "project_id": 14, + "created_at": "2013-12-03T17:15:43Z", + "updated_at": "2013-12-03T17:15:43Z", + "template": false, + "description": "Platform related issues", + "type": "ProjectLabel", + "group_id": 41 + } + ] + } + } +} \ No newline at end of file diff --git a/server/locks_controller.go b/server/locks_controller.go index 1ab1c48d3..8000e9984 100644 --- a/server/locks_controller.go +++ b/server/locks_controller.go @@ -4,7 +4,6 @@ import ( "fmt" "net/http" "net/url" - "strings" "github.com/gorilla/mux" "github.com/runatlantis/atlantis/server/events" @@ -48,13 +47,12 @@ func (l *LocksController) GetLock(w http.ResponseWriter, r *http.Request) { return } - // Extract the repo owner and repo name. - repo := strings.Split(lock.Project.RepoFullName, "/") + owner, repo := models.SplitRepoFullName(lock.Project.RepoFullName) viewData := LockDetailData{ LockKeyEncoded: id, LockKey: idUnencoded, - RepoOwner: repo[0], - RepoName: repo[1], + RepoOwner: owner, + RepoName: repo, PullRequestLink: lock.Pull.URL, LockedBy: lock.Pull.Author, Workspace: lock.Workspace,