feat: add useGeminiReview hook with comment cleanup#189
Conversation
Introduces a specialized hook to handle Gemini code reviews. This
ensures a cleaner pull request timeline by removing previous
**gemini-code-assist** comments before posting a new review request.
* Encapsulates the review logic away from the button component.
* Automatically deletes existing assistant comments.
* Invalidates the `open-prs` query state upon successful completion.
```mermaid
sequenceDiagram
participant UI as GeminiReviewButton
participant Hook as useGeminiReview
participant API as GitHub API
UI->>Hook: mutate()
Hook->>API: listComments()
API-->>Hook: comments
Note over Hook: Filter "gemini-code-assist" comments
loop Each existing comment
Hook->>API: deleteComment()
end
Hook->>API: createComment("/gemini review")
Hook->>Hook: invalidate open-prs
```
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Pull Request Test Coverage Report for Build 23121634691Details
💛 - Coveralls |
Extract hardcoded strings for the Gemini user login and the review command into named constants to improve maintainability.
Update the `GEMINI_USER_LOGIN` constant to include the `[bot]` suffix to match GitHub's bot naming convention. This ensures the hook correctly filters and deletes previous review comments.
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
The hook now identifies and removes review comments created by the
Gemini bot in addition to standard issue comments. This ensures a
cleaner PR state by removing all previous automated feedback before
a new review cycle begins.
```mermaid
graph TD
Start[Start Cleanup] --> GetIssue[Fetch Issue Comments]
Start --> GetReview[Fetch Review Comments]
GetIssue --> FilterIssue[Filter Gemini User]
GetReview --> FilterReview[Filter Gemini User]
FilterIssue --> DeleteIssue[Delete Issue Comments]
FilterReview --> DeleteReview[Delete Review Comments]
```
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces a new useGeminiReview hook, which is a great improvement as it encapsulates the logic for handling Gemini code reviews and cleans up the component code. The implementation is solid, but I've identified a couple of opportunities to improve performance by parallelizing API calls within the new hook. My suggestions aim to make the process of cleaning up old comments and fetching data more efficient.
| const comments = await octokit.paginate(octokit.issues.listComments, { | ||
| owner, | ||
| repo, | ||
| issue_number: pull_number, | ||
| per_page: 100, | ||
| }); | ||
|
|
||
| const geminiComments = comments.filter((c) => c.user?.login === GEMINI_USER_LOGIN); | ||
|
|
||
| const reviewComments = await octokit.paginate(octokit.pulls.listReviewComments, { | ||
| owner, | ||
| repo, | ||
| pull_number, | ||
| per_page: 100, | ||
| }); | ||
|
|
||
| const geminiReviewComments = reviewComments.filter((c) => c.user?.login === GEMINI_USER_LOGIN); |
There was a problem hiding this comment.
The two paginate calls to fetch issue comments and review comments are executed sequentially. Since they are independent, you can run them in parallel using Promise.all to improve performance by reducing the total wait time for data fetching.
| const comments = await octokit.paginate(octokit.issues.listComments, { | |
| owner, | |
| repo, | |
| issue_number: pull_number, | |
| per_page: 100, | |
| }); | |
| const geminiComments = comments.filter((c) => c.user?.login === GEMINI_USER_LOGIN); | |
| const reviewComments = await octokit.paginate(octokit.pulls.listReviewComments, { | |
| owner, | |
| repo, | |
| pull_number, | |
| per_page: 100, | |
| }); | |
| const geminiReviewComments = reviewComments.filter((c) => c.user?.login === GEMINI_USER_LOGIN); | |
| const [comments, reviewComments] = await Promise.all([ | |
| octokit.paginate(octokit.issues.listComments, { | |
| owner, | |
| repo, | |
| issue_number: pull_number, | |
| per_page: 100, | |
| }), | |
| octokit.paginate(octokit.pulls.listReviewComments, { | |
| owner, | |
| repo, | |
| pull_number, | |
| per_page: 100, | |
| }), | |
| ]); | |
| const geminiComments = comments.filter((c) => c.user?.login === GEMINI_USER_LOGIN); | |
| const geminiReviewComments = reviewComments.filter((c) => c.user?.login === GEMINI_USER_LOGIN); |
| for (const comment of geminiComments) { | ||
| try { | ||
| await octokit.issues.deleteComment({ owner, repo, comment_id: comment.id }); | ||
| } catch (e) { | ||
| console.error(`Failed to delete issue comment ${comment.id}`, e); | ||
| } | ||
| } | ||
|
|
||
| for (const comment of geminiReviewComments) { | ||
| try { | ||
| await octokit.pulls.deleteReviewComment({ owner, repo, comment_id: comment.id }); | ||
| } catch (e) { | ||
| console.error(`Failed to delete review comment ${comment.id}`, e); | ||
| } | ||
| } |
There was a problem hiding this comment.
The loops for deleting comments run sequentially, which can be slow if there are many comments to delete. You can significantly improve performance by running these deletion requests in parallel using Promise.all. This also makes the code more concise and handles errors for individual deletions gracefully without needing explicit try...catch blocks inside loops.
const deletionPromises = [
...geminiComments.map((comment) =>
octokit.issues.deleteComment({ owner, repo, comment_id: comment.id }).catch((e) => {
console.error(`Failed to delete issue comment ${comment.id}`, e);
}),
),
...geminiReviewComments.map((comment) =>
octokit.pulls.deleteReviewComment({ owner, repo, comment_id: comment.id }).catch((e) => {
console.error(`Failed to delete review comment ${comment.id}`, e);
}),
),
];
await Promise.all(deletionPromises);
Introduces a specialized hook to handle Gemini code reviews. This ensures a cleaner pull request timeline by removing previous gemini-code-assist comments before posting a new review request.
open-prsquery state upon successful completion.sequenceDiagram participant UI as GeminiReviewButton participant Hook as useGeminiReview participant API as GitHub API UI->>Hook: mutate() Hook->>API: listComments() API-->>Hook: comments Note over Hook: Filter "gemini-code-assist" comments loop Each existing comment Hook->>API: deleteComment() end Hook->>API: createComment("/gemini review") Hook->>Hook: invalidate open-prs