Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New ListPullRequestComments API #42

Merged
merged 10 commits into from
May 18, 2022
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/jfrog/froggit-go
go 1.17

require (
github.com/gfleury/go-bitbucket-v1 v0.0.0-20210826163055-dff2223adeac
github.com/gfleury/go-bitbucket-v1 v0.0.0-20220418082332-711d7d5e805f
github.com/google/go-github/v41 v41.0.0
github.com/google/uuid v1.3.0
github.com/ktrysmt/go-bitbucket v0.9.32
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/gfleury/go-bitbucket-v1 v0.0.0-20210826163055-dff2223adeac h1:0hlPRK2IeBbM3zab+3+vLh+vgepD+gsx9Ra9CIUeX84=
github.com/gfleury/go-bitbucket-v1 v0.0.0-20210826163055-dff2223adeac/go.mod h1:LB3osS9X2JMYmTzcCArHHLrndBAfcVLQAvUddfs+ONs=
github.com/gfleury/go-bitbucket-v1 v0.0.0-20220418082332-711d7d5e805f h1:xVRGXRHjGaqT9M+mNNQrsoku+p2z/+Ei/b2gs7ZCbZw=
github.com/gfleury/go-bitbucket-v1 v0.0.0-20220418082332-711d7d5e805f/go.mod h1:LB3osS9X2JMYmTzcCArHHLrndBAfcVLQAvUddfs+ONs=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
Expand Down
91 changes: 72 additions & 19 deletions vcsclient/bitbucketcloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,29 @@ func (client *BitbucketCloudClient) AddPullRequestComment(ctx context.Context, o
return err
}

// ListPullRequestComments on Bitbucket cloud
func (client *BitbucketCloudClient) ListPullRequestComments(ctx context.Context, owner, repository string, pullRequestID int) (res []CommentInfo, err error) {
err = validateParametersNotBlank(map[string]string{"owner": owner, "repository": repository})
if err != nil {
return nil, err
}
bitbucketClient := client.buildBitbucketCloudClient(ctx)
options := &bitbucket.PullRequestsOptions{
Owner: owner,
RepoSlug: repository,
ID: fmt.Sprint(pullRequestID),
}
comments, err := bitbucketClient.Repositories.PullRequests.GetComments(options)
if err != nil {
return
}
parsedComments, err := extractCommentsFromResponse(comments)
if err != nil {
return
}
return mapBitbucketCloudCommentToCommentInfo(parsedComments), nil
}

// GetLatestCommit on Bitbucket cloud
func (client *BitbucketCloudClient) GetLatestCommit(ctx context.Context, owner, repository, branch string) (CommitInfo, error) {
err := validateParametersNotBlank(map[string]string{
Expand Down Expand Up @@ -396,28 +419,45 @@ func (client *BitbucketCloudClient) UnlabelPullRequest(ctx context.Context, owne

func extractCommitFromResponse(commits interface{}) (*commitResponse, error) {
var res commitResponse
b, err := json.Marshal(commits)
if err != nil {
return nil, err
}
err = json.Unmarshal(b, &res)
if err != nil {
return nil, err
}
return &res, nil
err := extractStructFromResponse(commits, &res)
return &res, err
}

func extractCommitDetailsFromResponse(commit interface{}) (commitDetails, error) {
var res commitDetails
b, err := json.Marshal(commit)
if err != nil {
return commitDetails{}, err
}
err = json.Unmarshal(b, &res)
err := extractStructFromResponse(commit, &res)
return res, err
}

func extractCommentsFromResponse(comments interface{}) (*commentsResponse, error) {
var res commentsResponse
talarian1 marked this conversation as resolved.
Show resolved Hide resolved
err := extractStructFromResponse(comments, &res)
return &res, err
}

func extractStructFromResponse(response, aStructPointer interface{}) error {
b, err := json.Marshal(response)
if err != nil {
return commitDetails{}, err
return nil
talarian1 marked this conversation as resolved.
Show resolved Hide resolved
}
return res, nil
err = json.Unmarshal(b, aStructPointer)
return err
}

type commentsResponse struct {
Values []commentDetails `json:"values"`
}

type commentDetails struct {
ID int64 `json:"id"`
User user `json:"user"`
IsDeleted bool `json:"deleted"`
Content commentContent `json:"content"`
Created time.Time `json:"created_on"`
}

type commentContent struct {
Raw string `json:"raw"`
}

type commitResponse struct {
Expand All @@ -429,9 +469,7 @@ type commitDetails struct {
Date time.Time `json:"date"`
Message string `json:"message"`
Author struct {
User struct {
DisplayName string `json:"display_name"`
} `json:"user"`
User user `json:"user"`
} `json:"author"`
Links struct {
Self link `json:"self"`
Expand All @@ -441,6 +479,9 @@ type commitDetails struct {
} `json:"parents"`
}

type user struct {
DisplayName string `json:"display_name"`
}
type link struct {
Href string `json:"href"`
}
Expand Down Expand Up @@ -512,3 +553,15 @@ func mapBitbucketCloudCommitToCommitInfo(parsedCommit commitDetails) CommitInfo
ParentHashes: parents,
}
}

func mapBitbucketCloudCommentToCommentInfo(parsedComments *commentsResponse) []CommentInfo {
comments := make([]CommentInfo, len(parsedComments.Values))
for i, comment := range parsedComments.Values {
comments[i] = CommentInfo{
ID: comment.ID,
Content: comment.Content.Raw,
Created: comment.Created,
}
}
return comments
}
21 changes: 21 additions & 0 deletions vcsclient/bitbucketcloud_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,27 @@ func TestBitbucketCloud_AddPullRequestComment(t *testing.T) {
assert.NoError(t, err)
}

func TestBitbucketCloud_ListPullRequestComments(t *testing.T) {
ctx := context.Background()
response, err := os.ReadFile(filepath.Join("testdata", "bitbucketcloud", "pull_request_comments_list_response.json"))
assert.NoError(t, err)
client, cleanUp := createServerAndClient(t, vcsutils.BitbucketCloud, true, response,
fmt.Sprintf("/repositories/%s/%s/pullrequests/1/comments/", owner, repo1), createBitbucketCloudHandler)
defer cleanUp()

result, err := client.ListPullRequestComments(ctx, owner, repo1, 1)

require.NoError(t, err)
expectedCreated, err := time.Parse(time.RFC3339, "2022-05-16T11:04:07.075827+00:00")
assert.NoError(t, err)
assert.Len(t, result, 2)
assert.Equal(t, CommentInfo{
ID: 301545835,
Content: "I’m a comment ",
Created: expectedCreated,
}, result[0])
}

func TestBitbucketCloud_GetLatestCommit(t *testing.T) {
ctx := context.Background()
response, err := os.ReadFile(filepath.Join("testdata", "bitbucketcloud", "commit_list_response.json"))
Expand Down
32 changes: 32 additions & 0 deletions vcsclient/bitbucketserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"net/http"
"strconv"
"strings"
"time"

bitbucketv1 "github.com/gfleury/go-bitbucket-v1"
"github.com/jfrog/froggit-go/vcsutils"
Expand Down Expand Up @@ -305,6 +306,37 @@ func (client *BitbucketServerClient) AddPullRequestComment(ctx context.Context,
return err
}

// ListPullRequestComments on Bitbucket server
func (client *BitbucketServerClient) ListPullRequestComments(ctx context.Context, owner, repository string, pullRequestID int) ([]CommentInfo, error) {
bitbucketClient, err := client.buildBitbucketClient(ctx)
if err != nil {
return nil, err
}
var results []CommentInfo
var apiResponse *bitbucketv1.APIResponse
for isLastPage, nextPageStart := true, 0; isLastPage; isLastPage, nextPageStart = bitbucketv1.HasNextPage(apiResponse) {
apiResponse, err = bitbucketClient.GetActivities(owner, repository, int64(pullRequestID), createPaginationOptions(nextPageStart))
if err != nil {
return nil, err
}
activities, err := bitbucketv1.GetActivitiesResponse(apiResponse)
if err != nil {
return nil, err
}
for _, activity := range activities.Values {
// Add activity only if from type new comment.
if activity.Action == "COMMENTED" && activity.CommentAction == "ADDED" {
results = append(results, CommentInfo{
ID: int64(activity.Comment.ID),
Created: time.Unix(activity.Comment.CreatedDate, 0),
Content: activity.Comment.Text,
})
}
}
}
return results, nil
}

type projectsResponse struct {
Values []struct {
Key string `json:"key,omitempty"`
Expand Down
21 changes: 20 additions & 1 deletion vcsclient/bitbucketserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func TestBitbucketServer_ListBranches(t *testing.T) {
mockResponse := map[string][]bitbucketv1.Branch{
"values": {{ID: branch1}, {ID: branch2}},
}
client, cleanUp := createServerAndClient(t, vcsutils.BitbucketServer, false, mockResponse, "/api/1.0/projects/jfrog/repos/repo-1/branches", createBitbucketServerHandler)
client, cleanUp := createServerAndClient(t, vcsutils.BitbucketServer, false, mockResponse, "/api/1.0/projects/jfrog/repos/repo-1/branches?start=0", createBitbucketServerHandler)
defer cleanUp()

actualRepositories, err := client.ListBranches(ctx, owner, repo1)
Expand Down Expand Up @@ -197,6 +197,25 @@ func TestBitbucketServer_AddPullRequestComment(t *testing.T) {
assert.Error(t, err)
}

func TestBitbucketServer_ListPullRequestComments(t *testing.T) {
ctx := context.Background()
response, err := os.ReadFile(filepath.Join("testdata", "bitbucketserver", "pull_request_comments_list_response.json"))
assert.NoError(t, err)
client, cleanUp := createServerAndClient(t, vcsutils.BitbucketServer, true, response,
fmt.Sprintf("/api/1.0/projects/%s/repos/%s/pull-requests/1/activities?start=0", owner, repo1), createBitbucketServerHandler)
defer cleanUp()

result, err := client.ListPullRequestComments(ctx, owner, repo1, 1)

require.NoError(t, err)
assert.Len(t, result, 1)
assert.Equal(t, CommentInfo{
ID: 1,
Content: "A measured reply.",
Created: time.Unix(1548720847370, 0),
}, result[0])
}

func TestBitbucketServer_GetLatestCommit(t *testing.T) {
ctx := context.Background()
response, err := os.ReadFile(filepath.Join("testdata", "bitbucketserver", "commit_list_response.json"))
Expand Down
28 changes: 28 additions & 0 deletions vcsclient/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,23 @@ func (client *GitHubClient) AddPullRequestComment(ctx context.Context, owner, re
return err
}

// ListPullRequestComments on GitHub
func (client *GitHubClient) ListPullRequestComments(ctx context.Context, owner, repository string, pullRequestID int) ([]CommentInfo, error) {
err := validateParametersNotBlank(map[string]string{"owner": owner, "repository": repository})
if err != nil {
return []CommentInfo{}, err
}
ghClient, err := client.buildGithubClient(ctx)
if err != nil {
return []CommentInfo{}, err
}
commentsList, _, err := ghClient.Issues.ListComments(ctx, owner, repository, pullRequestID, &github.IssueListCommentsOptions{})
if err != nil {
return []CommentInfo{}, err
}
return mapGitHubCommentToCommentInfoList(commentsList)
}

// GetLatestCommit on GitHub
func (client *GitHubClient) GetLatestCommit(ctx context.Context, owner, repository, branch string) (CommitInfo, error) {
err := validateParametersNotBlank(map[string]string{
Expand Down Expand Up @@ -464,3 +481,14 @@ func mapGitHubCommitToCommitInfo(commit *github.RepositoryCommit) CommitInfo {
ParentHashes: parents,
}
}

func mapGitHubCommentToCommentInfoList(commentsList []*github.IssueComment) (res []CommentInfo, err error) {
for _, comment := range commentsList {
res = append(res, CommentInfo{
ID: *comment.ID,
Content: *comment.Body,
Created: *comment.CreatedAt,
})
}
return
}
23 changes: 23 additions & 0 deletions vcsclient/github_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,29 @@ func TestGitHubClient_ListPullRequestLabels(t *testing.T) {
assert.Error(t, err)
}

func TestGitHubClient_ListPullRequestComments(t *testing.T) {
ctx := context.Background()
response, err := os.ReadFile(filepath.Join("testdata", "github", "pull_request_comments_list_response.json"))
assert.NoError(t, err)
client, cleanUp := createServerAndClient(t, vcsutils.GitHub, false, response,
fmt.Sprintf("/repos/%s/%s/issues/1/comments", owner, repo1), createGitHubHandler)
defer cleanUp()

result, err := client.ListPullRequestComments(ctx, owner, repo1, 1)
require.NoError(t, err)
assert.Len(t, result, 2)
expectedCreated, err := time.Parse(time.RFC3339, "2011-04-14T16:00:49Z")
assert.NoError(t, err)
assert.Equal(t, CommentInfo{
ID: 10,
Content: "Great stuff!",
Created: expectedCreated,
}, result[0])

_, err = createBadGitHubClient(t).ListPullRequestComments(ctx, owner, repo1, 1)
talarian1 marked this conversation as resolved.
Show resolved Hide resolved
assert.Error(t, err)
}

func TestGitHubClient_UnlabelPullRequest(t *testing.T) {
ctx := context.Background()
client, cleanUp := createServerAndClient(t, vcsutils.GitHub, false, &github.PullRequest{}, fmt.Sprintf("/repos/jfrog/repo-1/issues/1/labels/%s", url.PathEscape(labelName)), createGitHubHandler)
Expand Down
25 changes: 25 additions & 0 deletions vcsclient/gitlab.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,20 @@ func (client *GitLabClient) AddPullRequestComment(ctx context.Context, owner, re
return err
}

// ListPullRequestComments on GitLab
func (client *GitLabClient) ListPullRequestComments(ctx context.Context, owner, repository string, pullRequestID int) ([]CommentInfo, error) {
err := validateParametersNotBlank(map[string]string{"owner": owner, "repository": repository})
if err != nil {
return []CommentInfo{}, err
}
commentsList, _, err := client.glClient.Notes.ListMergeRequestNotes(getProjectID(owner, repository), pullRequestID, &gitlab.ListMergeRequestNotesOptions{},
gitlab.WithContext(ctx))
if err != nil {
return []CommentInfo{}, err
}
return mapGitLabNotesToCommentInfoList(commentsList), nil
}

// GetLatestCommit on GitLab
func (client *GitLabClient) GetLatestCommit(ctx context.Context, owner, repository, branch string) (CommitInfo, error) {
err := validateParametersNotBlank(map[string]string{
Expand Down Expand Up @@ -387,3 +401,14 @@ func mapGitLabCommitToCommitInfo(commit *gitlab.Commit) CommitInfo {
ParentHashes: commit.ParentIDs,
}
}

func mapGitLabNotesToCommentInfoList(notes []*gitlab.Note) (res []CommentInfo) {
for _, note := range notes {
res = append(res, CommentInfo{
ID: int64(note.ID),
Content: note.Body,
Created: *note.CreatedAt,
})
}
return
}
21 changes: 21 additions & 0 deletions vcsclient/gitlab_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,27 @@ func TestGitLabClient_AddPullRequestComment(t *testing.T) {
assert.NoError(t, err)
}

func TestGitLabClient_ListPullRequestComments(t *testing.T) {
ctx := context.Background()
response, err := os.ReadFile(filepath.Join("testdata", "gitlab", "pull_request_comments_list_response.json"))
assert.NoError(t, err)

client, cleanUp := createServerAndClient(t, vcsutils.GitLab, false, response,
fmt.Sprintf("/api/v4/projects/%s/merge_requests/1/notes", url.PathEscape(owner+"/"+repo1)), createGitLabHandler)
defer cleanUp()

result, err := client.ListPullRequestComments(ctx, owner, repo1, 1)
require.NoError(t, err)
expectedCreated, err := time.Parse(time.RFC3339, "2013-10-02T09:56:03Z")
assert.NoError(t, err)
assert.Len(t, result, 2)
assert.Equal(t, CommentInfo{
ID: 305,
Content: "Text of the comment\r\n",
Created: expectedCreated,
}, result[1])
}

func TestGitLabClient_GetLatestCommit(t *testing.T) {
ctx := context.Background()
response, err := os.ReadFile(filepath.Join("testdata", "gitlab", "commit_list_response.json"))
Expand Down
Loading