-
Notifications
You must be signed in to change notification settings - Fork 0
Description
AI-Focused PR Review Capabilities for Forked gh CLI (agynio/github-cli)
Overview
This spec defines PR review operations in our forked gh CLI, optimized for AI agent workflows. The UX uses gh subcommands and wraps GitHub’s REST API v3. GraphQL tradeoffs are noted, but REST is preferred for stability, coverage of review comments, and ease of payload shaping.
Authentication and Scopes
Auth mechanism: Inherits gh auth token (GH_TOKEN) usage.
Required scopes:
repo (for private repositories; read and write operations on PRs/reviews/comments).
No additional scopes required for public repository read operations.
Rate limiting:
REST: 5,000 requests/hour per authenticated token.
Pagination: Standard per_page and page query params; gh should expose flags to control them.
Operation 1: View Inline Review Comments by Review ID or Latest Review
Recommendation: REST (preferred)
Tradeoffs:
REST offers direct endpoints for listing reviews and review comments with essential fields (e.g., path, position, in_reply_to_id).
GraphQL could fetch nested thread structures in fewer calls but requires node IDs, introduces field cost accounting, and complicates stable ID handling vs numeric IDs in REST.
For “latest review,” REST list + selection by submitted_at/state is reliable; thread grouping can be reconstructed client-side via in_reply_to_id.
REST Endpoints and Methods
List reviews for a PR (to locate latest submitted review):
GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews
List comments for a specific review:
GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments
Minimal Input Parameters
owner: string (e.g., "agynio")
repo: string (e.g., "cli")
pull_number: int (e.g., 42)
review_id: int (when provided; e.g., 12345)
latest: boolean (optional; if true, find latest submitted review)
Pagination (optional): per_page int (default 30), page int (default 1)
Examples
By review ID:
gh pr review-comments view 42 --review-id 12345
Latest submitted review on PR:
gh pr review-comments view 42 --latest
With pagination:
gh pr review-comments view 42 --review-id 12345 --per-page 100 --page 2
Minimal Output Structures (JSON schemas)
Review (from list endpoint; subset for selection):
{
"id": 0,
"user": { "login": "" },
"state": "APPROVED",
"body": null,
"commit_id": null,
"submitted_at": "",
"author_association": ""
}
Review Comment (from comments endpoint; essential fields):
{
"id": 0,
"pull_request_review_id": 0,
"in_reply_to_id": 0,
"body": "",
"user": { "login": "" },
"path": "",
"position": 0,
"line": 0,
"side": "RIGHT",
"start_line": 0,
"start_side": "RIGHT",
"original_commit_id": "",
"created_at": "",
"updated_at": ""
}
Edge Cases and Constraints
Latest review: Select the most recent review with state != "PENDING" by submitted_at (if submitted_at null, treat as not submitted).
Outdated comments: position becomes null; retain original_commit_id and path for context.
Multi-line range comments: If present, line/side and start_line/start_side may be returned; REST review comments endpoint carries these fields when created via line-based comment APIs.
Threading: Reconstruct threads client-side using in_reply_to_id and grouping by pull_request_review_id.
Pagination: Use per_page/page; agents should iterate when comments exceed defaults.
Proposed gh UX
Subcommand:
gh pr review-comments view
Flags:
--review-id : Target specific review ID.
--latest: Use latest submitted review on PR.
--per-page , --page : Pagination controls.
Output:
Default: compact JSON array of minimal comment fields; optional --json to control fields; optional --human to format as text for agents.
Flag to API Mapping:
--review-id => GET /pulls/{number}/reviews/{id}/comments
--latest => GET /pulls/{number}/reviews then select by submitted_at; follow with GET /pulls/{number}/reviews/{id}/comments
--per-page, --page => query params
Operation 2: Reply to a Comment in a Review Thread by Comment ID
Recommendation: REST (preferred)
Tradeoffs:
REST exposes a dedicated replies endpoint bound to numeric comment IDs.
GraphQL requires node IDs and thread-based mutations; additional complexity not needed for simple replies.
REST Endpoint and Method
POST /repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies
Minimal Input Parameters
owner: string
repo: string
pull_number: int
comment_id: int (must be a review comment ID, not a PR conversation “issue comment” ID)
body: string (reply text; markdown supported)
Example
gh pr review-comments reply 42 --comment-id 987654 --body "Thanks! Fixed in 3ad2c7."
Request Payload (JSON)
{ "body": "Thanks! Fixed in 3ad2c7." }
Minimal Output Structure (JSON schema)
{
"id": 0,
"pull_request_review_id": 0,
"in_reply_to_id": 0,
"body": "",
"user": { "login": "" },
"path": "",
"position": 0,
"line": 0,
"side": "RIGHT",
"created_at": "",
"updated_at": ""
}
Edge Cases and Constraints
Comment type: Must be a review comment; issue-style PR comments are not supported by this endpoint.
Outdated threads: Reply is still allowed; position may be null.
Body length limits: Practical limit ~64KB; avoid excessively long replies.
Rate limiting: Standard; single write per call.
Proposed gh UX
Subcommand:
gh pr review-comments reply
Flags:
--comment-id (required)
--body | --body-file (mutually exclusive)
Output:
JSON of created reply with minimal fields.
Flag to API Mapping:
--comment-id => path param in replies endpoint
--body/--body-file => payload body
Operation 3: Inline Review — split into open, add comments, submit
A) Open Review (Create a Pending Review)
Endpoint: POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews (omit event to create PENDING)
Minimal Input Parameters
owner: string
repo: string
pull_number: int
body: string (optional)
commit_id: string (optional)
CLI: gh pr review open [--body|--body-file] [--commit-sha]
Request (minimal):
{
"body": "Initial notes for pending review",
"commit_id": "abc123def456..."
}
Response (minimal):
{
"id": 223344,
"state": "PENDING",
"user": { "login": "reviewerA" },
"submitted_at": null,
"commit_id": "abc123def456..."
}
Optional Abort pending review:
Endpoint: DELETE /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}
CLI: gh pr review abort --review-id
B) Add Comments to a Pending Review
Endpoint: POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments
Minimal Input Parameters
owner: string
repo: string
pull_number: int
review_id: int (PENDING)
comment(s): path + position + body OR path + line + side (+ optional range)
CLI: gh pr review add-comment --review-id [--add-comment ...] [--comments-file ]
Request (position-based example):
{
"path": "src/foo/bar.go",
"position": 12,
"body": "Nit: rename var"
}
Request (line-based with optional range):
{
"path": "src/foo/bar.go",
"line": 45,
"side": "RIGHT",
"start_line": 40,
"start_side": "RIGHT",
"body": "Consider extracting helper"
}
Response (minimal):
{
"id": 987654,
"pull_request_review_id": 223344,
"in_reply_to_id": null,
"body": "Nit: rename var",
"user": { "login": "reviewerA" },
"path": "src/foo/bar.go",
"position": 12,
"created_at": "2024-08-10T12:34:56Z",
"updated_at": "2024-08-10T12:34:56Z"
}
C) Close (Submit) Review with Terminal Event
Endpoint: POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/events
Minimal Input Parameters
owner: string
repo: string
pull_number: int
review_id: int (PENDING)
event: COMMENT | APPROVE | REQUEST_CHANGES
body: string (optional; recommended for REQUEST_CHANGES)
CLI: gh pr review submit --review-id --event {COMMENT|APPROVE|REQUEST_CHANGES} [--body|--body-file]
Request (minimal):
{
"event": "REQUEST_CHANGES",
"body": "Please address the noted issues."
}
Response (minimal):
{
"id": 223344,
"state": "CHANGES_REQUESTED",
"body": "Please address the noted issues.",
"submitted_at": "2024-08-10T13:00:00Z"
}
Notes
Only PENDING reviews accept added comments and can be submitted.
Invalid path/position/line/side → 422.
Multi-comment adds: CLI iterates per comment and surfaces per-item success/failure.
Error Handling and Status Codes
200/201: OK/Created
400: Bad input (e.g., malformed JSON)
401/403: Auth/scopes issues
404: PR or review/comment not found
409: Conflict (e.g., adding comments to non-PENDING review)
422: Unprocessable Entity (e.g., invalid position/path mapping)
429: Rate limit exceeded (gh should surface X-RateLimit headers)
Appendix: Sample gh api Invocations (for reference/testing)
List reviews:
gh api repos/:owner/:repo/pulls/:number/reviews
List comments for a review:
gh api repos/:owner/:repo/pulls/:number/reviews/:review_id/comments --paginate
Reply to a review comment:
gh api --method POST repos/:owner/:repo/pulls/:number/comments/:comment_id/replies -f body='Thanks!'
Open a review (pending):
gh api --method POST repos/:owner/:repo/pulls/:number/reviews --input open.json
Add a review comment to a pending review:
gh api --method POST repos/:owner/:repo/pulls/:number/reviews/:review_id/comments --input comment.json
Submit a review:
gh api --method POST repos/:owner/:repo/pulls/:number/reviews/:review_id/events -f event='REQUEST_CHANGES' -f body='Please address notes.'.