Skip to content

Commit 9606b67

Browse files
authored
Update gemini_review.py
1 parent e33a0ae commit 9606b67

File tree

1 file changed

+48
-29
lines changed

1 file changed

+48
-29
lines changed

hack/gemini_review.py

Lines changed: 48 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,45 @@
22
import os
33
from github import Github
44

5-
def get_pr_latest_commit_diff(repo_name, pr_number, github_token):
6-
"""Retrieves and cleans the diff from the latest commit of a PR, excluding test files."""
5+
def get_pr_latest_commit_diff_files(repo_name, pr_number, github_token):
6+
"""Retrieves diff information for each file in the latest commit of a PR, excluding test files."""
77
g = Github(github_token)
88
repo = g.get_repo(repo_name)
99
pr = repo.get_pull(pr_number)
1010

1111
try:
12-
commits = list(pr.get_commits()) # Get all commits in the PR
12+
commits = list(pr.get_commits())
1313
if commits:
14-
latest_commit = commits[-1] # Get the latest commit
14+
latest_commit = commits[-1]
1515
files = latest_commit.files
16-
combined_diff = ""
16+
diff_files = []
1717
for file in files:
18-
# Exclude test files (adjust the condition as needed)
1918
if not file.filename.endswith("_test.go") and not file.filename.endswith("_test.py") and not "/test/" in file.filename:
2019
if file.patch:
21-
combined_diff += file.patch + "\n"
22-
return combined_diff
20+
diff_files.append(file)
21+
return diff_files
2322
else:
24-
return None # No commits in the PR
23+
return None
2524
except Exception as e:
26-
print(f"Error getting diff from latest commit: {e}")
25+
print(f"Error getting diff files from latest commit: {e}")
2726
return None
2827

29-
def generate_gemini_review(diff, api_key):
30-
"""Generates a code review using the Gemini API."""
28+
def generate_gemini_review_with_annotations(diff_file, api_key):
29+
"""Generates a code review with annotations for a single file using the Gemini API."""
3130
genai.configure(api_key=api_key)
3231
model = genai.GenerativeModel('gemini-pro')
3332

34-
max_diff_length = 20000 # Example limit (adjust based on token count)
33+
diff = diff_file.patch
34+
max_diff_length = 20000 # Adjust based on token count
3535
if len(diff) > max_diff_length:
3636
diff = diff[:max_diff_length]
3737
diff += "\n... (truncated due to length limit) ..."
3838

3939
prompt = f"""
40-
Review the following code diff and provide feedback. Point out potential issues,
41-
suggest improvements, and highlight good practices. Keep the review concise.
40+
Review the following code diff from file `{diff_file.filename}` and provide feedback.
41+
Point out potential issues, suggest improvements, and highlight good practices.
42+
For each issue or suggestion, specify the line numbers from the diff where the change occurs.
43+
Keep the review concise.
4244
4345
```diff
4446
{diff}
@@ -47,33 +49,50 @@ def generate_gemini_review(diff, api_key):
4749
response = model.generate_content(prompt)
4850
return response.text if response.text else None
4951

50-
def post_github_comment(repo_name, pr_number, comment, github_token):
51-
"""Posts a comment to a GitHub pull request."""
52+
def post_github_review_comments(repo_name, pr_number, diff_file, review_comment, github_token):
53+
"""Posts review comments to a GitHub pull request, annotating specific lines."""
5254
g = Github(github_token)
5355
repo = g.get_repo(repo_name)
5456
pr = repo.get_pull(pr_number)
55-
pr.create_issue_comment(comment)
56-
print("Review comment posted successfully.")
57+
58+
if review_comment:
59+
# Parse the review comment for line number annotations
60+
lines_to_comment = []
61+
for line in review_comment.split('\n'):
62+
if "line" in line.lower() and ":" in line:
63+
try:
64+
line_num = int(line.lower().split("line")[1].split(":")[0].strip())
65+
lines_to_comment.append(line_num)
66+
except ValueError:
67+
continue # Skip lines that don't have a valid line number
68+
69+
if lines_to_comment:
70+
for line_num in lines_to_comment:
71+
pr.create_review_comment(body=review_comment, commit=pr.get_commits()[-1], path=diff_file.filename, position=line_num)
72+
print(f"Review comments for {diff_file.filename} posted successfully.")
73+
else:
74+
pr.create_issue_comment(f"Review for {diff_file.filename}:\n{review_comment}")
75+
print(f"Review for {diff_file.filename} posted as general comment since no line number was found.")
76+
77+
else:
78+
print(f"Gemini API returned no response for {diff_file.filename}.")
5779

5880
def main():
59-
"""Main function to orchestrate the Gemini PR review."""
81+
"""Main function to orchestrate the Gemini PR review with annotations."""
6082
api_key = os.environ.get('GEMINI_API_KEY')
6183
pr_number = int(os.environ.get('PR_NUMBER'))
6284
repo_name = os.environ.get('GITHUB_REPOSITORY')
6385
github_token = os.environ.get('GITHUB_TOKEN')
6486

65-
diff = get_pr_latest_commit_diff(repo_name, pr_number, github_token)
87+
diff_files = get_pr_latest_commit_diff_files(repo_name, pr_number, github_token)
6688

67-
if diff is None:
68-
print("Failed to retrieve PR diff from latest commit. Exiting.")
89+
if diff_files is None:
90+
print("Failed to retrieve PR diff files from latest commit. Exiting.")
6991
return
7092

71-
review_comment = generate_gemini_review(diff, api_key)
72-
73-
if review_comment:
74-
post_github_comment(repo_name, pr_number, review_comment, github_token)
75-
else:
76-
print("Gemini API returned no response.")
93+
for diff_file in diff_files:
94+
review_comment = generate_gemini_review_with_annotations(diff_file, api_key)
95+
post_github_review_comments(repo_name, pr_number, diff_file, review_comment, github_token)
7796

7897
if __name__ == "__main__":
7998
main()

0 commit comments

Comments
 (0)