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

Add endpoints for robot comments #116

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
53 changes: 31 additions & 22 deletions changes.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ type RobotCommentInput struct {
Properties *map[string]*string `json:"properties,omitempty"`
// Suggested fixes for this robot comment as a list of FixSuggestionInfo
// entities.
FixSuggestions *FixSuggestionInfo `json:"fix_suggestions,omitempty"`
FixSuggestions []FixSuggestionInfo `json:"fix_suggestions,omitempty"`
}

// RobotCommentInfo entity contains information about a robot inline comment
Expand All @@ -314,7 +314,7 @@ type RobotCommentInfo struct {
Properties map[string]string `json:"properties,omitempty"`
// Suggested fixes for this robot comment as a list of FixSuggestionInfo
// entities.
FixSuggestions *FixSuggestionInfo `json:"fix_suggestions,omitempty"`
FixSuggestions []FixSuggestionInfo `json:"fix_suggestions,omitempty"`
}

// FixSuggestionInfo entity represents a suggested fix.
Expand All @@ -328,7 +328,7 @@ type FixSuggestionInfo struct {
// A list of FixReplacementInfo entities indicating how the content of one or
// several files should be modified. Within a file, they should refer to
// non-overlapping regions.
Replacements FixReplacementInfo `json:"replacements"`
Replacements []FixReplacementInfo `json:"replacements"`
}

// FixReplacementInfo entity describes how the content of a file should be replaced by another content.
Expand All @@ -345,7 +345,7 @@ type FixReplacementInfo struct {
Range CommentRange `json:"range"`

// The content which should be used instead of the current one.
Replacement string `json:"replacement,omitempty"`
Replacement string `json:"replacement"`
}

// AttentionSetInfo entity contains details of users that are in the attention set.
Expand Down Expand Up @@ -670,7 +670,16 @@ func (s *ChangesService) GetIncludedIn(changeID string) (*IncludedInInfo, *Respo
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#list-change-comments
func (s *ChangesService) ListChangeComments(changeID string) (*map[string][]CommentInfo, *Response, error) {
u := fmt.Sprintf("changes/%s/comments", changeID)
return s.getCommentInfoMapResponse(u)
return s.getCommentInfoMapSliceResponse(u)
}

// Lists the robot comments of all revisions of the change.
// Return a map that maps the file path to a list of RobotCommentInfo entries. The entries in the map are sorted by file path.
//
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#list-change-robot-comments
func (s *ChangesService) ListChangeRobotComments(changeID string) (map[string][]RobotCommentInfo, *Response, error) {
u := fmt.Sprintf("changes/%s/robotcomments", changeID)
return s.getRobotCommentInfoMapSliceResponse(u)
}

// ListChangeDrafts lLists the draft comments of all revisions of the change that belong to the calling user.
Expand All @@ -680,23 +689,7 @@ func (s *ChangesService) ListChangeComments(changeID string) (*map[string][]Comm
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#list-change-drafts
func (s *ChangesService) ListChangeDrafts(changeID string) (*map[string][]CommentInfo, *Response, error) {
u := fmt.Sprintf("changes/%s/drafts", changeID)
return s.getCommentInfoMapResponse(u)
}

// getCommentInfoMapResponse retrieved a map of CommentInfo Response for a GET request
func (s *ChangesService) getCommentInfoMapResponse(u string) (*map[string][]CommentInfo, *Response, error) {
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}

v := new(map[string][]CommentInfo)
resp, err := s.client.Do(req, v)
if err != nil {
return nil, resp, err
}

return v, resp, err
return s.getCommentInfoMapSliceResponse(u)
}

// CheckChange performs consistency checks on the change, and returns a ChangeInfo entity with the problems field set to a list of ProblemInfo entities.
Expand Down Expand Up @@ -741,6 +734,22 @@ func (s *ChangesService) getCommentInfoMapSliceResponse(u string) (*map[string][
return v, resp, err
}

// getRobotCommentInfoMapSliceResponse retrieved a map with a slice of RobotCommentInfo Response for a GET request
func (s *ChangesService) getRobotCommentInfoMapSliceResponse(u string) (map[string][]RobotCommentInfo, *Response, error) {
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}

var v map[string][]RobotCommentInfo
resp, err := s.client.Do(req, &v)
if err != nil {
return nil, resp, err
}

return v, resp, err
}

// CreateChange creates a new change.
//
// The change input ChangeInput entity must be provided in the request body.
Expand Down
25 changes: 25 additions & 0 deletions changes_revision.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,26 @@ func (s *ChangesService) GetComment(changeID, revisionID, commentID string) (*Co
return s.getCommentInfoResponse(u)
}

// GetRobotComment retrieves a robot comment of a revision.
//
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#get-robot-comment
func (s *ChangesService) GetRobotComment(changeID, revisionID, commentID string) (*RobotCommentInfo, *Response, error) {
u := fmt.Sprintf("changes/%s/revisions/%s/robotcomments/%s", changeID, revisionID, commentID)

req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}

v := new(RobotCommentInfo)
resp, err := s.client.Do(req, v)
if err != nil {
return nil, resp, err
}

return v, resp, err
}

