From 24583b05f74728a5a869f1150b3b8f4aec69ba23 Mon Sep 17 00:00:00 2001 From: zmeir Date: Mon, 17 Jul 2023 10:41:02 +0300 Subject: [PATCH] Publish GitHub review comments with single API call --- pr_agent/git_providers/github_provider.py | 19 +++++++++++---- pr_agent/tools/pr_reviewer.py | 28 +++++++++++++++++++---- requirements.txt | 2 +- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/pr_agent/git_providers/github_provider.py b/pr_agent/git_providers/github_provider.py index 4f7d44bc..6d6d1c13 100644 --- a/pr_agent/git_providers/github_provider.py +++ b/pr_agent/git_providers/github_provider.py @@ -3,7 +3,7 @@ from datetime import datetime from typing import Optional, Tuple from urllib.parse import urlparse -from github import AppAuthentication, Github +from github import AppAuthentication, Github, Auth from pr_agent.config_loader import settings @@ -54,6 +54,10 @@ class GithubProvider(GitProvider): self.pr.comments_list.append(response) def publish_inline_comment(self, body: str, relevant_file: str, relevant_line_in_file: str): + logging.warning("Using deprecated `publish_inline_comment` - use `publish_inline_comments` instead") + self.publish_inline_comments([self.create_inline_comment(body, relevant_file, relevant_line_in_file)]) + + def create_inline_comment(self, body: str, relevant_file: str, relevant_line_in_file: str): self.diff_files = self.diff_files if self.diff_files else self.get_diff_files() position = -1 for file in self.diff_files: @@ -72,9 +76,16 @@ class GithubProvider(GitProvider): if position == -1: if settings.config.verbosity_level >= 2: logging.info(f"Could not find position for {relevant_file} {relevant_line_in_file}") + subject_type = "FILE" else: - path = relevant_file.strip() - self.pr.create_review_comment(body=body, commit_id=self.last_commit_id, path=path, position=position) + subject_type = "LINE" + path = relevant_file.strip() + # placeholder for future API support (already supported in single inline comment) + # return dict(body=body, path=path, position=position, subject_type=subject_type) + return dict(body=body, path=path, position=position) if subject_type == "LINE" else {} + + def publish_inline_comments(self, comments: list[dict]): + self.pr.create_review(commit=self.last_commit_id, comments=comments) def publish_code_suggestion(self, body: str, relevant_file: str, @@ -212,7 +223,7 @@ class GithubProvider(GitProvider): raise ValueError( "GitHub token is required when using user deployment. See: " "https://github.com/Codium-ai/pr-agent#method-2-run-from-source") from e - return Github(token) + return Github(auth=Auth.Token(token)) def _get_repo(self): return self.github_client.get_repo(self.repo) diff --git a/pr_agent/tools/pr_reviewer.py b/pr_agent/tools/pr_reviewer.py index afcb574b..fe4a6986 100644 --- a/pr_agent/tools/pr_reviewer.py +++ b/pr_agent/tools/pr_reviewer.py @@ -92,7 +92,13 @@ class PRReviewer: if settings.config.git_provider == 'github' and \ settings.pr_reviewer.inline_code_comments and \ 'Code suggestions' in data['PR Feedback']: - del data['PR Feedback']['Code suggestions'] + # keeping only code suggestions that can't be submitted as inline comments + data['PR Feedback']['Code suggestions'] = [ + d for d in data['PR Feedback']['Code suggestions'] + if any(key not in d for key in ('relevant file', 'relevant line in file', 'suggestion content')) + ] + if not data['PR Feedback']['Code suggestions']: + del data['PR Feedback']['Code suggestions'] markdown_text = convert_to_markdown(data) user = self.git_provider.get_user_id() @@ -118,9 +124,21 @@ class PRReviewer: except json.decoder.JSONDecodeError: data = try_fix_json(review) + comments = [] for d in data['PR Feedback']['Code suggestions']: - relevant_file = d['relevant file'].strip() - relevant_line_in_file = d['relevant line in file'].strip() - content = d['suggestion content'] + relevant_file = d.get('relevant file', '').strip() + relevant_line_in_file = d.get('relevant line in file', '').strip() + content = d.get('suggestion content', '') + if not relevant_file or not relevant_line_in_file or not content: + logging.info("Skipping inline comment with missing file/line/content") + continue - self.git_provider.publish_inline_comment(content, relevant_file, relevant_line_in_file) \ No newline at end of file + if settings.config.git_provider == 'github': + comment = self.git_provider.create_inline_comment(content, relevant_file, relevant_line_in_file) + if comment: + comments.append(comment) + else: + self.git_provider.publish_inline_comment(content, relevant_file, relevant_line_in_file) + + if comments: + self.git_provider.publish_inline_comments(comments) diff --git a/requirements.txt b/requirements.txt index 8695f709..399cd3ab 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ dynaconf==3.1.12 fastapi==0.99.0 -PyGithub==1.58.2 +PyGithub==1.59.* retry==0.9.2 openai==0.27.8 Jinja2==3.1.2