From f6b3d57df0d319443252bc4ed0ea6550064b7091 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Thu, 13 Jul 2023 16:26:00 +0300 Subject: [PATCH 1/8] remove title and description --- README.md | 2 -- pr_agent/algo/utils.py | 1 - pr_agent/settings/pr_reviewer_prompts.toml | 7 +------ tests/unit/test_convert_to_markdown.py | 3 --- 4 files changed, 1 insertion(+), 12 deletions(-) diff --git a/README.md b/README.md index a2afa596e..b6514c052 100644 --- a/README.md +++ b/README.md @@ -183,7 +183,6 @@ Here is a quick overview of the different sub-tools of PR Reviewer: - PR Analysis - Summarize main theme - - PR description and title - PR type classification - Is the PR covered by relevant tests - Is this a focused PR @@ -199,7 +198,6 @@ This is how a typical output of the PR Reviewer looks like: #### PR Analysis - ๐ŸŽฏ **Main theme:** Adding language extension handler and token handler -- ๐Ÿ” **Description and title:** Yes - ๐Ÿ“Œ **Type of PR:** Enhancement - ๐Ÿงช **Relevant tests added:** No - โœจ **Focused PR:** Yes, the PR is focused on adding two new handlers for language extension and token counting. diff --git a/pr_agent/algo/utils.py b/pr_agent/algo/utils.py index 67c6f52b7..ff4bbdac0 100644 --- a/pr_agent/algo/utils.py +++ b/pr_agent/algo/utils.py @@ -11,7 +11,6 @@ def convert_to_markdown(output_data: dict) -> str: emojis = { "Main theme": "๐ŸŽฏ", - "Description and title": "๐Ÿ”", "Type of PR": "๐Ÿ“Œ", "Relevant tests added": "๐Ÿงช", "Unrelated changes": "โš ๏ธ", diff --git a/pr_agent/settings/pr_reviewer_prompts.toml b/pr_agent/settings/pr_reviewer_prompts.toml index 36b4c8cdf..f87563b72 100644 --- a/pr_agent/settings/pr_reviewer_prompts.toml +++ b/pr_agent/settings/pr_reviewer_prompts.toml @@ -13,10 +13,6 @@ You must use the following JSON schema to format your answer: "type": "string", "description": "a short explanation of the PR" }, - "Description and title": { - "type": "string", - "description": "yes\\no question: does this PR have a relevant description and title" - }, "Type of PR": { "type": "string", "enum": ["Bug fix", "Tests", "Bug fix with tests", "Refactoring", "Enhancement", "Documentation", "Other"] @@ -37,7 +33,7 @@ You must use the following JSON schema to format your answer: "PR Feedback": { "General PR suggestions": { "type": "string", - "description": "important suggestions for the contributors and maintainers of this PR, may include overall structure, primary purpose and best practices. consider using specific filenames, classes and functions names. explain yourself!" + "description": "General important suggestions for the contributors and maintainers of this PR. May include suggestions for overall structure, primary purpose, best practices, etc. consider using specific filenames, classes and functions names. explain yourself!" }, "Code suggestions": { "type": "array", @@ -75,7 +71,6 @@ Example output: "PR Analysis": { "Main theme": "xxx", - "Description and title": "Yes", "Type of PR": "Bug fix", {%- if require_tests %} "Relevant tests added": "No", diff --git a/tests/unit/test_convert_to_markdown.py b/tests/unit/test_convert_to_markdown.py index a40574ae0..02e3ceacc 100644 --- a/tests/unit/test_convert_to_markdown.py +++ b/tests/unit/test_convert_to_markdown.py @@ -46,7 +46,6 @@ class TestConvertToMarkdown: def test_simple_dictionary_input(self): input_data = { 'Main theme': 'Test', - 'Description and title': 'Test description', 'Type of PR': 'Test type', 'Relevant tests added': 'no', 'Unrelated changes': 'n/a', # won't be included in the output @@ -69,7 +68,6 @@ def test_simple_dictionary_input(self): } expected_output = """\ - ๐ŸŽฏ **Main theme:** Test -- ๐Ÿ” **Description and title:** Test description - ๐Ÿ“Œ **Type of PR:** Test type - ๐Ÿงช **Relevant tests added:** no - โœจ **Focused PR:** Yes @@ -108,7 +106,6 @@ def test_empty_dictionary_input(self): def test_dictionary_input_containing_only_empty_dictionaries(self): input_data = { 'Main theme': {}, - 'Description and title': {}, 'Type of PR': {}, 'Relevant tests added': {}, 'Unrelated changes': {}, From 04e15dbf982f7a6cc8529a2a362adb976c1d16f7 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Thu, 13 Jul 2023 16:34:56 +0300 Subject: [PATCH 2/8] General PR suggestions prompt --- pr_agent/settings/pr_reviewer_prompts.toml | 2 +- tests/unit/test_fix_output.py | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/pr_agent/settings/pr_reviewer_prompts.toml b/pr_agent/settings/pr_reviewer_prompts.toml index f87563b72..4a234905d 100644 --- a/pr_agent/settings/pr_reviewer_prompts.toml +++ b/pr_agent/settings/pr_reviewer_prompts.toml @@ -33,7 +33,7 @@ You must use the following JSON schema to format your answer: "PR Feedback": { "General PR suggestions": { "type": "string", - "description": "General important suggestions for the contributors and maintainers of this PR. May include suggestions for overall structure, primary purpose, best practices, etc. consider using specific filenames, classes and functions names. explain yourself!" + "description": "General suggestions and feedback for the contributors and maintainers of this PR. May include important suggestions for the overall structure, primary purpose, best practices, critical bugs, and other aspects of the PR. Explain your suggestions." }, "Code suggestions": { "type": "array", diff --git a/tests/unit/test_fix_output.py b/tests/unit/test_fix_output.py index af0794ad8..08e0504b4 100644 --- a/tests/unit/test_fix_output.py +++ b/tests/unit/test_fix_output.py @@ -7,11 +7,10 @@ class TestTryFixJson: # Tests that JSON with complete 'Code suggestions' section returns expected output def test_incomplete_code_suggestions(self): - review = '{"PR Analysis": {"Main theme": "xxx", "Description and title": "Yes", "Type of PR": "Bug fix"}, "PR Feedback": {"General PR suggestions": "..., `xxx`...", "Code suggestions": [{"relevant file": "xxx.py", "suggestion content": "xxx [important]"}, {"suggestion number": 2, "relevant file": "yyy.py", "suggestion content": "yyy [incomp...' + review = '{"PR Analysis": {"Main theme": "xxx", "Type of PR": "Bug fix"}, "PR Feedback": {"General PR suggestions": "..., `xxx`...", "Code suggestions": [{"relevant file": "xxx.py", "suggestion content": "xxx [important]"}, {"suggestion number": 2, "relevant file": "yyy.py", "suggestion content": "yyy [incomp...' expected_output = { 'PR Analysis': { 'Main theme': 'xxx', - 'Description and title': 'Yes', 'Type of PR': 'Bug fix' }, 'PR Feedback': { @@ -27,11 +26,10 @@ def test_incomplete_code_suggestions(self): assert try_fix_json(review) == expected_output def test_incomplete_code_suggestions_new_line(self): - review = '{"PR Analysis": {"Main theme": "xxx", "Description and title": "Yes", "Type of PR": "Bug fix"}, "PR Feedback": {"General PR suggestions": "..., `xxx`...", "Code suggestions": [{"relevant file": "xxx.py", "suggestion content": "xxx [important]"} \n\t, {"suggestion number": 2, "relevant file": "yyy.py", "suggestion content": "yyy [incomp...' + review = '{"PR Analysis": {"Main theme": "xxx", "Type of PR": "Bug fix"}, "PR Feedback": {"General PR suggestions": "..., `xxx`...", "Code suggestions": [{"relevant file": "xxx.py", "suggestion content": "xxx [important]"} \n\t, {"suggestion number": 2, "relevant file": "yyy.py", "suggestion content": "yyy [incomp...' expected_output = { 'PR Analysis': { 'Main theme': 'xxx', - 'Description and title': 'Yes', 'Type of PR': 'Bug fix' }, 'PR Feedback': { @@ -47,11 +45,10 @@ def test_incomplete_code_suggestions_new_line(self): assert try_fix_json(review) == expected_output def test_incomplete_code_suggestions_many_close_brackets(self): - review = '{"PR Analysis": {"Main theme": "xxx", "Description and title": "Yes", "Type of PR": "Bug fix"}, "PR Feedback": {"General PR suggestions": "..., `xxx`...", "Code suggestions": [{"relevant file": "xxx.py", "suggestion content": "xxx [important]"} \n, {"suggestion number": 2, "relevant file": "yyy.py", "suggestion content": "yyy }, [}\n ,incomp.} ,..' + review = '{"PR Analysis": {"Main theme": "xxx", "Type of PR": "Bug fix"}, "PR Feedback": {"General PR suggestions": "..., `xxx`...", "Code suggestions": [{"relevant file": "xxx.py", "suggestion content": "xxx [important]"} \n, {"suggestion number": 2, "relevant file": "yyy.py", "suggestion content": "yyy }, [}\n ,incomp.} ,..' expected_output = { 'PR Analysis': { 'Main theme': 'xxx', - 'Description and title': 'Yes', 'Type of PR': 'Bug fix' }, 'PR Feedback': { @@ -67,11 +64,10 @@ def test_incomplete_code_suggestions_many_close_brackets(self): assert try_fix_json(review) == expected_output def test_incomplete_code_suggestions_relevant_file(self): - review = '{"PR Analysis": {"Main theme": "xxx", "Description and title": "Yes", "Type of PR": "Bug fix"}, "PR Feedback": {"General PR suggestions": "..., `xxx`...", "Code suggestions": [{"relevant file": "xxx.py", "suggestion content": "xxx [important]"}, {"suggestion number": 2, "relevant file": "yyy.p' + review = '{"PR Analysis": {"Main theme": "xxx", "Type of PR": "Bug fix"}, "PR Feedback": {"General PR suggestions": "..., `xxx`...", "Code suggestions": [{"relevant file": "xxx.py", "suggestion content": "xxx [important]"}, {"suggestion number": 2, "relevant file": "yyy.p' expected_output = { 'PR Analysis': { 'Main theme': 'xxx', - 'Description and title': 'Yes', 'Type of PR': 'Bug fix' }, 'PR Feedback': { From bef17f72eb2c08b617df14ecc24084d663c5914f Mon Sep 17 00:00:00 2001 From: mrT23 Date: Thu, 13 Jul 2023 17:24:56 +0300 Subject: [PATCH 3/8] PRDescription --- pr_agent/cli.py | 6 ++ pr_agent/config_loader.py | 1 + pr_agent/settings/pr_description_prompts.toml | 45 +++++++++++ pr_agent/tools/pr_description.py | 81 +++++++++++++++++++ 4 files changed, 133 insertions(+) create mode 100644 pr_agent/settings/pr_description_prompts.toml create mode 100644 pr_agent/tools/pr_description.py diff --git a/pr_agent/cli.py b/pr_agent/cli.py index 66d00cd19..8b2800654 100644 --- a/pr_agent/cli.py +++ b/pr_agent/cli.py @@ -3,6 +3,7 @@ import logging import os +from pr_agent.tools.pr_description import PRDescription from pr_agent.tools.pr_questions import PRQuestions from pr_agent.tools.pr_reviewer import PRReviewer @@ -11,12 +12,17 @@ def run(): parser = argparse.ArgumentParser(description='AI based pull request analyzer') parser.add_argument('--pr_url', type=str, help='The URL of the PR to review', required=True) parser.add_argument('--question', type=str, help='Optional question to ask', required=False) + parser.add_argument('--pr_description', action='store_true', help='Optional question to ask', required=False) args = parser.parse_args() logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO")) if args.question: print(f"Question: {args.question} about PR {args.pr_url}") reviewer = PRQuestions(args.pr_url, args.question) asyncio.run(reviewer.answer()) + elif args.pr_description: + print(f"PR description: {args.pr_url}") + reviewer = PRDescription(args.pr_url) + asyncio.run(reviewer.describe()) else: print(f"Reviewing PR: {args.pr_url}") reviewer = PRReviewer(args.pr_url, cli_mode=True) diff --git a/pr_agent/config_loader.py b/pr_agent/config_loader.py index 550f743ef..ed98fccd4 100644 --- a/pr_agent/config_loader.py +++ b/pr_agent/config_loader.py @@ -11,6 +11,7 @@ "settings/configuration.toml", "settings/pr_reviewer_prompts.toml", "settings/pr_questions_prompts.toml", + "settings/pr_description_prompts.toml", "settings_prod/.secrets.toml" ]] ) diff --git a/pr_agent/settings/pr_description_prompts.toml b/pr_agent/settings/pr_description_prompts.toml new file mode 100644 index 000000000..76e8dd454 --- /dev/null +++ b/pr_agent/settings/pr_description_prompts.toml @@ -0,0 +1,45 @@ +[pr_description_prompt] +system="""You are CodiumAI-PR-Reviewer, a language model designed to review git pull requests. +Your task is to provide full description of the PR content. +- Make sure not to focus the new PR code (the '+' lines). + +You must use the following JSON schema to format your answer: +```json +{ + "PR Title": { + "type": "string", + "description": "an informative title for the PR, describing its main theme" + }, + "Type of PR": { + "type": "string", + "enum": ["Bug fix", "Tests", "Bug fix with tests", "Refactoring", "Enhancement", "Documentation", "Other"] + }, + "PR Description": { + "type": "string", + "description": "an informative and concise description of the PR" + }, + "PR Walkthrough": { + "type": "string", + "description": "a walkthrough of the PR changes. Review file by file, in bullet points, and shortly describe the changes in each file. Format: -`filename`: description of changes\n..." + } +} +""" + +user="""PR Info: +Title: '{{title}}' +Branch: '{{branch}}' +Description: '{{description}}' +{%- if language %} +Main language: {{language}} +{%- endif %} + + +The PR Git Diff: +``` +{{diff}} +``` +Note that lines in the diff body are prefixed with a symbol that represents the type of change: '-' for deletions, '+' for additions, and ' ' (a space) for unchanged lines. + +Response (should be a valid JSON, and nothing else): +```json +""" diff --git a/pr_agent/tools/pr_description.py b/pr_agent/tools/pr_description.py new file mode 100644 index 000000000..be237254a --- /dev/null +++ b/pr_agent/tools/pr_description.py @@ -0,0 +1,81 @@ +import copy +import json +import logging + +from jinja2 import Environment, StrictUndefined + +from pr_agent.algo.ai_handler import AiHandler +from pr_agent.algo.pr_processing import get_pr_diff +from pr_agent.algo.token_handler import TokenHandler +from pr_agent.algo.utils import convert_to_markdown +from pr_agent.config_loader import settings +from pr_agent.git_providers import get_git_provider +from pr_agent.git_providers.git_provider import get_main_pr_language + + +class PRDescription: + def __init__(self, pr_url: str): + self.git_provider = get_git_provider()(pr_url) + self.main_pr_language = get_main_pr_language( + self.git_provider.get_languages(), self.git_provider.get_files() + ) + self.ai_handler = AiHandler() + self.vars = { + "title": self.git_provider.pr.title, + "branch": self.git_provider.get_pr_branch(), + "description": self.git_provider.get_description(), + "language": self.main_pr_language, + "diff": "", # empty diff for initial calculation + } + self.token_handler = TokenHandler(self.git_provider.pr, + self.vars, + settings.pr_description_prompt.system, + settings.pr_description_prompt.user) + self.patches_diff = None + self.prediction = None + + async def describe(self): + logging.info('Answering a PR question...') + if settings.config.publish_review: + self.git_provider.publish_comment("Preparing pr description...", is_temporary=True) + logging.info('Getting PR diff...') + self.patches_diff = get_pr_diff(self.git_provider, self.token_handler) + logging.info('Getting AI prediction...') + self.prediction = await self._get_prediction() + logging.info('Preparing answer...') + pr_comment = self._prepare_pr_answer() + if settings.config.publish_review: + logging.info('Pushing answer...') + self.git_provider.publish_comment(pr_comment) + self.git_provider.remove_initial_comment() + return "" + + async def _get_prediction(self): + variables = copy.deepcopy(self.vars) + variables["diff"] = self.patches_diff # update diff + environment = Environment(undefined=StrictUndefined) + system_prompt = environment.from_string(settings.pr_description_prompt.system).render(variables) + user_prompt = environment.from_string(settings.pr_description_prompt.user).render(variables) + if settings.config.verbosity_level >= 2: + logging.info(f"\nSystem prompt:\n{system_prompt}") + logging.info(f"\nUser prompt:\n{user_prompt}") + model = settings.config.model + response, finish_reason = await self.ai_handler.chat_completion(model=model, temperature=0.2, + system=system_prompt, user=user_prompt) + return response + + def _prepare_pr_answer(self) -> str: + data = json.loads(self.prediction) + markdown_text = "" + # for key, value in data.items(): + # markdown_text += f"## {key}\n\n" + # markdown_text += f"{value}\n\n" + for key, value in data.items(): + markdown_text += f"{key}:\n" + if 'walkthrough' not in key.lower(): + markdown_text += f"**{value}**\n" + else: + markdown_text += f"{value}\n\n___\n" + if settings.config.verbosity_level >= 2: + logging.info(f"markdown_text:\n{markdown_text}") + return markdown_text From 2102cf424eee310130c1da91f40447fd721d0b1d Mon Sep 17 00:00:00 2001 From: mrT23 Date: Thu, 13 Jul 2023 17:31:28 +0300 Subject: [PATCH 4/8] stable --- pr_agent/settings/pr_description_prompts.toml | 6 ++++-- pr_agent/tools/pr_description.py | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/pr_agent/settings/pr_description_prompts.toml b/pr_agent/settings/pr_description_prompts.toml index 76e8dd454..33d7e01ed 100644 --- a/pr_agent/settings/pr_description_prompts.toml +++ b/pr_agent/settings/pr_description_prompts.toml @@ -18,11 +18,13 @@ You must use the following JSON schema to format your answer: "type": "string", "description": "an informative and concise description of the PR" }, - "PR Walkthrough": { + "PR Main Files Walkthrough": { "type": "string", - "description": "a walkthrough of the PR changes. Review file by file, in bullet points, and shortly describe the changes in each file. Format: -`filename`: description of changes\n..." + "description": "a walkthrough of the PR changes. Review main files, in bullet points, and shortly describe the changes in each file (up to 10 most important files). Format: -`filename`: description of changes\n..." } } + +Don't repeat the prompt in the answer, and avoid outputting the 'type' and 'description' fields. """ user="""PR Info: diff --git a/pr_agent/tools/pr_description.py b/pr_agent/tools/pr_description.py index be237254a..8ae01791a 100644 --- a/pr_agent/tools/pr_description.py +++ b/pr_agent/tools/pr_description.py @@ -72,10 +72,10 @@ def _prepare_pr_answer(self) -> str: # markdown_text += f"{value}\n\n" for key, value in data.items(): markdown_text += f"{key}:\n" - if 'walkthrough' not in key.lower(): - markdown_text += f"**{value}**\n" + if 'walkthrough' in key.lower(): + markdown_text += f"{value}\n" else: - markdown_text += f"{value}\n\n___\n" + markdown_text += f"**{value}**\n\n___\n" if settings.config.verbosity_level >= 2: logging.info(f"markdown_text:\n{markdown_text}") return markdown_text From 92cd55a8a5004e2a6a10a23e9f69a413db4cc177 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Thu, 13 Jul 2023 17:34:18 +0300 Subject: [PATCH 5/8] ignore current title --- pr_agent/settings/pr_description_prompts.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/pr_agent/settings/pr_description_prompts.toml b/pr_agent/settings/pr_description_prompts.toml index 33d7e01ed..2ec31b1cb 100644 --- a/pr_agent/settings/pr_description_prompts.toml +++ b/pr_agent/settings/pr_description_prompts.toml @@ -28,9 +28,7 @@ Don't repeat the prompt in the answer, and avoid outputting the 'type' and 'desc """ user="""PR Info: -Title: '{{title}}' Branch: '{{branch}}' -Description: '{{description}}' {%- if language %} Main language: {{language}} {%- endif %} From b29b5868872781ad1293ec37bb9b5f901c06ca69 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Thu, 13 Jul 2023 17:53:17 +0300 Subject: [PATCH 6/8] set as title --- pr_agent/git_providers/github_provider.py | 4 ++++ pr_agent/tools/pr_description.py | 20 +++++++++++--------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/pr_agent/git_providers/github_provider.py b/pr_agent/git_providers/github_provider.py index 49b0ccbe5..958a56e84 100644 --- a/pr_agent/git_providers/github_provider.py +++ b/pr_agent/git_providers/github_provider.py @@ -39,6 +39,10 @@ def get_diff_files(self) -> list[FilePatchInfo]: diff_files.append(FilePatchInfo(original_file_content_str, new_file_content_str, file.patch, file.filename)) return diff_files + def publish_description(self, pr_title: str, pr_body: str): + self.pr.edit(title=pr_title, body=pr_body) + # self.pr.create_issue_comment(pr_comment) + def publish_comment(self, pr_comment: str, is_temporary: bool = False): response = self.pr.create_issue_comment(pr_comment) if hasattr(response, "user") and hasattr(response.user, "login"): diff --git a/pr_agent/tools/pr_description.py b/pr_agent/tools/pr_description.py index 8ae01791a..334678e48 100644 --- a/pr_agent/tools/pr_description.py +++ b/pr_agent/tools/pr_description.py @@ -43,10 +43,10 @@ async def describe(self): logging.info('Getting AI prediction...') self.prediction = await self._get_prediction() logging.info('Preparing answer...') - pr_comment = self._prepare_pr_answer() + pr_title, pr_body = self._prepare_pr_answer() if settings.config.publish_review: logging.info('Pushing answer...') - self.git_provider.publish_comment(pr_comment) + self.git_provider.publish_description(pr_title, pr_body) self.git_provider.remove_initial_comment() return "" @@ -64,18 +64,20 @@ async def _get_prediction(self): system=system_prompt, user=user_prompt) return response - def _prepare_pr_answer(self) -> str: + def _prepare_pr_answer(self): data = json.loads(self.prediction) - markdown_text = "" + pr_body = "" # for key, value in data.items(): # markdown_text += f"## {key}\n\n" # markdown_text += f"{value}\n\n" + title = data['PR Title'] + del data['PR Title'] for key, value in data.items(): - markdown_text += f"{key}:\n" + pr_body += f"{key}:\n" if 'walkthrough' in key.lower(): - markdown_text += f"{value}\n" + pr_body += f"{value}\n" else: - markdown_text += f"**{value}**\n\n___\n" + pr_body += f"**{value}**\n\n___\n" if settings.config.verbosity_level >= 2: - logging.info(f"markdown_text:\n{markdown_text}") - return markdown_text + logging.info(f"title:\n{title}\n{pr_body}") + return title, pr_body From a5c3696a7e026595cd51344a04a616f54b8b4edb Mon Sep 17 00:00:00 2001 From: mrT23 Date: Thu, 13 Jul 2023 18:04:28 +0300 Subject: [PATCH 7/8] publish_description as abstract method --- pr_agent/git_providers/git_provider.py | 4 ++++ pr_agent/git_providers/gitlab_provider.py | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/pr_agent/git_providers/git_provider.py b/pr_agent/git_providers/git_provider.py index a30df90bc..e86f461d8 100644 --- a/pr_agent/git_providers/git_provider.py +++ b/pr_agent/git_providers/git_provider.py @@ -16,6 +16,10 @@ class GitProvider(ABC): def get_diff_files(self) -> list[FilePatchInfo]: pass + @abstractmethod + def publish_description(self, pr_title: str, pr_body: str): + pass + @abstractmethod def publish_comment(self, pr_comment: str, is_temporary: bool = False): pass diff --git a/pr_agent/git_providers/gitlab_provider.py b/pr_agent/git_providers/gitlab_provider.py index e9279a82a..485e0cf93 100644 --- a/pr_agent/git_providers/gitlab_provider.py +++ b/pr_agent/git_providers/gitlab_provider.py @@ -44,6 +44,10 @@ def get_diff_files(self) -> list[FilePatchInfo]: def get_files(self): return [change['new_path'] for change in self.mr.changes()['changes']] + def publish_description(self, pr_title: str, pr_body: str): + logging.exception("Not implemented yet") + pass + def publish_comment(self, mr_comment: str, is_temporary: bool = False): comment = self.mr.notes.create({'body': mr_comment}) if is_temporary: From c0a7976e9bec2491107fdc454196a723cca04c0e Mon Sep 17 00:00:00 2001 From: mrT23 Date: Thu, 13 Jul 2023 18:26:35 +0300 Subject: [PATCH 8/8] diff_files --- pr_agent/algo/pr_processing.py | 4 ++-- pr_agent/git_providers/github_provider.py | 2 -- pr_agent/tools/pr_reviewer.py | 11 ++++++++--- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/pr_agent/algo/pr_processing.py b/pr_agent/algo/pr_processing.py index 63fe0caa8..f99d126cf 100644 --- a/pr_agent/algo/pr_processing.py +++ b/pr_agent/algo/pr_processing.py @@ -24,10 +24,10 @@ def get_pr_diff(git_provider: Union[GithubProvider, Any], token_handler: TokenHa Returns a string with the diff of the PR. If needed, apply diff minimization techniques to reduce the number of tokens """ - git_provider.pr.files = list(git_provider.get_diff_files()) + git_provider.pr.diff_files = list(git_provider.get_diff_files()) # get pr languages - pr_languages = sort_files_by_main_languages(git_provider.get_languages(), git_provider.pr.files) + pr_languages = sort_files_by_main_languages(git_provider.get_languages(), git_provider.pr.diff_files) # generate a standard diff string, with patch extension patches_extended, total_tokens = pr_generate_extended_diff(pr_languages, token_handler) diff --git a/pr_agent/git_providers/github_provider.py b/pr_agent/git_providers/github_provider.py index 958a56e84..16ec6293d 100644 --- a/pr_agent/git_providers/github_provider.py +++ b/pr_agent/git_providers/github_provider.py @@ -26,8 +26,6 @@ def set_pr(self, pr_url: str): self.pr = self._get_pr() def get_files(self): - if hasattr(self.pr, 'files'): - return self.pr.files return self.pr.get_files() def get_diff_files(self) -> list[FilePatchInfo]: diff --git a/pr_agent/tools/pr_reviewer.py b/pr_agent/tools/pr_reviewer.py index 23af99d5c..eabf89550 100644 --- a/pr_agent/tools/pr_reviewer.py +++ b/pr_agent/tools/pr_reviewer.py @@ -122,22 +122,27 @@ def _publish_inline_code_comments(self): pr = self.git_provider.pr last_commit_id = list(pr.get_commits())[-1] - files = list(self.git_provider.get_diff_files()) + if hasattr(pr, 'diff_files'): # prevent bringing all the files again + diff_files = pr.diff_files + else: + diff_files = list(self.git_provider.get_diff_files()) 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'] position = -1 - for file in files: + for file in diff_files: if file.filename.strip() == relevant_file: patch = file.patch patch_lines = patch.splitlines() for i, line in enumerate(patch_lines): if relevant_line_in_file in line: position = i + break if position == -1: - logging.info(f"Could not find position for {relevant_file} {relevant_line_in_file}") + if settings.config.verbosity_level >= 2: + logging.info(f"Could not find position for {relevant_file} {relevant_line_in_file}") else: body = content path = relevant_file.strip()