// GetSubmitType gets the method the server will use to submit (merge) the change.
//
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#get-submit-type
Expand Down Expand Up @@ -313,6 +333,11 @@ func (s *ChangesService) ListRevisionComments(changeID, revisionID string) (*map
return s.getCommentInfoMapSliceResponse(u)
}

func (s *ChangesService) ListRevisionRobotComments(changeID, revisionID string) (map[string][]RobotCommentInfo, *Response, error) {
u := fmt.Sprintf("changes/%s/revisions/%s/robotcomments", changeID, revisionID)
return s.getRobotCommentInfoMapSliceResponse(u)
}

// ListFiles lists the files that were modified, added or deleted in a revision.
// As result a map is returned that maps the file path to a list of FileInfo entries.
// The entries in the map are sorted by file path.
Expand Down
233 changes: 233 additions & 0 deletions changes_revision_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"net/http/httptest"
"reflect"
"testing"
"time"

"github.com/andygrunwald/go-gerrit"
)
Expand Down Expand Up @@ -79,3 +80,235 @@ func TestChangesService_ListFilesReviewed(t *testing.T) {
t.Errorf("client.Changes.ListFilesReviewed:\ngot: %q\nwant: %q", got, want)
}
}

func TestChangesService_ListRevisionRobotComment(t *testing.T) {
listRobotCommentResponse := `)]}'
{
"main.c": [
{
"robot_id": "robot",
"robot_run_id": "1",
"fix_suggestions": [
{
"fix_id": "c3302a6f_1578ee9e",
"description": "suggestion",
"replacements": [
{
"path": "main.c",
"range": {
"start_line": 3,
"start_character": 0,
"end_line": 5,
"end_character": 1
},
"replacement": "int main() { printf(\"Hello world!\"); }"
}
]
}
],
"author": {
"_account_id": 1000000,
"name": "Jhon Smith",
"username": "jhon"
},
"change_message_id": "517e6c92e4bd105f1e611294a3010ea177771551",
"patch_set": 1,
"id": "f7d3d07f_bf17b66e",
"line": 5,
"range": {
"start_line": 3,
"start_character": 0,
"end_line": 5,
"end_character": 1
},
"updated": "2022-07-05 13:44:34.000000000",
"message": "[clang-format] fix suggestion",
"commit_id": "be8ce493368f2ce0fa73b56f5e2bd0dc17ca4359"
}
]
}`

ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/changes/changeID/revisions/revisionID/robotcomments" {
t.Errorf("%s != /changes/changeID/revisions/revisionID/robotcomments", r.URL.Path)
}
if r.Method != "GET" {
t.Error("Method != GET")
}
fmt.Fprint(w, listRobotCommentResponse)
}))
defer ts.Close()

client, err := gerrit.NewClient(ts.URL, nil)
if err != nil {
t.Error(err)
}

got, _, err := client.Changes.ListRevisionRobotComments("changeID", "revisionID")
if err != nil {
t.Errorf("Changes.ListRevisionRobotComments returned error: %v", err)
}

