From 0938aa133f10b146c24dd58963b7ceb017c92715 Mon Sep 17 00:00:00 2001 From: yiheng-kkk <272397091+yiheng-kkk@users.noreply.github.com> Date: Tue, 1 Sep 2026 13:09:01 +0800 Subject: [PATCH 1/2] Return range coordinates for review comments --- pkg/github/minimal_types.go | 29 +++++++++---- pkg/github/pullrequests.go | 13 +++--- pkg/github/pullrequests_test.go | 74 ++++++++++++++++++++++++++++----- 3 files changed, 94 insertions(+), 22 deletions(-) diff --git a/pkg/github/minimal_types.go b/pkg/github/minimal_types.go index 675ec050bc..f8cf9f307c 100644 --- a/pkg/github/minimal_types.go +++ b/pkg/github/minimal_types.go @@ -1942,13 +1942,16 @@ type MinimalPageInfo struct { // MinimalReviewComment is the trimmed output type for PR review comment objects. type MinimalReviewComment struct { - Body string `json:"body,omitempty"` - Path string `json:"path"` - Line *int `json:"line,omitempty"` - Author string `json:"author,omitempty"` - CreatedAt string `json:"created_at,omitempty"` - UpdatedAt string `json:"updated_at,omitempty"` - HTMLURL string `json:"html_url"` + Body string `json:"body,omitempty"` + Path string `json:"path"` + Line *int `json:"line,omitempty"` + OriginalLine *int `json:"original_line,omitempty"` + StartLine *int `json:"start_line,omitempty"` + OriginalStartLine *int `json:"original_start_line,omitempty"` + Author string `json:"author,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` + HTMLURL string `json:"html_url"` } // MinimalReviewThread is the trimmed output type for PR review thread objects. @@ -2287,6 +2290,18 @@ func convertToMinimalReviewComment(c reviewCommentNode) MinimalReviewComment { line := int(*c.Line) m.Line = &line } + if c.OriginalLine != nil { + originalLine := int(*c.OriginalLine) + m.OriginalLine = &originalLine + } + if c.StartLine != nil { + startLine := int(*c.StartLine) + m.StartLine = &startLine + } + if c.OriginalStartLine != nil { + originalStartLine := int(*c.OriginalStartLine) + m.OriginalStartLine = &originalStartLine + } if !c.CreatedAt.IsZero() { m.CreatedAt = c.CreatedAt.Format(time.RFC3339) diff --git a/pkg/github/pullrequests.go b/pkg/github/pullrequests.go index afd2778510..e512dfef1d 100644 --- a/pkg/github/pullrequests.go +++ b/pkg/github/pullrequests.go @@ -461,11 +461,14 @@ type reviewThreadNode struct { } type reviewCommentNode struct { - ID githubv4.ID - Body githubv4.String - Path githubv4.String - Line *githubv4.Int - Author struct { + ID githubv4.ID + Body githubv4.String + Path githubv4.String + Line *githubv4.Int + OriginalLine *githubv4.Int + StartLine *githubv4.Int + OriginalStartLine *githubv4.Int + Author struct { Login githubv4.String } CreatedAt githubv4.DateTime diff --git a/pkg/github/pullrequests_test.go b/pkg/github/pullrequests_test.go index 92fb4b24a3..75f092206e 100644 --- a/pkg/github/pullrequests_test.go +++ b/pkg/github/pullrequests_test.go @@ -2187,13 +2187,16 @@ func Test_GetPullRequestComments(t *testing.T) { "isOutdated": false, "isCollapsed": false, "comments": map[string]any{ - "totalCount": 2, + "totalCount": 3, "nodes": []map[string]any{ { - "id": "PRRC_kwDOA0xdyM4AX1Y0", - "body": "This looks good", - "path": "file1.go", - "line": 5, + "id": "PRRC_kwDOA0xdyM4AX1Y0", + "body": "This looks good", + "path": "file1.go", + "line": 86, + "originalLine": 84, + "startLine": 73, + "originalStartLine": 73, "author": map[string]any{ "login": "reviewer1", }, @@ -2202,10 +2205,11 @@ func Test_GetPullRequestComments(t *testing.T) { "url": "https://github.com/owner/repo/pull/42#discussion_r101", }, { - "id": "PRRC_kwDOA0xdyM4AX1Y1", - "body": "Please fix this", - "path": "file1.go", - "line": 10, + "id": "PRRC_kwDOA0xdyM4AX1Y1", + "body": "Please fix this", + "path": "file1.go", + "line": 159, + "originalLine": 157, "author": map[string]any{ "login": "reviewer2", }, @@ -2213,6 +2217,21 @@ func Test_GetPullRequestComments(t *testing.T) { "updatedAt": "2024-01-01T13:00:00Z", "url": "https://github.com/owner/repo/pull/42#discussion_r102", }, + { + "id": "PRRC_kwDOA0xdyM4AX1Y2", + "body": "Comment with current coordinates unavailable", + "path": "file1.go", + "line": nil, + "originalLine": 178, + "startLine": nil, + "originalStartLine": 176, + "author": map[string]any{ + "login": "reviewer3", + }, + "createdAt": "2024-01-01T14:00:00Z", + "updatedAt": "2024-01-01T14:00:00Z", + "url": "https://github.com/owner/repo/pull/42#discussion_r103", + }, }, }, }, @@ -2251,13 +2270,48 @@ func Test_GetPullRequestComments(t *testing.T) { assert.Equal(t, false, thread.IsCollapsed) // Validate comments within thread - assert.Len(t, thread.Comments, 2) + assert.Len(t, thread.Comments, 3) // Validate first comment comment1 := thread.Comments[0] assert.Equal(t, "This looks good", comment1.Body) assert.Equal(t, "file1.go", comment1.Path) assert.Equal(t, "reviewer1", comment1.Author) + require.NotNil(t, comment1.Line) + assert.Equal(t, 86, *comment1.Line) + require.NotNil(t, comment1.OriginalLine) + assert.Equal(t, 84, *comment1.OriginalLine) + require.NotNil(t, comment1.StartLine) + assert.Equal(t, 73, *comment1.StartLine) + require.NotNil(t, comment1.OriginalStartLine) + assert.Equal(t, 73, *comment1.OriginalStartLine) + + comment2 := thread.Comments[1] + require.NotNil(t, comment2.Line) + assert.Equal(t, 159, *comment2.Line) + require.NotNil(t, comment2.OriginalLine) + assert.Equal(t, 157, *comment2.OriginalLine) + assert.Nil(t, comment2.StartLine) + assert.Nil(t, comment2.OriginalStartLine) + + var raw struct { + ReviewThreads []struct { + Comments []map[string]any `json:"comments"` + } `json:"review_threads"` + } + require.NoError(t, json.Unmarshal([]byte(textContent), &raw)) + require.Len(t, raw.ReviewThreads, 1) + require.Len(t, raw.ReviewThreads[0].Comments, 3) + assert.NotContains(t, raw.ReviewThreads[0].Comments[1], "start_line") + assert.NotContains(t, raw.ReviewThreads[0].Comments[1], "original_start_line") + + comment3 := thread.Comments[2] + assert.Nil(t, comment3.Line) + require.NotNil(t, comment3.OriginalLine) + assert.Equal(t, 178, *comment3.OriginalLine) + assert.Nil(t, comment3.StartLine) + require.NotNil(t, comment3.OriginalStartLine) + assert.Equal(t, 176, *comment3.OriginalStartLine) // Validate pagination info assert.Equal(t, false, result.PageInfo.HasNextPage) From ee91ae3890f32ce075a14c7117a6b7ee43e55b24 Mon Sep 17 00:00:00 2001 From: Sam Morrow Date: Tue, 1 Sep 2026 12:39:03 +0200 Subject: [PATCH 2/2] docs(pull-requests): describe review comment coordinates Document nullable current and original range fields and assert their serialized omission behavior for single-line and outdated comments. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- README.md | 2 +- docs/feature-flags.md | 2 +- pkg/github/__toolsnaps__/pull_request_read.snap | 2 +- pkg/github/pullrequests.go | 2 +- pkg/github/pullrequests_test.go | 8 ++++++++ 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 145281bcdb..7e290b80b1 100644 --- a/README.md +++ b/README.md @@ -1197,7 +1197,7 @@ The following sets of tools are available: 3. get_status - Get combined commit status of a head commit in a pull request. 4. get_files - Get the list of files changed in a pull request. Use with pagination parameters to control the number of results returned. 5. get_commits - Get the list of commits on a pull request. Use with pagination parameters to control the number of results returned. - 6. get_review_comments - Get review threads on a pull request. Each thread contains logically grouped review comments made on the same code location during pull request reviews. Returns threads with metadata (isResolved, isOutdated, isCollapsed) and their associated comments. Use cursor-based pagination (perPage, after) to control results. + 6. get_review_comments - Get review threads on a pull request. Each thread contains logically grouped review comments made on the same code location during pull request reviews. Returns thread metadata and comments with nullable current and original line-range coordinates (line, start_line, original_line, original_start_line). Current coordinates are omitted when unavailable, such as for outdated comments. Use cursor-based pagination (perPage, after) to control results. 7. get_reviews - Get the reviews on a pull request. When asked for review comments, use get_review_comments method. Use with pagination parameters to control the number of results returned. 8. get_comments - Get comments on a pull request. Use this if user doesn't specifically want review comments. Use with pagination parameters to control the number of results returned. 9. get_check_runs - Get check runs for the head commit of a pull request. Check runs are the individual CI/CD jobs and checks that run on the PR. diff --git a/docs/feature-flags.md b/docs/feature-flags.md index 0ed3f9dc0e..77ad68f0b2 100644 --- a/docs/feature-flags.md +++ b/docs/feature-flags.md @@ -357,7 +357,7 @@ runtime behavior (such as output formatting) won't appear here. ### `thread_resolution_reason` - **pull_request_review_write** - Write operations (create, submit, delete) on pull request reviews - - **Required OAuth Scopes**: `repo` + - **OAuth Challenge Scopes**: `repo` - `body`: Review comment text (string, optional) - `commitID`: SHA of commit to review (string, optional) - `event`: Review action to perform. (string, optional) diff --git a/pkg/github/__toolsnaps__/pull_request_read.snap b/pkg/github/__toolsnaps__/pull_request_read.snap index 41bc90b597..d518c7cad9 100644 --- a/pkg/github/__toolsnaps__/pull_request_read.snap +++ b/pkg/github/__toolsnaps__/pull_request_read.snap @@ -12,7 +12,7 @@ "type": "string" }, "method": { - "description": "Action to specify what pull request data needs to be retrieved from GitHub. \nPossible options: \n 1. get - Get details of a specific pull request.\n 2. get_diff - Get the diff of a pull request.\n 3. get_status - Get combined commit status of a head commit in a pull request.\n 4. get_files - Get the list of files changed in a pull request. Use with pagination parameters to control the number of results returned.\n 5. get_commits - Get the list of commits on a pull request. Use with pagination parameters to control the number of results returned.\n 6. get_review_comments - Get review threads on a pull request. Each thread contains logically grouped review comments made on the same code location during pull request reviews. Returns threads with metadata (isResolved, isOutdated, isCollapsed) and their associated comments. Use cursor-based pagination (perPage, after) to control results.\n 7. get_reviews - Get the reviews on a pull request. When asked for review comments, use get_review_comments method. Use with pagination parameters to control the number of results returned.\n 8. get_comments - Get comments on a pull request. Use this if user doesn't specifically want review comments. Use with pagination parameters to control the number of results returned.\n 9. get_check_runs - Get check runs for the head commit of a pull request. Check runs are the individual CI/CD jobs and checks that run on the PR.\n", + "description": "Action to specify what pull request data needs to be retrieved from GitHub. \nPossible options: \n 1. get - Get details of a specific pull request.\n 2. get_diff - Get the diff of a pull request.\n 3. get_status - Get combined commit status of a head commit in a pull request.\n 4. get_files - Get the list of files changed in a pull request. Use with pagination parameters to control the number of results returned.\n 5. get_commits - Get the list of commits on a pull request. Use with pagination parameters to control the number of results returned.\n 6. get_review_comments - Get review threads on a pull request. Each thread contains logically grouped review comments made on the same code location during pull request reviews. Returns thread metadata and comments with nullable current and original line-range coordinates (line, start_line, original_line, original_start_line). Current coordinates are omitted when unavailable, such as for outdated comments. Use cursor-based pagination (perPage, after) to control results.\n 7. get_reviews - Get the reviews on a pull request. When asked for review comments, use get_review_comments method. Use with pagination parameters to control the number of results returned.\n 8. get_comments - Get comments on a pull request. Use this if user doesn't specifically want review comments. Use with pagination parameters to control the number of results returned.\n 9. get_check_runs - Get check runs for the head commit of a pull request. Check runs are the individual CI/CD jobs and checks that run on the PR.\n", "enum": [ "get", "get_diff", diff --git a/pkg/github/pullrequests.go b/pkg/github/pullrequests.go index e512dfef1d..bfbc577597 100644 --- a/pkg/github/pullrequests.go +++ b/pkg/github/pullrequests.go @@ -36,7 +36,7 @@ Possible options: 3. get_status - Get combined commit status of a head commit in a pull request. 4. get_files - Get the list of files changed in a pull request. Use with pagination parameters to control the number of results returned. 5. get_commits - Get the list of commits on a pull request. Use with pagination parameters to control the number of results returned. - 6. get_review_comments - Get review threads on a pull request. Each thread contains logically grouped review comments made on the same code location during pull request reviews. Returns threads with metadata (isResolved, isOutdated, isCollapsed) and their associated comments. Use cursor-based pagination (perPage, after) to control results. + 6. get_review_comments - Get review threads on a pull request. Each thread contains logically grouped review comments made on the same code location during pull request reviews. Returns thread metadata and comments with nullable current and original line-range coordinates (line, start_line, original_line, original_start_line). Current coordinates are omitted when unavailable, such as for outdated comments. Use cursor-based pagination (perPage, after) to control results. 7. get_reviews - Get the reviews on a pull request. When asked for review comments, use get_review_comments method. Use with pagination parameters to control the number of results returned. 8. get_comments - Get comments on a pull request. Use this if user doesn't specifically want review comments. Use with pagination parameters to control the number of results returned. 9. get_check_runs - Get check runs for the head commit of a pull request. Check runs are the individual CI/CD jobs and checks that run on the PR. diff --git a/pkg/github/pullrequests_test.go b/pkg/github/pullrequests_test.go index 75f092206e..2bf98443d5 100644 --- a/pkg/github/pullrequests_test.go +++ b/pkg/github/pullrequests_test.go @@ -2302,8 +2302,16 @@ func Test_GetPullRequestComments(t *testing.T) { require.NoError(t, json.Unmarshal([]byte(textContent), &raw)) require.Len(t, raw.ReviewThreads, 1) require.Len(t, raw.ReviewThreads[0].Comments, 3) + assert.Equal(t, float64(86), raw.ReviewThreads[0].Comments[0]["line"]) + assert.Equal(t, float64(84), raw.ReviewThreads[0].Comments[0]["original_line"]) + assert.Equal(t, float64(73), raw.ReviewThreads[0].Comments[0]["start_line"]) + assert.Equal(t, float64(73), raw.ReviewThreads[0].Comments[0]["original_start_line"]) assert.NotContains(t, raw.ReviewThreads[0].Comments[1], "start_line") assert.NotContains(t, raw.ReviewThreads[0].Comments[1], "original_start_line") + assert.NotContains(t, raw.ReviewThreads[0].Comments[2], "line") + assert.NotContains(t, raw.ReviewThreads[0].Comments[2], "start_line") + assert.Equal(t, float64(178), raw.ReviewThreads[0].Comments[2]["original_line"]) + assert.Equal(t, float64(176), raw.ReviewThreads[0].Comments[2]["original_start_line"]) comment3 := thread.Comments[2] assert.Nil(t, comment3.Line)