From c01408e2052703e6ff8743ad3b6eef00d5008283 Mon Sep 17 00:00:00 2001 From: James Strachan Date: Wed, 2 Oct 2019 18:54:49 +0100 Subject: [PATCH] fix: add support for get PRs to bitbucket cloud --- README.md | 6 +- go.mod | 2 +- scm/driver/bitbucket/pr.go | 106 ++++++- scm/driver/bitbucket/pr_test.go | 32 +- scm/driver/bitbucket/repo.go | 1 + scm/driver/bitbucket/repo_test.go | 3 +- scm/driver/bitbucket/testdata/pulls.json | 291 ++++++++++++++++++ .../bitbucket/testdata/pulls.json.golden | 154 +++++++++ .../bitbucket/testdata/repo.json.golden | 23 +- .../bitbucket/testdata/repos.json.golden | 2 + scm/driver/bitbucket/user.go | 27 +- scm/factory/examples/pr/main.go | 1 + scm/factory/factory.go | 12 +- 13 files changed, 634 insertions(+), 26 deletions(-) create mode 100644 scm/driver/bitbucket/testdata/pulls.json create mode 100644 scm/driver/bitbucket/testdata/pulls.json.golden diff --git a/README.md b/README.md index 97726e190..7aacfaca2 100644 --- a/README.md +++ b/README.md @@ -55,9 +55,13 @@ To help hack on the different drivers here's a list of docs which outline the gi ### Bitbucket Server -* REST API reference: https://docs.atlassian.com/bitbucket-server/rest/6.5.1/bitbucket-rest.html +* REST API reference: https://docs.atlassian.com/bitbucket-server/rest/6.5.1/bitbucket-rest.html * Webhooks: https://confluence.atlassian.com/bitbucketserver/event-payload-938025882.html +### Bitbucket Cloud + +* REST API reference: https://developer.atlassian.com/bitbucket/api/2/reference/ + ### Gitlab * REST API reference: https://docs.gitlab.com/ee/api/ diff --git a/go.mod b/go.mod index bd8d23ae5..6fa82ee2b 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/pkg/errors v0.8.1 github.com/shurcooL/githubv4 v0.0.0-20190718010115-4ba037080260 github.com/shurcooL/graphql v0.0.0-20181231061246-d48a9a75455f // indirect - github.com/sirupsen/logrus v1.4.2 // indirect + github.com/sirupsen/logrus v1.4.2 github.com/stretchr/testify v1.3.0 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 k8s.io/apimachinery v0.0.0-20190703205208-4cfb76a8bf76 diff --git a/scm/driver/bitbucket/pr.go b/scm/driver/bitbucket/pr.go index b49bea9ba..488bd1d17 100644 --- a/scm/driver/bitbucket/pr.go +++ b/scm/driver/bitbucket/pr.go @@ -5,8 +5,11 @@ package bitbucket import ( + "bytes" "context" "fmt" + "strings" + "time" "github.com/jenkins-x/go-scm/scm" ) @@ -15,6 +18,8 @@ type pullService struct { *issueService } +const debugDump = false + func (s *pullService) Find(ctx context.Context, repo string, number int) (*scm.PullRequest, *scm.Response, error) { path := fmt.Sprintf("2.0/repositories/%s/pullrequests/%d", repo, number) out := new(pullRequest) @@ -25,6 +30,12 @@ func (s *pullService) Find(ctx context.Context, repo string, number int) (*scm.P func (s *pullService) List(ctx context.Context, repo string, opts scm.PullRequestListOptions) ([]*scm.PullRequest, *scm.Response, error) { path := fmt.Sprintf("2.0/repositories/%s/pullrequests?%s", repo, encodePullRequestListOptions(opts)) out := new(pullRequests) + if debugDump { + var buf bytes.Buffer + res, err := s.client.do(ctx, "GET", path, nil, &buf) + fmt.Printf("%s\n", buf.String()) + return nil, res, err + } res, err := s.client.do(ctx, "GET", path, nil, out) copyPagination(out.pagination, res) return convertPullRequests(out), res, err @@ -48,17 +59,102 @@ func (s *pullService) Close(ctx context.Context, repo string, number int) (*scm. return nil, scm.ErrNotSupported } -type pullRequest struct{} +type prCommit struct { + LatestCommit string `json:"hash"` +} + +type prSource struct { + Commit struct { + Type string `json:"type"` + Ref string `json:"ref"` + Commit string `json:"hash"` + } `json:"commit"` + Repository repository `json:"repository"` + Branch struct { + Name string `json:"name"` + } `json:"branch"` +} + +type prDestination struct { + Commit struct { + Type string `json:"type"` + Ref string `json:"ref"` + Commit string `json:"Commit"` + } `json:"commit"` + Repository repository `json:"repository"` + Branch struct { + Name string `json:"name"` + } `json:"branch"` +} + +type pullRequest struct { + ID int `json:"id"` + //Version int `json:"version"` + Title string `json:"title"` + Description string `json:"description"` + State string `json:"state"` + CreatedDate time.Time `json:"created_on"` + UpdatedDate time.Time `json:"updated_on"` + Source prSource `json:"source"` + Destination prDestination `json:"destination"` + Locked bool `json:"locked"` + Author user `json:"author"` + Reviewers []user `json:"reviewers"` + Participants []user `json:"participants"` + Links struct { + Self link `json:"self"` + HTML link `json:"html"` + } `json:"links"` +} type pullRequests struct { pagination Values []*pullRequest `json:"values"` } -func convertPullRequests(from *pullRequests) []*scm.PullRequest { - return nil +func convertPullRequest(from *pullRequest) *scm.PullRequest { + // TODO + fork := "false" + closed := strings.ToLower(from.State) != "open" + return &scm.PullRequest{ + Number: from.ID, + Title: from.Title, + Body: from.Description, + Sha: from.Source.Commit.Commit, + Ref: fmt.Sprintf("refs/pull-requests/%d/from", from.ID), + Source: from.Source.Commit.Commit, + Target: from.Destination.Commit.Commit, + Fork: fork, + Base: convertPullRequestBranch(from.Destination.Commit.Ref, from.Destination.Commit.Commit, from.Destination.Repository), + Head: convertPullRequestBranch(from.Source.Commit.Ref, from.Source.Commit.Commit, from.Source.Repository), + Link: from.Links.HTML.Href, + State: strings.ToLower(from.State), + Closed: closed, + Merged: from.State == "MERGED", + Created: from.CreatedDate, + Updated: from.UpdatedDate, + Author: scm.User{ + Login: from.Author.GetLogin(), + Name: from.Author.DisplayName, + Email: from.Author.EmailAddress, + Link: from.Author.Links.Self.Href, + Avatar: from.Author.Links.Avatar.Href, + }, + } } -func convertPullRequest(from *pullRequest) *scm.PullRequest { - return nil +func convertPullRequestBranch(ref string, sha string, repo repository) scm.PullRequestBranch { + return scm.PullRequestBranch{ + Ref: ref, + Sha: sha, + Repo: *convertRepository(&repo), + } +} + +func convertPullRequests(from *pullRequests) []*scm.PullRequest { + answer := []*scm.PullRequest{} + for _, pr := range from.Values { + answer = append(answer, convertPullRequest(pr)) + } + return answer } diff --git a/scm/driver/bitbucket/pr_test.go b/scm/driver/bitbucket/pr_test.go index 4bfe71e69..d44dbfeb4 100644 --- a/scm/driver/bitbucket/pr_test.go +++ b/scm/driver/bitbucket/pr_test.go @@ -21,7 +21,37 @@ func TestPullFind(t *testing.T) { } func TestPullList(t *testing.T) { - t.Skip() + defer gock.Off() + + gock.New("https://api.bitbucket.org"). + Get("/2.0/repositories/octocat/hello-world/pullrequests"). + MatchParam("pagelen", "30"). + MatchParam("page", "1"). + MatchParam("state", "all"). + Reply(200). + Type("application/json"). + //SetHeaders(mockHeaders). + //SetHeaders(mockPageHeaders). + File("testdata/pulls.json") + + client := NewDefault() + got, _, err := client.PullRequests.List(context.Background(), "octocat/hello-world", scm.PullRequestListOptions{Page: 1, Size: 30, Open: true, Closed: true}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.PullRequest{} + raw, _ := ioutil.ReadFile("testdata/pulls.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + + data, _ := json.Marshal(got) + t.Logf("got JSON: %s", data) + } } func TestPullListChanges(t *testing.T) { diff --git a/scm/driver/bitbucket/repo.go b/scm/driver/bitbucket/repo.go index eed65be25..62d3c8d6d 100644 --- a/scm/driver/bitbucket/repo.go +++ b/scm/driver/bitbucket/repo.go @@ -195,6 +195,7 @@ func convertRepository(from *repository) *scm.Repository { ID: from.UUID, Name: name, Namespace: namespace, + FullName: from.FullName, Link: fmt.Sprintf("https://bitbucket.org/%s", from.FullName), Branch: from.Mainbranch.Name, Private: from.IsPrivate, diff --git a/scm/driver/bitbucket/repo_test.go b/scm/driver/bitbucket/repo_test.go index ced1eeb0f..14441879b 100644 --- a/scm/driver/bitbucket/repo_test.go +++ b/scm/driver/bitbucket/repo_test.go @@ -112,7 +112,8 @@ func TestRepositoryList(t *testing.T) { client, _ := New("https://api.bitbucket.org") for { - repos, res, err := client.Repositories.List(context.Background(), opts) + ctx := context.Background() + repos, res, err := client.Repositories.List(ctx, opts) if err != nil { t.Error(err) } diff --git a/scm/driver/bitbucket/testdata/pulls.json b/scm/driver/bitbucket/testdata/pulls.json new file mode 100644 index 000000000..96e9869a0 --- /dev/null +++ b/scm/driver/bitbucket/testdata/pulls.json @@ -0,0 +1,291 @@ +{ + "pagelen": 10, + "values": [ + { + "description": "", + "links": { + "decline": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/pullrequests/2/decline" + }, + "diffstat": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/diffstat/jstrachan/demo6:42f383c381d9%0Dec8d3da80fc5?from_pullrequest_id=2" + }, + "commits": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/pullrequests/2/commits" + }, + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/pullrequests/2" + }, + "comments": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/pullrequests/2/comments" + }, + "merge": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/pullrequests/2/merge" + }, + "html": { + "href": "https://bitbucket.org/jstrachan/demo6/pull-requests/2" + }, + "activity": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/pullrequests/2/activity" + }, + "diff": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/diff/jstrachan/demo6:42f383c381d9%0Dec8d3da80fc5?from_pullrequest_id=2" + }, + "approve": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/pullrequests/2/approve" + }, + "statuses": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/pullrequests/2/statuses" + } + }, + "title": "added awesome to Jenkinsfile", + "close_source_branch": false, + "type": "pullrequest", + "id": 2, + "destination": { + "commit": { + "Commit": "ec8d3da80fc5", + "type": "commit", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/commit/ec8d3da80fc5" + }, + "html": { + "href": "https://bitbucket.org/jstrachan/demo6/commits/ec8d3da80fc5" + } + } + }, + "repository": { + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6" + }, + "html": { + "href": "https://bitbucket.org/jstrachan/demo6" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7Bb7c5a1c5-28bb-4e20-b262-3beaff0dd827%7D?ts=default" + } + }, + "type": "repository", + "name": "demo6", + "full_name": "jstrachan/demo6", + "uuid": "{b7c5a1c5-28bb-4e20-b262-3beaff0dd827}" + }, + "branch": { + "name": "master" + } + }, + "created_on": "2018-04-21T08:56:02.020408+00:00", + "summary": { + "raw": "", + "markup": "markdown", + "html": "", + "type": "rendered" + }, + "source": { + "commit": { + "hash": "42f383c381d9", + "type": "commit", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/commit/42f383c381d9" + }, + "html": { + "href": "https://bitbucket.org/jstrachan/demo6/commits/42f383c381d9" + } + } + }, + "repository": { + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6" + }, + "html": { + "href": "https://bitbucket.org/jstrachan/demo6" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7Bb7c5a1c5-28bb-4e20-b262-3beaff0dd827%7D?ts=default" + } + }, + "type": "repository", + "name": "demo6", + "full_name": "jstrachan/demo6", + "uuid": "{b7c5a1c5-28bb-4e20-b262-3beaff0dd827}" + }, + "branch": { + "name": "somestuff" + } + }, + "comment_count": 0, + "state": "OPEN", + "task_count": 0, + "reason": "", + "updated_on": "2018-04-21T09:01:57.659051+00:00", + "author": { + "display_name": "James Strachan", + "uuid": "{9c09f561-6d19-4635-8d6f-5eb06fed3a08}", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B9c09f561-6d19-4635-8d6f-5eb06fed3a08%7D" + }, + "html": { + "href": "https://bitbucket.org/%7B9c09f561-6d19-4635-8d6f-5eb06fed3a08%7D/" + }, + "avatar": { + "href": "https://secure.gravatar.com/avatar/64dbbbeb960d4014b28cd64d73340d94?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FJS-3.png" + } + }, + "nickname": "JamesS", + "type": "user", + "account_id": "557058:8ad5a564-ff17-4b3f-8b89-67d523e02c90" + }, + "merge_commit": null, + "closed_by": null + }, + { + "description": "", + "links": { + "decline": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/pullrequests/1/decline" + }, + "diffstat": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/diffstat/jstrachan/demo6:bf9b796a1dd0%0Dec8d3da80fc5?from_pullrequest_id=1" + }, + "commits": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/pullrequests/1/commits" + }, + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/pullrequests/1" + }, + "comments": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/pullrequests/1/comments" + }, + "merge": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/pullrequests/1/merge" + }, + "html": { + "href": "https://bitbucket.org/jstrachan/demo6/pull-requests/1" + }, + "activity": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/pullrequests/1/activity" + }, + "diff": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/diff/jstrachan/demo6:bf9b796a1dd0%0Dec8d3da80fc5?from_pullrequest_id=1" + }, + "approve": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/pullrequests/1/approve" + }, + "statuses": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/pullrequests/1/statuses" + } + }, + "title": "added awesome", + "close_source_branch": false, + "type": "pullrequest", + "id": 1, + "destination": { + "commit": { + "hash": "ec8d3da80fc5", + "type": "commit", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/commit/ec8d3da80fc5" + }, + "html": { + "href": "https://bitbucket.org/jstrachan/demo6/commits/ec8d3da80fc5" + } + } + }, + "repository": { + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6" + }, + "html": { + "href": "https://bitbucket.org/jstrachan/demo6" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7Bb7c5a1c5-28bb-4e20-b262-3beaff0dd827%7D?ts=default" + } + }, + "type": "repository", + "name": "demo6", + "full_name": "jstrachan/demo6", + "uuid": "{b7c5a1c5-28bb-4e20-b262-3beaff0dd827}" + }, + "branch": { + "name": "master" + } + }, + "created_on": "2018-04-18T14:07:40.354351+00:00", + "summary": { + "raw": "", + "markup": "markdown", + "html": "", + "type": "rendered" + }, + "source": { + "commit": { + "hash": "bf9b796a1dd0", + "type": "commit", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6/commit/bf9b796a1dd0" + }, + "html": { + "href": "https://bitbucket.org/jstrachan/demo6/commits/bf9b796a1dd0" + } + } + }, + "repository": { + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/jstrachan/demo6" + }, + "html": { + "href": "https://bitbucket.org/jstrachan/demo6" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7Bb7c5a1c5-28bb-4e20-b262-3beaff0dd827%7D?ts=default" + } + }, + "type": "repository", + "name": "demo6", + "full_name": "jstrachan/demo6", + "uuid": "{b7c5a1c5-28bb-4e20-b262-3beaff0dd827}" + }, + "branch": { + "name": "cheese" + } + }, + "comment_count": 0, + "state": "OPEN", + "task_count": 0, + "reason": "", + "updated_on": "2018-04-20T16:28:21.843691+00:00", + "author": { + "display_name": "James Strachan", + "uuid": "{9c09f561-6d19-4635-8d6f-5eb06fed3a08}", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B9c09f561-6d19-4635-8d6f-5eb06fed3a08%7D" + }, + "html": { + "href": "https://bitbucket.org/%7B9c09f561-6d19-4635-8d6f-5eb06fed3a08%7D/" + }, + "avatar": { + "href": "https://secure.gravatar.com/avatar/64dbbbeb960d4014b28cd64d73340d94?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FJS-3.png" + } + }, + "nickname": "JamesS", + "type": "user", + "account_id": "557058:8ad5a564-ff17-4b3f-8b89-67d523e02c90" + }, + "merge_commit": null, + "closed_by": null + } + ], + "page": 1, + "size": 2 +} \ No newline at end of file diff --git a/scm/driver/bitbucket/testdata/pulls.json.golden b/scm/driver/bitbucket/testdata/pulls.json.golden new file mode 100644 index 000000000..1c17bdd40 --- /dev/null +++ b/scm/driver/bitbucket/testdata/pulls.json.golden @@ -0,0 +1,154 @@ +[ + { + "Number": 2, + "Title": "added awesome to Jenkinsfile", + "Body": "", + "Labels": null, + "Sha": "42f383c381d9", + "Ref": "refs/pull-requests/2/from", + "Source": "42f383c381d9", + "Target": "ec8d3da80fc5", + "Base": { + "Ref": "", + "Sha": "ec8d3da80fc5", + "Repo": { + "ID": "{b7c5a1c5-28bb-4e20-b262-3beaff0dd827}", + "Namespace": "jstrachan", + "Name": "demo6", + "FullName": "jstrachan/demo6", + "Perm": null, + "Branch": "", + "Private": false, + "Clone": "https://bitbucket.org/jstrachan/demo6.git", + "CloneSSH": "git@bitbucket.org:jstrachan/demo6.git", + "Link": "https://bitbucket.org/jstrachan/demo6", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + } + }, + "Head": { + "Ref": "", + "Sha": "42f383c381d9", + "Repo": { + "ID": "{b7c5a1c5-28bb-4e20-b262-3beaff0dd827}", + "Namespace": "jstrachan", + "Name": "demo6", + "FullName": "jstrachan/demo6", + "Perm": null, + "Branch": "", + "Private": false, + "Clone": "https://bitbucket.org/jstrachan/demo6.git", + "CloneSSH": "git@bitbucket.org:jstrachan/demo6.git", + "Link": "https://bitbucket.org/jstrachan/demo6", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + } + }, + "Fork": "false", + "Link": "https://bitbucket.org/jstrachan/demo6/pull-requests/2", + "State": "open", + "Closed": false, + "Draft": false, + "Merged": false, + "Mergeable": false, + "Rebaseable": false, + "MergeableState": "", + "MergeSha": "", + "Author": { + "Login": "", + "Name": "James Strachan", + "Email": "", + "Avatar": "https://secure.gravatar.com/avatar/64dbbbeb960d4014b28cd64d73340d94?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FJS-3.png", + "Link": "https://api.bitbucket.org/2.0/users/%7B9c09f561-6d19-4635-8d6f-5eb06fed3a08%7D", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Assignees": null, + "Milestone": { + "Number": 0, + "ID": 0, + "Title": "", + "Description": "", + "Link": "", + "State": "" + }, + "Created": "2018-04-21T08:56:02.020408Z", + "Updated": "2018-04-21T09:01:57.659051Z" + }, + { + "Number": 1, + "Title": "added awesome", + "Body": "", + "Labels": null, + "Sha": "bf9b796a1dd0", + "Ref": "refs/pull-requests/1/from", + "Source": "bf9b796a1dd0", + "Target": "", + "Base": { + "Ref": "", + "Sha": "", + "Repo": { + "ID": "{b7c5a1c5-28bb-4e20-b262-3beaff0dd827}", + "Namespace": "jstrachan", + "Name": "demo6", + "FullName": "jstrachan/demo6", + "Perm": null, + "Branch": "", + "Private": false, + "Clone": "https://bitbucket.org/jstrachan/demo6.git", + "CloneSSH": "git@bitbucket.org:jstrachan/demo6.git", + "Link": "https://bitbucket.org/jstrachan/demo6", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + } + }, + "Head": { + "Ref": "", + "Sha": "bf9b796a1dd0", + "Repo": { + "ID": "{b7c5a1c5-28bb-4e20-b262-3beaff0dd827}", + "Namespace": "jstrachan", + "Name": "demo6", + "FullName": "jstrachan/demo6", + "Perm": null, + "Branch": "", + "Private": false, + "Clone": "https://bitbucket.org/jstrachan/demo6.git", + "CloneSSH": "git@bitbucket.org:jstrachan/demo6.git", + "Link": "https://bitbucket.org/jstrachan/demo6", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + } + }, + "Fork": "false", + "Link": "https://bitbucket.org/jstrachan/demo6/pull-requests/1", + "State": "open", + "Closed": false, + "Draft": false, + "Merged": false, + "Mergeable": false, + "Rebaseable": false, + "MergeableState": "", + "MergeSha": "", + "Author": { + "Login": "", + "Name": "James Strachan", + "Email": "", + "Avatar": "https://secure.gravatar.com/avatar/64dbbbeb960d4014b28cd64d73340d94?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FJS-3.png", + "Link": "https://api.bitbucket.org/2.0/users/%7B9c09f561-6d19-4635-8d6f-5eb06fed3a08%7D", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Assignees": null, + "Milestone": { + "Number": 0, + "ID": 0, + "Title": "", + "Description": "", + "Link": "", + "State": "" + }, + "Created": "2018-04-18T14:07:40.354351Z", + "Updated": "2018-04-20T16:28:21.843691Z" + } +] \ No newline at end of file diff --git a/scm/driver/bitbucket/testdata/repo.json.golden b/scm/driver/bitbucket/testdata/repo.json.golden index 74fb17f75..6383f830f 100644 --- a/scm/driver/bitbucket/testdata/repo.json.golden +++ b/scm/driver/bitbucket/testdata/repo.json.golden @@ -1,13 +1,14 @@ { - "ID": "{7dd600e6-0d9c-4801-b967-cb4cc17359ff}", - "Namespace": "atlassian", - "Name": "stash-example-plugin", - "Perm": null, - "Branch": "master", - "Private": true, - "Clone": "https://bitbucket.org/atlassian/stash-example-plugin.git", - "CloneSSH": "git@bitbucket.org:atlassian/stash-example-plugin.git", - "Link": "https://bitbucket.org/atlassian/stash-example-plugin", - "Created": "2013-04-15T03:05:05.595458Z", - "Updated": "2018-04-01T16:36:35.970175Z" + "ID": "{7dd600e6-0d9c-4801-b967-cb4cc17359ff}", + "Namespace": "atlassian", + "Name": "stash-example-plugin", + "FullName": "atlassian/stash-example-plugin", + "Perm": null, + "Branch": "master", + "Private": true, + "Clone": "https://bitbucket.org/atlassian/stash-example-plugin.git", + "CloneSSH": "git@bitbucket.org:atlassian/stash-example-plugin.git", + "Link": "https://bitbucket.org/atlassian/stash-example-plugin", + "Created": "2013-04-15T03:05:05.595458Z", + "Updated": "2018-04-01T16:36:35.970175Z" } \ No newline at end of file diff --git a/scm/driver/bitbucket/testdata/repos.json.golden b/scm/driver/bitbucket/testdata/repos.json.golden index d873143db..8faa73cea 100644 --- a/scm/driver/bitbucket/testdata/repos.json.golden +++ b/scm/driver/bitbucket/testdata/repos.json.golden @@ -3,6 +3,7 @@ "ID": "{7dd600e6-0d9c-4801-b967-cb4cc17359ff}", "Namespace": "atlassian", "Name": "stash-example-plugin", + "FullName": "atlassian/stash-example-plugin", "Perm": null, "Branch": "master", "Private": true, @@ -16,6 +17,7 @@ "ID": "{7dd600e6-0d9c-4801-b967-cb4cc17359ff}", "Namespace": "atlassian", "Name": "stash-example-plugin", + "FullName": "atlassian/stash-example-plugin", "Perm": null, "Branch": "master", "Private": true, diff --git a/scm/driver/bitbucket/user.go b/scm/driver/bitbucket/user.go index 0001cf98f..3231f5e35 100644 --- a/scm/driver/bitbucket/user.go +++ b/scm/driver/bitbucket/user.go @@ -33,9 +33,24 @@ func (s *userService) FindEmail(ctx context.Context) (string, *scm.Response, err } type user struct { - Login string `json:"username"` - Name string `json:"display_name"` - Links links `json:"links"` + Login string `json:"username"` + Name string `json:"nickname"` + EmailAddress string `json:"emailAddress"` + ID int `json:"id"` + DisplayName string `json:"display_name"` + Active bool `json:"active"` + Slug string `json:"slug"` + Type string `json:"type"` + Links struct { + Self link `json:"self"` + HTML link `json:"html"` + Avatar link `json:"avatar"` + } `json:"links"` +} + +func (u *user) GetLogin() string { + answer := u.Login + return answer } type links struct { @@ -48,9 +63,13 @@ type link struct { } func convertUser(from *user) *scm.User { + name := from.Name + if name == "" { + name = from.DisplayName + } return &scm.User{ Avatar: fmt.Sprintf("https://bitbucket.org/account/%s/avatar/32/", from.Login), Login: from.Login, - Name: from.Name, + Name: name, } } diff --git a/scm/factory/examples/pr/main.go b/scm/factory/examples/pr/main.go index eac6065ec..99e3129dd 100644 --- a/scm/factory/examples/pr/main.go +++ b/scm/factory/examples/pr/main.go @@ -46,6 +46,7 @@ func main() { } fmt.Printf("%s:\n", string(data)) } + return } prText := args[2] number, err := strconv.Atoi(prText) diff --git a/scm/factory/factory.go b/scm/factory/factory.go index 23f9db0cc..06fb58bb0 100644 --- a/scm/factory/factory.go +++ b/scm/factory/factory.go @@ -33,7 +33,7 @@ func NewClient(driver, serverURL, oauthToken string) (*scm.Client, error) { switch driver { case "bitbucket", "bitbucketcloud": if serverURL != "" { - client, err = bitbucket.New(serverURL) + client, err = bitbucket.New(ensureBBCEndpoint(serverURL)) } else { client = bitbucket.NewDefault() } @@ -73,7 +73,7 @@ func NewClient(driver, serverURL, oauthToken string) (*scm.Client, error) { return client, err } if oauthToken != "" { - if driver == "gitlab" { + if driver == "gitlab" || driver == "bitbucketcloud" { client.Client = &http.Client{ Transport: &transport.PrivateToken{ Token: oauthToken, @@ -117,3 +117,11 @@ func ensureGHEEndpoint(u string) string { } return u } + +// ensureBBCEndpoint lets ensure we have the /api/v3 suffix on the URL +func ensureBBCEndpoint(u string) string { + if strings.HasPrefix(u, "https://bitbucket.org") || strings.HasPrefix(u, "http://bitbucket.org") { + return "https://api.bitbucket.org" + } + return u +}