From 4411f6d88adf81656ecfad030711721da38620be Mon Sep 17 00:00:00 2001 From: never-known-soldier Date: Tue, 19 Sep 2023 12:54:33 +0530 Subject: [PATCH 01/12] Update README.md file --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index fb7a0b64..56406ce0 100644 --- a/README.md +++ b/README.md @@ -84,13 +84,14 @@ See the [usage guide](./Usage.md) for instructions how to run the different tool
## Table of Contents +- [Table of Contents](#table-of-contents) - [Overview](#overview) - [Try it now](#try-it-now) - [Installation](#installation) -- [Usage guide](./Usage.md) - [How it works](#how-it-works) -- [Why use PR-Agent](#why-use-pr-agent) +- [Why use PR-Agent?](#why-use-pr-agent) - [Roadmap](#roadmap) +- [Similar Projects](#similar-projects)
@@ -103,8 +104,8 @@ See the [usage guide](./Usage.md) for instructions how to run the different tool | | Auto-Description | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | | Improve Code | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | :white_check_mark: | | | ⮑ Extended | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | :white_check_mark: | -| | Reflect and Review | :white_check_mark: | | :white_check_mark: | | :white_check_mark: | :white_check_mark: | -| | Update CHANGELOG.md | :white_check_mark: | | :white_check_mark: | | | | +| | Reflect and Review | :white_check_mark: | :white_check_mark: | :white_check_mark: | | :white_check_mark: | :white_check_mark: | +| | Update CHANGELOG.md | :white_check_mark: | :white_check_mark: | :white_check_mark: | | | | | | | | | | | | | USAGE | CLI | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | | App / webhook | :white_check_mark: | :white_check_mark: | | | | From 632de3f186b5db7adbdde972887aa2ea360fae23 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Wed, 20 Sep 2023 07:39:56 +0300 Subject: [PATCH 02/12] protections --- README.md | 2 - pr_agent/tools/pr_code_suggestions.py | 42 ++++++++++-------- pr_agent/tools/pr_description.py | 64 ++++++++++++++------------- pr_agent/tools/pr_reviewer.py | 44 +++++++++--------- 4 files changed, 82 insertions(+), 70 deletions(-) diff --git a/README.md b/README.md index 720277a0..12252194 100644 --- a/README.md +++ b/README.md @@ -86,14 +86,12 @@ See the [usage guide](./Usage.md) for instructions how to run the different tool
## Table of Contents -- [Table of Contents](#table-of-contents) - [Overview](#overview) - [Try it now](#try-it-now) - [Installation](#installation) - [How it works](#how-it-works) - [Why use PR-Agent?](#why-use-pr-agent) - [Roadmap](#roadmap) -- [Similar Projects](#similar-projects)
diff --git a/pr_agent/tools/pr_code_suggestions.py b/pr_agent/tools/pr_code_suggestions.py index ba45598e..4ba27dd8 100644 --- a/pr_agent/tools/pr_code_suggestions.py +++ b/pr_agent/tools/pr_code_suggestions.py @@ -48,27 +48,33 @@ class PRCodeSuggestions: get_settings().pr_code_suggestions_prompt.user) async def run(self): - logging.info('Generating code suggestions for PR...') - if get_settings().config.publish_output: - self.git_provider.publish_comment("Preparing review...", is_temporary=True) + try: + logging.info('Generating code suggestions for PR...') + if get_settings().config.publish_output: + self.git_provider.publish_comment("Preparing review...", is_temporary=True) - logging.info('Preparing PR review...') - if not self.is_extended: - await retry_with_fallback_models(self._prepare_prediction) - data = self._prepare_pr_code_suggestions() - else: - data = await retry_with_fallback_models(self._prepare_prediction_extended) + logging.info('Preparing PR review...') + if not self.is_extended: + await retry_with_fallback_models(self._prepare_prediction) + data = self._prepare_pr_code_suggestions() + else: + data = await retry_with_fallback_models(self._prepare_prediction_extended) + if (not data) or (not 'Code suggestions' in data): + logging.info('No code suggestions found for PR.') + return - if (not self.is_extended and get_settings().pr_code_suggestions.rank_suggestions) or \ - (self.is_extended and get_settings().pr_code_suggestions.rank_extended_suggestions): - logging.info('Ranking Suggestions...') - data['Code suggestions'] = await self.rank_suggestions(data['Code suggestions']) + if (not self.is_extended and get_settings().pr_code_suggestions.rank_suggestions) or \ + (self.is_extended and get_settings().pr_code_suggestions.rank_extended_suggestions): + logging.info('Ranking Suggestions...') + data['Code suggestions'] = await self.rank_suggestions(data['Code suggestions']) - if get_settings().config.publish_output: - logging.info('Pushing PR review...') - self.git_provider.remove_initial_comment() - logging.info('Pushing inline code suggestions...') - self.push_inline_code_suggestions(data) + if get_settings().config.publish_output: + logging.info('Pushing PR review...') + self.git_provider.remove_initial_comment() + logging.info('Pushing inline code suggestions...') + self.push_inline_code_suggestions(data) + except Exception as e: + logging.error(f"Failed to generate code suggestions for PR, error: {e}") async def _prepare_prediction(self, model: str): logging.info('Getting PR diff...') diff --git a/pr_agent/tools/pr_description.py b/pr_agent/tools/pr_description.py index 3c388eb4..d9600a2e 100644 --- a/pr_agent/tools/pr_description.py +++ b/pr_agent/tools/pr_description.py @@ -63,40 +63,44 @@ class PRDescription: """ Generates a PR description using an AI model and publishes it to the PR. """ - logging.info(f"Generating a PR description {self.pr_id}") - if get_settings().config.publish_output: - self.git_provider.publish_comment("Preparing pr description...", is_temporary=True) - await retry_with_fallback_models(self._prepare_prediction) + try: + logging.info(f"Generating a PR description {self.pr_id}") + if get_settings().config.publish_output: + self.git_provider.publish_comment("Preparing pr description...", is_temporary=True) - logging.info(f"Preparing answer {self.pr_id}") - if self.prediction: - self._prepare_data() - else: - return None + await retry_with_fallback_models(self._prepare_prediction) - pr_labels = [] - if get_settings().pr_description.publish_labels: - pr_labels = self._prepare_labels() - - if get_settings().pr_description.use_description_markers: - pr_title, pr_body = self._prepare_pr_answer_with_markers() - else: - pr_title, pr_body, = self._prepare_pr_answer() - full_markdown_description = f"## Title\n\n{pr_title}\n\n___\n{pr_body}" - - if get_settings().config.publish_output: - logging.info(f"Pushing answer {self.pr_id}") - if get_settings().pr_description.publish_description_as_comment: - self.git_provider.publish_comment(full_markdown_description) + logging.info(f"Preparing answer {self.pr_id}") + if self.prediction: + self._prepare_data() else: - self.git_provider.publish_description(pr_title, pr_body) - if get_settings().pr_description.publish_labels and self.git_provider.is_supported("get_labels"): - current_labels = self.git_provider.get_labels() - if current_labels is None: - current_labels = [] - self.git_provider.publish_labels(pr_labels + current_labels) - self.git_provider.remove_initial_comment() + return None + + pr_labels = [] + if get_settings().pr_description.publish_labels: + pr_labels = self._prepare_labels() + + if get_settings().pr_description.use_description_markers: + pr_title, pr_body = self._prepare_pr_answer_with_markers() + else: + pr_title, pr_body, = self._prepare_pr_answer() + full_markdown_description = f"## Title\n\n{pr_title}\n\n___\n{pr_body}" + + if get_settings().config.publish_output: + logging.info(f"Pushing answer {self.pr_id}") + if get_settings().pr_description.publish_description_as_comment: + self.git_provider.publish_comment(full_markdown_description) + else: + self.git_provider.publish_description(pr_title, pr_body) + if get_settings().pr_description.publish_labels and self.git_provider.is_supported("get_labels"): + current_labels = self.git_provider.get_labels() + if current_labels is None: + current_labels = [] + self.git_provider.publish_labels(pr_labels + current_labels) + self.git_provider.remove_initial_comment() + except Exception as e: + logging.error(f"Error generating PR description {self.pr_id}: {e}") return "" diff --git a/pr_agent/tools/pr_reviewer.py b/pr_agent/tools/pr_reviewer.py index b6bca536..01e3f276 100644 --- a/pr_agent/tools/pr_reviewer.py +++ b/pr_agent/tools/pr_reviewer.py @@ -95,28 +95,32 @@ class PRReviewer: """ Review the pull request and generate feedback. """ - if self.is_auto and not get_settings().pr_reviewer.automatic_review: - logging.info(f'Automatic review is disabled {self.pr_url}') - return None - logging.info(f'Reviewing PR: {self.pr_url} ...') + try: + if self.is_auto and not get_settings().pr_reviewer.automatic_review: + logging.info(f'Automatic review is disabled {self.pr_url}') + return None - if get_settings().config.publish_output: - self.git_provider.publish_comment("Preparing review...", is_temporary=True) - - await retry_with_fallback_models(self._prepare_prediction) - - logging.info('Preparing PR review...') - pr_comment = self._prepare_pr_review() - - if get_settings().config.publish_output: - logging.info('Pushing PR review...') - self.git_provider.publish_comment(pr_comment) - self.git_provider.remove_initial_comment() - - if get_settings().pr_reviewer.inline_code_comments: - logging.info('Pushing inline code comments...') - self._publish_inline_code_comments() + logging.info(f'Reviewing PR: {self.pr_url} ...') + + if get_settings().config.publish_output: + self.git_provider.publish_comment("Preparing review...", is_temporary=True) + + await retry_with_fallback_models(self._prepare_prediction) + + logging.info('Preparing PR review...') + pr_comment = self._prepare_pr_review() + + if get_settings().config.publish_output: + logging.info('Pushing PR review...') + self.git_provider.publish_comment(pr_comment) + self.git_provider.remove_initial_comment() + + if get_settings().pr_reviewer.inline_code_comments: + logging.info('Pushing inline code comments...') + self._publish_inline_code_comments() + except Exception as e: + logging.error(f"Failed to review PR: {e}") async def _prepare_prediction(self, model: str) -> None: """ From c2fe2fc657ea6bc0ac809cdcb96a1ccf1700d489 Mon Sep 17 00:00:00 2001 From: Ori Kotek Date: Wed, 20 Sep 2023 13:50:10 +0300 Subject: [PATCH 03/12] Added a release notes file --- RELEASE_NOTES.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 RELEASE_NOTES.md diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md new file mode 100644 index 00000000..2fcfd2e8 --- /dev/null +++ b/RELEASE_NOTES.md @@ -0,0 +1,24 @@ +## [Version 0.7] - 2023-09-20 + +### Docker Tags +- codiumai/pr-agent:0.7 +- codiumai/pr-agent:0.7-github_app +- codiumai/pr-agent:0.7-bitbucket-app +- codiumai/pr-agent:0.7-gitlab_webhook +- codiumai/pr-agent:0.7-github_polling +- codiumai/pr-agent:0.7-github_action + +### Added +- + +### Changed +- + +### Deprecated +- + +### Removed +- + +### Fixed +- From 497f84b3bdc69ee7dfa99c78d49e47d5b580b297 Mon Sep 17 00:00:00 2001 From: Ori Kotek Date: Wed, 20 Sep 2023 14:23:55 +0300 Subject: [PATCH 04/12] Update release notes --- Dockerfile.github_action_dockerhub | 2 +- RELEASE_NOTES.md | 23 ++++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Dockerfile.github_action_dockerhub b/Dockerfile.github_action_dockerhub index 61d64e25..5d7ec092 100644 --- a/Dockerfile.github_action_dockerhub +++ b/Dockerfile.github_action_dockerhub @@ -1 +1 @@ -FROM codiumai/pr-agent:github_action +FROM codiumai/pr-agent:0.7-github_action diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 2fcfd2e8..bdb0165b 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -8,17 +8,18 @@ - codiumai/pr-agent:0.7-github_polling - codiumai/pr-agent:0.7-github_action -### Added -- +### Added::Algo +- New tool /similar_issue - Currently on GitHub app and CLI: indexes the issues in the repo, find the most similar issues to the target issue. +- Describe markers: Empower the /describe tool with a templating capability (see more details in https://github.com/Codium-ai/pr-agent/pull/273). +- New feature in the /review tool - added an estimated effort estimation to the review (https://github.com/Codium-ai/pr-agent/pull/306). -### Changed -- - -### Deprecated -- - -### Removed -- +### Added::Infrastructure +- Implementation of a GitLab webhook. +- Implementation of a BitBucket app. ### Fixed -- +- Protection against no code suggestions generated. +- Resilience to repositories where the languages cannot be automatically detected. + + + From dcbd3132d1920589ffa30c599ee65bd9940089c6 Mon Sep 17 00:00:00 2001 From: Ori Kotek Date: Wed, 20 Sep 2023 14:41:24 +0300 Subject: [PATCH 05/12] Release notes --- Dockerfile.github_action_dockerhub | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile.github_action_dockerhub b/Dockerfile.github_action_dockerhub index 5d7ec092..61d64e25 100644 --- a/Dockerfile.github_action_dockerhub +++ b/Dockerfile.github_action_dockerhub @@ -1 +1 @@ -FROM codiumai/pr-agent:0.7-github_action +FROM codiumai/pr-agent:github_action From 1370a051f17965930bec7ed15aa8459c198b920b Mon Sep 17 00:00:00 2001 From: mrT23 Date: Wed, 20 Sep 2023 14:47:52 +0300 Subject: [PATCH 06/12] Update INSTALL.md --- INSTALL.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 5f107b20..9c46ac50 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -122,7 +122,7 @@ jobs: OPENAI_KEY: ${{ secrets.OPENAI_KEY }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} ``` -** if you want to pin your action to a specific commit for stability reasons +** if you want to pin your action to a specific release (v0.7 for example) for stability reasons, use: ```yaml on: pull_request: @@ -139,7 +139,7 @@ jobs: steps: - name: PR Agent action step id: pragent - uses: Codium-ai/pr-agent@ + uses: Codium-ai/pr-agent@v0.7 env: OPENAI_KEY: ${{ secrets.OPENAI_KEY }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 7545b2582388913d6113b194e177feb4aabd8bbe Mon Sep 17 00:00:00 2001 From: mrT23 Date: Wed, 20 Sep 2023 14:49:50 +0300 Subject: [PATCH 07/12] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 12252194..37c8724a 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ CodiumAI `PR-Agent` is an open-source tool aiming to help developers review pull See the [usage guide](./Usage.md) for instructions how to run the different tools from [CLI](./Usage.md#working-from-a-local-repo-cli), or by [online usage](./Usage.md#online-usage), as well as additional details on optional commands and configurations. +[Release notes](./RELEASE_NOTES.md)

Example results:

From fbfa186733efcccae5bfa3b11ea1e3e4029d80dd Mon Sep 17 00:00:00 2001 From: mrT23 Date: Wed, 20 Sep 2023 14:50:21 +0300 Subject: [PATCH 08/12] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 37c8724a..3a7f61a2 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ CodiumAI `PR-Agent` is an open-source tool aiming to help developers review pull See the [usage guide](./Usage.md) for instructions how to run the different tools from [CLI](./Usage.md#working-from-a-local-repo-cli), or by [online usage](./Usage.md#online-usage), as well as additional details on optional commands and configurations. + [Release notes](./RELEASE_NOTES.md)

Example results:

From fcd9821d106bc9e80d848a6999843e6af840fd36 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Wed, 20 Sep 2023 15:57:06 +0300 Subject: [PATCH 09/12] protections --- pr_agent/algo/git_patch_processing.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/pr_agent/algo/git_patch_processing.py b/pr_agent/algo/git_patch_processing.py index 1a2bd22b..79366354 100644 --- a/pr_agent/algo/git_patch_processing.py +++ b/pr_agent/algo/git_patch_processing.py @@ -40,6 +40,10 @@ def extend_patch(original_file_str, patch_str, num_lines) -> str: extended_patch_lines.extend( original_lines[start1 + size1 - 1:start1 + size1 - 1 + num_lines]) + res = list(match.groups()) + for i in range(len(res)): + if res[i] is None: + res[i] = 0 try: start1, size1, start2, size2 = map(int, match.groups()[:4]) except: # '@@ -0,0 +1 @@' case @@ -207,10 +211,15 @@ __old hunk__ old_content_lines = [] if match: prev_header_line = header_line + + res = list(match.groups()) + for i in range(len(res)): + if res[i] is None: + res[i] = 0 try: - start1, size1, start2, size2 = map(int, match.groups()[:4]) + start1, size1, start2, size2 = map(int, res[:4]) except: # '@@ -0,0 +1 @@' case - start1, size1, size2 = map(int, match.groups()[:3]) + start1, size1, size2 = map(int, res[:3]) start2 = 0 elif line.startswith('+'): From 992f51a0197d008fc6a58a8c92ec58bbaa9bac4a Mon Sep 17 00:00:00 2001 From: mrT23 Date: Wed, 20 Sep 2023 15:59:35 +0300 Subject: [PATCH 10/12] protections --- pr_agent/algo/git_patch_processing.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pr_agent/algo/git_patch_processing.py b/pr_agent/algo/git_patch_processing.py index 79366354..58d05235 100644 --- a/pr_agent/algo/git_patch_processing.py +++ b/pr_agent/algo/git_patch_processing.py @@ -45,11 +45,11 @@ def extend_patch(original_file_str, patch_str, num_lines) -> str: if res[i] is None: res[i] = 0 try: - start1, size1, start2, size2 = map(int, match.groups()[:4]) + start1, size1, start2, size2 = map(int, res[:4]) except: # '@@ -0,0 +1 @@' case - start1, size1, size2 = map(int, match.groups()[:3]) + start1, size1, size2 = map(int, res[:3]) start2 = 0 - section_header = match.groups()[4] + section_header = res[4] extended_start1 = max(1, start1 - num_lines) extended_size1 = size1 + (start1 - extended_start1) + num_lines extended_start2 = max(1, start2 - num_lines) From be54fb5bf8d4d6d726fac56cf61d44bc0d533dcf Mon Sep 17 00:00:00 2001 From: mrT23 Date: Thu, 21 Sep 2023 21:29:41 +0300 Subject: [PATCH 11/12] pr_id --- pr_agent/git_providers/git_provider.py | 3 +++ pr_agent/git_providers/github_provider.py | 7 +++++++ pr_agent/git_providers/gitlab_provider.py | 8 +++++++- pr_agent/tools/pr_description.py | 2 +- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/pr_agent/git_providers/git_provider.py b/pr_agent/git_providers/git_provider.py index 0911d2d2..a4a242f3 100644 --- a/pr_agent/git_providers/git_provider.py +++ b/pr_agent/git_providers/git_provider.py @@ -127,6 +127,9 @@ class GitProvider(ABC): def get_commit_messages(self): pass + def get_pr_id(self): + return "" + def get_main_pr_language(languages, files) -> str: """ Get the main language of the commit. Return an empty string if cannot determine. diff --git a/pr_agent/git_providers/github_provider.py b/pr_agent/git_providers/github_provider.py index 0521716b..39a58144 100644 --- a/pr_agent/git_providers/github_provider.py +++ b/pr_agent/git_providers/github_provider.py @@ -446,3 +446,10 @@ class GithubProvider(GitProvider): logging.info(f"Failed adding line link, error: {e}") return "" + + def get_pr_id(self): + try: + pr_id = f"{self.repo}/{self.pr_num}" + return pr_id + except: + return "" diff --git a/pr_agent/git_providers/gitlab_provider.py b/pr_agent/git_providers/gitlab_provider.py index a1d0b334..c88e01bd 100644 --- a/pr_agent/git_providers/gitlab_provider.py +++ b/pr_agent/git_providers/gitlab_provider.py @@ -378,4 +378,10 @@ class GitLabProvider(GitProvider): commit_messages_str = "" if max_tokens: commit_messages_str = clip_tokens(commit_messages_str, max_tokens) - return commit_messages_str \ No newline at end of file + return commit_messages_str + + def get_pr_id(self): + try: + return str(self.pr.id) + except: + return "" diff --git a/pr_agent/tools/pr_description.py b/pr_agent/tools/pr_description.py index d9600a2e..2214f3b6 100644 --- a/pr_agent/tools/pr_description.py +++ b/pr_agent/tools/pr_description.py @@ -29,7 +29,7 @@ class PRDescription: self.main_pr_language = get_main_pr_language( self.git_provider.get_languages(), self.git_provider.get_files() ) - self.pr_id = f"{self.git_provider.repo}/{self.git_provider.pr_num}" + self.pr_id = self.git_provider.get_pr_id() # Initialize the AI handler self.ai_handler = AiHandler() From 3e07fe618fc3267c59d3030fffc623ad88330628 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Thu, 21 Sep 2023 21:35:00 +0300 Subject: [PATCH 12/12] pr_id gitlab --- pr_agent/git_providers/gitlab_provider.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pr_agent/git_providers/gitlab_provider.py b/pr_agent/git_providers/gitlab_provider.py index c88e01bd..33cbee2b 100644 --- a/pr_agent/git_providers/gitlab_provider.py +++ b/pr_agent/git_providers/gitlab_provider.py @@ -382,6 +382,7 @@ class GitLabProvider(GitProvider): def get_pr_id(self): try: - return str(self.pr.id) + pr_id = self.mr.web_url + return pr_id except: return ""