want := map[string][]gerrit.RobotCommentInfo{
"main.c": {
{
CommentInfo: gerrit.CommentInfo{
PatchSet: 1,
ID: "f7d3d07f_bf17b66e",
Line: 5,
Range: &gerrit.CommentRange{
StartLine: 3,
StartCharacter: 0,
EndLine: 5,
EndCharacter: 1,
},
Message: "[clang-format] fix suggestion",
Updated: &gerrit.Timestamp{
Time: time.Date(2022, 7, 5, 13, 44, 34, 0, time.UTC),
},
Author: gerrit.AccountInfo{
AccountID: 1000000,
Name: "Jhon Smith",
Username: "jhon",
},
},
RobotID: "robot",
RobotRunID: "1",
FixSuggestions: []gerrit.FixSuggestionInfo{
{
FixID: "c3302a6f_1578ee9e",
Description: "suggestion",
Replacements: []gerrit.FixReplacementInfo{
{
Path: "main.c",
Range: gerrit.CommentRange{
StartLine: 3,
StartCharacter: 0,
EndLine: 5,
EndCharacter: 1,
},
Replacement: "int main() { printf(\"Hello world!\"); }",
},
},
},
},
},
},
}

if !reflect.DeepEqual(got, want) {
t.Errorf("Change.ListRevisionRobotComments:\ngot: %+v\nwant: %+v", got, want)
}
}

func TestChangesService_GetRobotComment(t *testing.T) {
getRobotCommentResponse := `)]}'
{
"robot_id": "robot",
"robot_run_id": "1",
"fix_suggestions": [
{
"fix_id": "c3302a6f_1578ee9e",
"description": "suggestion",
"replacements": [
{
"path": "main.c",
"range": {
"start_line": 3,
"start_character": 0,
"end_line": 5,
"end_character": 1
},
"replacement": "int main() { printf(\"Hello world!\"); }"
}
]
}
],
"author": {
"_account_id": 1000000,
"name": "Jhon Smith",
"username": "jhon"
},
"change_message_id": "517e6c92e4bd105f1e611294a3010ea177771551",
"patch_set": 1,
"id": "f7d3d07f_bf17b66e",
"line": 5,
"range": {
"start_line": 3,
"start_character": 0,
"end_line": 5,
"end_character": 1
},
"updated": "2022-07-05 13:44:34.000000000",
"message": "[clang-format] fix suggestion",
"commit_id": "be8ce493368f2ce0fa73b56f5e2bd0dc17ca4359"
}`

ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/changes/changeID/revisions/revisionID/robotcomments/commentID" {
t.Errorf("%s != /changes/changeID/revisions/revisionID/robotcomments/commentID", r.URL.Path)
}
if r.Method != "GET" {
t.Error("Method != GET")
}
fmt.Fprint(w, getRobotCommentResponse)
}))
defer ts.Close()

client, err := gerrit.NewClient(ts.URL, nil)
if err != nil {
t.Error(err)
}

got, _, err := client.Changes.GetRobotComment("changeID", "revisionID", "commentID")
if err != nil {
t.Errorf("Changes.GetRobotComment returned error: %v", err)
}

want := &gerrit.RobotCommentInfo{
CommentInfo: gerrit.CommentInfo{
PatchSet: 1,
ID: "f7d3d07f_bf17b66e",
Line: 5,
Range: &gerrit.CommentRange{
StartLine: 3,
StartCharacter: 0,
EndLine: 5,
EndCharacter: 1,
},
Message: "[clang-format] fix suggestion",
Updated: &gerrit.Timestamp{
Time: time.Date(2022, 7, 5, 13, 44, 34, 0, time.UTC),
},
Author: gerrit.AccountInfo{
AccountID: 1000000,
Name: "Jhon Smith",
Username: "jhon",
},
},
RobotID: "robot",
RobotRunID: "1",
FixSuggestions: []gerrit.FixSuggestionInfo{
{
FixID: "c3302a6f_1578ee9e",
Description: "suggestion",
Replacements: []gerrit.FixReplacementInfo{
{
Path: "main.c",
Range: gerrit.CommentRange{
StartLine: 3,
StartCharacter: 0,
EndLine: 5,
EndCharacter: 1,
},
Replacement: "int main() { printf(\"Hello world!\"); }",
},
},
},
},
}

if !reflect.DeepEqual(got, want) {
t.Errorf("Change.GetRobotComment:\ngot: %+v\nwant: %+v", got, want)
}
}
Loading