From cf4d007737ac3467ed838a32a6db4d19105974e1 Mon Sep 17 00:00:00 2001 From: Zohar Meir <33152084+zmeir@users.noreply.github.com> Date: Tue, 31 Oct 2023 00:00:48 +0200 Subject: [PATCH 01/18] Fix commands list for push trigger --- pr_agent/servers/github_app.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pr_agent/servers/github_app.py b/pr_agent/servers/github_app.py index 7b33fdc2..36cc3e88 100644 --- a/pr_agent/servers/github_app.py +++ b/pr_agent/servers/github_app.py @@ -122,7 +122,7 @@ async def handle_request(body: Dict[str, Any], event: str): if body.get("requested_reviewer", {}).get("login", "") != bot_user: return {} get_logger().info(f"Performing review for {api_url=} because of {event=} and {action=}") - await _perform_commands(agent, body, api_url, log_context) + await _perform_commands("pr_commands", agent, body, api_url, log_context) # handle pull_request event with synchronize action - "push trigger" for new commits elif event == 'pull_request' and action == 'synchronize' and get_settings().github_app.handle_push_trigger: @@ -174,7 +174,7 @@ async def handle_request(body: Dict[str, Any], event: str): get_logger().info(f"Skipping incremental review because there was no initial review for {api_url=} yet") return {} get_logger().info(f"Performing incremental review for {api_url=} because of {event=} and {action=}") - await _perform_commands(agent, body, api_url, log_context) + await _perform_commands("push_commands", agent, body, api_url, log_context) finally: # release the waiting task block @@ -203,9 +203,9 @@ def _check_pull_request_event(action: str, body: dict, log_context: dict, bot_us return pull_request, api_url -async def _perform_commands(agent: PRAgent, body: dict, api_url: str, log_context: dict): +async def _perform_commands(commands_conf: str, agent: PRAgent, body: dict, api_url: str, log_context: dict): apply_repo_settings(api_url) - commands = get_settings().github_app.pr_commands + commands = get_settings().get(f"github_app.{commands_conf}") for command in commands: split_command = command.split(" ") command = split_command[0] From c623c3baf4b9915d6ca89a8312aa14f40e1d4ea2 Mon Sep 17 00:00:00 2001 From: zmeir Date: Wed, 1 Nov 2023 21:02:25 +0200 Subject: [PATCH 02/18] Added new configurations to prevent too frequent incremental commits on push trigger --- pr_agent/git_providers/git_provider.py | 11 ++++++-- pr_agent/git_providers/github_provider.py | 4 +-- pr_agent/settings/configuration.toml | 6 +++++ pr_agent/tools/pr_reviewer.py | 31 ++++++++++++++++++++--- 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/pr_agent/git_providers/git_provider.py b/pr_agent/git_providers/git_provider.py index 9dee9e3c..3511c2a6 100644 --- a/pr_agent/git_providers/git_provider.py +++ b/pr_agent/git_providers/git_provider.py @@ -190,6 +190,13 @@ class IncrementalPR: def __init__(self, is_incremental: bool = False): self.is_incremental = is_incremental self.commits_range = None - self.first_new_commit_sha = None - self.last_seen_commit_sha = None + self.first_new_commit = None + self.last_seen_commit = None + @property + def first_new_commit_sha(self): + return None if self.first_new_commit is None else self.first_new_commit.sha + + @property + def last_seen_commit_sha(self): + return None if self.last_seen_commit is None else self.last_seen_commit.sha diff --git a/pr_agent/git_providers/github_provider.py b/pr_agent/git_providers/github_provider.py index 40b0e121..5ed35d04 100644 --- a/pr_agent/git_providers/github_provider.py +++ b/pr_agent/git_providers/github_provider.py @@ -66,10 +66,10 @@ class GithubProvider(GitProvider): first_new_commit_index = None for index in range(len(self.commits) - 1, -1, -1): if self.commits[index].commit.author.date > last_review_time: - self.incremental.first_new_commit_sha = self.commits[index].sha + self.incremental.first_new_commit = self.commits[index] first_new_commit_index = index else: - self.incremental.last_seen_commit_sha = self.commits[index].sha + self.incremental.last_seen_commit = self.commits[index] break return self.commits[first_new_commit_index:] if first_new_commit_index is not None else [] diff --git a/pr_agent/settings/configuration.toml b/pr_agent/settings/configuration.toml index ffe6d39d..06519f0a 100644 --- a/pr_agent/settings/configuration.toml +++ b/pr_agent/settings/configuration.toml @@ -25,6 +25,9 @@ inline_code_comments = false ask_and_reflect=false automatic_review=true remove_previous_review_comment=false +require_all_thresholds_for_incremental_review=false +minimal_commits_for_incremental_review=0 +minimal_minutes_for_incremental_review=0 extra_instructions = "" [pr_description] # /describe # @@ -105,6 +108,9 @@ push_commands = [ --pr_reviewer.num_code_suggestions=0 \ --pr_reviewer.inline_code_comments=false \ --pr_reviewer.remove_previous_review_comment=true \ + --pr_reviewer.require_all_thresholds_for_incremental_review=false \ + --pr_reviewer.minimal_commits_for_incremental_review=5 \ + --pr_reviewer.minimal_minutes_for_incremental_review=30 \ --pr_reviewer.extra_instructions='' \ """ ] diff --git a/pr_agent/tools/pr_reviewer.py b/pr_agent/tools/pr_reviewer.py index 7cf561e2..c13e7edd 100644 --- a/pr_agent/tools/pr_reviewer.py +++ b/pr_agent/tools/pr_reviewer.py @@ -1,4 +1,5 @@ import copy +import datetime from collections import OrderedDict from typing import List, Tuple @@ -100,9 +101,33 @@ class PRReviewer: if self.is_auto and not get_settings().pr_reviewer.automatic_review: get_logger().info(f'Automatic review is disabled {self.pr_url}') return None - if self.is_auto and self.incremental.is_incremental and not self.incremental.first_new_commit_sha: - get_logger().info(f"Incremental review is enabled for {self.pr_url} but there are no new commits") - return None + if self.incremental.is_incremental: + if self.is_auto and not self.incremental.first_new_commit_sha: + get_logger().info(f"Incremental review is enabled for {self.pr_url} but there are no new commits") + return None + # checking if there are enough commits to start the review + num_new_commits = len(self.incremental.commits_range) + num_commits_threshold = get_settings().pr_reviewer.minimal_commits_for_incremental_review + not_enough_commits = num_new_commits < num_commits_threshold + # checking if the commits are not too recent to start the review + recent_commits_threshold = datetime.datetime.now() - datetime.timedelta( + minutes=get_settings().pr_reviewer.minimal_minutes_for_incremental_review + ) + last_seen_commit_date = ( + self.incremental.last_seen_commit.commit.author.date if self.incremental.last_seen_commit else None + ) + all_commits_too_recent = ( + last_seen_commit_date > recent_commits_threshold if self.incremental.last_seen_commit else False + ) + # check all the thresholds or just one to start the review + condition = any if get_settings().pr_reviewer.require_all_thresholds_for_incremental_review else all + if condition((not_enough_commits, all_commits_too_recent)): + get_logger().info( + f"Incremental review is enabled for {self.pr_url} but didn't pass the threshold check to run:" + f"\n* Number of new commits = {num_new_commits} (threshold is {num_commits_threshold})" + f"\n* Last seen commit date = {last_seen_commit_date} (threshold is {recent_commits_threshold})" + ) + return None get_logger().info(f'Reviewing PR: {self.pr_url} ...') From e1370a838536f325f941bd738e330495c2b8bf72 Mon Sep 17 00:00:00 2001 From: Ori Kotek Date: Thu, 2 Nov 2023 15:24:47 +0200 Subject: [PATCH 03/18] Update publish_inline_comments in bitbucket_provider.py to use 'position' instead of 'start_line' --- pr_agent/git_providers/bitbucket_provider.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr_agent/git_providers/bitbucket_provider.py b/pr_agent/git_providers/bitbucket_provider.py index abff4d04..b5d08bfb 100644 --- a/pr_agent/git_providers/bitbucket_provider.py +++ b/pr_agent/git_providers/bitbucket_provider.py @@ -183,7 +183,7 @@ class BitbucketProvider(GitProvider): def publish_inline_comments(self, comments: list[dict]): for comment in comments: - self.publish_inline_comment(comment['body'], comment['start_line'], comment['path']) + self.publish_inline_comment(comment['body'], comment['position'], comment['path']) def get_title(self): return self.pr.title From fe3527de3c36565c7fecf0081de2da7553bafd90 Mon Sep 17 00:00:00 2001 From: Ori Kotek Date: Fri, 3 Nov 2023 12:23:49 +0200 Subject: [PATCH 04/18] Add exception handling for applying repo settings failure --- pr_agent/git_providers/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pr_agent/git_providers/utils.py b/pr_agent/git_providers/utils.py index 50fd3915..5c9af8b0 100644 --- a/pr_agent/git_providers/utils.py +++ b/pr_agent/git_providers/utils.py @@ -27,7 +27,8 @@ def apply_repo_settings(pr_url): get_settings().unset(section) get_settings().set(section, section_dict, merge=False) get_logger().info(f"Applying repo settings for section {section}, contents: {contents}") - + except Exception as e: + get_logger().exception("Failed to apply repo settings", e) finally: if repo_settings_file: try: From 194bfe1193c0266053f9a35eb866fd606a726381 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Sun, 5 Nov 2023 07:59:59 +0200 Subject: [PATCH 05/18] Update INSTALL.md --- INSTALL.md | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 4e588b92..c020b863 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -31,21 +31,29 @@ There are several ways to use PR-Agent: To request a review for a PR, or ask a question about a PR, you can run directly from the Docker image. Here's how: -For GitHub: +- For GitHub: ``` docker run --rm -it -e OPENAI.KEY= -e GITHUB.USER_TOKEN= codiumai/pr-agent:latest --pr_url review ``` -For GitLab: + +- For GitLab: ``` docker run --rm -it -e OPENAI.KEY= -e CONFIG.GIT_PROVIDER=gitlab -e GITLAB.PERSONAL_ACCESS_TOKEN= codiumai/pr-agent:latest --pr_url review ``` -For BitBucket: + +Note: If you have a dedicated GitLab instance, you need to specify the custom url as variable: +``` +docker run --rm -it -e OPENAI.KEY= -e CONFIG.GIT_PROVIDER=gitlab -e GITLAB.PERSONAL_ACCESS_TOKEN= GITLAB.URL= codiumai/pr-agent:latest --pr_url review +``` + +- For BitBucket: ``` docker run --rm -it -e CONFIG.GIT_PROVIDER=bitbucket -e OPENAI.KEY=$OPENAI_API_KEY -e BITBUCKET.BEARER_TOKEN=$BITBUCKET_BEARER_TOKEN codiumai/pr-agent:latest --pr_url= review ``` For other git providers, update CONFIG.GIT_PROVIDER accordingly, and check the `pr_agent/settings/.secrets_template.toml` file for the environment variables expected names and values. +--- Similarly, to ask a question about a PR, run the following command: ``` @@ -59,7 +67,8 @@ Note: If you want to ensure you're running a specific version of the Docker imag ```bash docker run --rm -it -e OPENAI.KEY= -e GITHUB.USER_TOKEN= codiumai/pr-agent@sha256:71b5ee15df59c745d352d84752d01561ba64b6d51327f97d46152f0c58a5f678 --pr_url review ``` -in addition, you can run a [specific released versions](./RELEASE_NOTES.md) of pr-agent, for example: + +Or you can run a [specific released versions](./RELEASE_NOTES.md) of pr-agent, for example: ``` codiumai/pr-agent@v0.8 ``` From e6ef123ce533697d6f13ee443c91a68024c668c9 Mon Sep 17 00:00:00 2001 From: koid Date: Sun, 5 Nov 2023 15:38:19 +0900 Subject: [PATCH 06/18] add middleware when initializing fastapi --- pr_agent/servers/serverless.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pr_agent/servers/serverless.py b/pr_agent/servers/serverless.py index 91596315..b03d9171 100644 --- a/pr_agent/servers/serverless.py +++ b/pr_agent/servers/serverless.py @@ -1,12 +1,15 @@ from fastapi import FastAPI from mangum import Mangum +from starlette.middleware import Middleware +from starlette_context.middleware import RawContextMiddleware from pr_agent.log import setup_logger from pr_agent.servers.github_app import router setup_logger() -app = FastAPI() +middleware = [Middleware(RawContextMiddleware)] +app = FastAPI(middleware=middleware) app.include_router(router) handler = Mangum(app, lifespan="off") From bb2760ae416037a7daae7131fb29d2189e28dd48 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Mon, 6 Nov 2023 08:10:04 +0200 Subject: [PATCH 07/18] tools --- INSTALL.md | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index c020b863..d0298033 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -29,7 +29,9 @@ There are several ways to use PR-Agent: ### Use Docker image (no installation required) -To request a review for a PR, or ask a question about a PR, you can run directly from the Docker image. Here's how: +A list of the relevant tools can be found in the [tools guide](./docs/TOOLS_GUIDE.md). + +To invoke a tool (for example `review`), you can run directly from the Docker image. Here's how: - For GitHub: ``` @@ -55,22 +57,15 @@ For other git providers, update CONFIG.GIT_PROVIDER accordingly, and check the ` --- -Similarly, to ask a question about a PR, run the following command: -``` -docker run --rm -it -e OPENAI.KEY= -e GITHUB.USER_TOKEN= codiumai/pr-agent --pr_url ask "" -``` -A list of the relevant tools can be found in the [tools guide](./docs/TOOLS_GUIDE.md). - - -Note: If you want to ensure you're running a specific version of the Docker image, consider using the image's digest: +If you want to ensure you're running a specific version of the Docker image, consider using the image's digest: ```bash docker run --rm -it -e OPENAI.KEY= -e GITHUB.USER_TOKEN= codiumai/pr-agent@sha256:71b5ee15df59c745d352d84752d01561ba64b6d51327f97d46152f0c58a5f678 --pr_url review ``` Or you can run a [specific released versions](./RELEASE_NOTES.md) of pr-agent, for example: ``` -codiumai/pr-agent@v0.8 +codiumai/pr-agent@v0.9 ``` --- From 8fc663911f8ac1bbeac29e26dd576b931b97e91a Mon Sep 17 00:00:00 2001 From: mrT23 Date: Mon, 6 Nov 2023 08:15:43 +0200 Subject: [PATCH 08/18] fixe bitbucket get_repo_settings bug --- pr_agent/git_providers/bitbucket_provider.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pr_agent/git_providers/bitbucket_provider.py b/pr_agent/git_providers/bitbucket_provider.py index b5d08bfb..27575f2a 100644 --- a/pr_agent/git_providers/bitbucket_provider.py +++ b/pr_agent/git_providers/bitbucket_provider.py @@ -44,6 +44,8 @@ class BitbucketProvider(GitProvider): url = (f"https://api.bitbucket.org/2.0/repositories/{self.workspace_slug}/{self.repo_slug}/src/" f"{self.pr.destination_branch}/.pr_agent.toml") response = requests.request("GET", url, headers=self.headers) + if response.status_code == 404: # not found + return "" contents = response.text.encode('utf-8') return contents except Exception: From e37daf69877dbd171f4ac9c92d5053a444598e61 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Mon, 6 Nov 2023 08:27:34 +0200 Subject: [PATCH 09/18] link to change --- pr_agent/git_providers/bitbucket_provider.py | 26 ++++++++++++++++++++ pr_agent/tools/pr_reviewer.py | 13 ---------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/pr_agent/git_providers/bitbucket_provider.py b/pr_agent/git_providers/bitbucket_provider.py index 27575f2a..ec7a66ed 100644 --- a/pr_agent/git_providers/bitbucket_provider.py +++ b/pr_agent/git_providers/bitbucket_provider.py @@ -32,8 +32,10 @@ class BitbucketProvider(GitProvider): self.repo = None self.pr_num = None self.pr = None + self.pr_url = pr_url self.temp_comments = [] self.incremental = incremental + self.diff_files = None if pr_url: self.set_pr(pr_url) self.bitbucket_comment_api_url = self.pr._BitbucketBase__data["links"]["comments"]["href"] @@ -116,6 +118,9 @@ class BitbucketProvider(GitProvider): return [diff.new.path for diff in self.pr.diffstat()] def get_diff_files(self) -> list[FilePatchInfo]: + if self.diff_files: + return self.diff_files + diffs = self.pr.diffstat() diff_split = [ "diff --git%s" % x for x in self.pr.diff().split("diff --git") if x.strip() @@ -135,6 +140,7 @@ class BitbucketProvider(GitProvider): diff.new.path, ) ) + self.diff_files = diff_files return diff_files def publish_comment(self, pr_comment: str, is_temporary: bool = False): @@ -183,6 +189,26 @@ class BitbucketProvider(GitProvider): ) return response + def generate_link_to_relevant_line_number(self, suggestion) -> str: + try: + relevant_file = suggestion['relevant file'].strip('`').strip("'") + relevant_line_str = suggestion['relevant line'] + if not relevant_line_str: + return "" + + diff_files = self.get_diff_files() + position, absolute_position = find_line_number_of_relevant_line_in_file \ + (diff_files, relevant_file, relevant_line_str) + + if absolute_position != -1 and self.pr_url: + link = f"{self.pr_url}/#L{relevant_file}T{absolute_position}" + return link + except Exception as e: + if get_settings().config.verbosity_level >= 2: + get_logger().info(f"Failed adding line link, error: {e}") + + return "" + def publish_inline_comments(self, comments: list[dict]): for comment in comments: self.publish_inline_comment(comment['body'], comment['position'], comment['path']) diff --git a/pr_agent/tools/pr_reviewer.py b/pr_agent/tools/pr_reviewer.py index 7cf561e2..b5091a6a 100644 --- a/pr_agent/tools/pr_reviewer.py +++ b/pr_agent/tools/pr_reviewer.py @@ -217,19 +217,6 @@ class PRReviewer: suggestion['relevant line'] = f"[{suggestion['relevant line']}]({link})" else: pass - # try: - # relevant_file = suggestion['relevant file'].strip('`').strip("'") - # relevant_line_str = suggestion['relevant line'] - # if not relevant_line_str: - # return "" - # - # position, absolute_position = find_line_number_of_relevant_line_in_file( - # self.git_provider.diff_files, relevant_file, relevant_line_str) - # if absolute_position != -1: - # suggestion[ - # 'relevant line'] = f"{suggestion['relevant line']} (line {absolute_position})" - # except: - # pass # Add incremental review section From fed1c160ebca0f553c582420b57469585f004508 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Mon, 6 Nov 2023 08:43:15 +0200 Subject: [PATCH 10/18] files walkthrough bullets --- pr_agent/tools/pr_description.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr_agent/tools/pr_description.py b/pr_agent/tools/pr_description.py index 4f0081fb..dacf3b09 100644 --- a/pr_agent/tools/pr_description.py +++ b/pr_agent/tools/pr_description.py @@ -248,7 +248,7 @@ class PRDescription: for file in value: filename = file['filename'].replace("'", "`") description = file['changes in file'] - pr_body += f'`{filename}`: {description}\n' + pr_body += f'- `{filename}`: {description}\n' if self.git_provider.is_supported("gfm_markdown"): pr_body +="\n" else: From 92071fcf1ca1b041377e57ebb04899f6da0195e0 Mon Sep 17 00:00:00 2001 From: zmeir Date: Mon, 6 Nov 2023 09:13:04 +0200 Subject: [PATCH 11/18] Stack all incremental parameters --- pr_agent/settings/configuration.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pr_agent/settings/configuration.toml b/pr_agent/settings/configuration.toml index 06519f0a..b0786cd3 100644 --- a/pr_agent/settings/configuration.toml +++ b/pr_agent/settings/configuration.toml @@ -25,10 +25,11 @@ inline_code_comments = false ask_and_reflect=false automatic_review=true remove_previous_review_comment=false +extra_instructions = "" +# specific configurations for incremental review (/review -i) require_all_thresholds_for_incremental_review=false minimal_commits_for_incremental_review=0 minimal_minutes_for_incremental_review=0 -extra_instructions = "" [pr_description] # /describe # publish_labels=true From 8e3fa3926a756bff3a99ff47bdd444af7b5e229f Mon Sep 17 00:00:00 2001 From: zmeir Date: Mon, 6 Nov 2023 09:21:22 +0200 Subject: [PATCH 12/18] Extract incremental review checks to separate method --- pr_agent/tools/pr_reviewer.py | 60 +++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/pr_agent/tools/pr_reviewer.py b/pr_agent/tools/pr_reviewer.py index c13e7edd..7e5ddda1 100644 --- a/pr_agent/tools/pr_reviewer.py +++ b/pr_agent/tools/pr_reviewer.py @@ -101,33 +101,8 @@ class PRReviewer: if self.is_auto and not get_settings().pr_reviewer.automatic_review: get_logger().info(f'Automatic review is disabled {self.pr_url}') return None - if self.incremental.is_incremental: - if self.is_auto and not self.incremental.first_new_commit_sha: - get_logger().info(f"Incremental review is enabled for {self.pr_url} but there are no new commits") - return None - # checking if there are enough commits to start the review - num_new_commits = len(self.incremental.commits_range) - num_commits_threshold = get_settings().pr_reviewer.minimal_commits_for_incremental_review - not_enough_commits = num_new_commits < num_commits_threshold - # checking if the commits are not too recent to start the review - recent_commits_threshold = datetime.datetime.now() - datetime.timedelta( - minutes=get_settings().pr_reviewer.minimal_minutes_for_incremental_review - ) - last_seen_commit_date = ( - self.incremental.last_seen_commit.commit.author.date if self.incremental.last_seen_commit else None - ) - all_commits_too_recent = ( - last_seen_commit_date > recent_commits_threshold if self.incremental.last_seen_commit else False - ) - # check all the thresholds or just one to start the review - condition = any if get_settings().pr_reviewer.require_all_thresholds_for_incremental_review else all - if condition((not_enough_commits, all_commits_too_recent)): - get_logger().info( - f"Incremental review is enabled for {self.pr_url} but didn't pass the threshold check to run:" - f"\n* Number of new commits = {num_new_commits} (threshold is {num_commits_threshold})" - f"\n* Last seen commit date = {last_seen_commit_date} (threshold is {recent_commits_threshold})" - ) - return None + if self.incremental.is_incremental and not self._can_run_incremental_review(): + return None get_logger().info(f'Reviewing PR: {self.pr_url} ...') @@ -372,3 +347,34 @@ class PRReviewer: self.git_provider.remove_comment(comment) except Exception as e: get_logger().exception(f"Failed to remove previous review comment, error: {e}") + + def _can_run_incremental_review(self) -> bool: + """Checks if we can run incremental review according the various configurations and previous review""" + # checking if running is auto mode but there are no new commits + if self.is_auto and not self.incremental.first_new_commit_sha: + get_logger().info(f"Incremental review is enabled for {self.pr_url} but there are no new commits") + return False + # checking if there are enough commits to start the review + num_new_commits = len(self.incremental.commits_range) + num_commits_threshold = get_settings().pr_reviewer.minimal_commits_for_incremental_review + not_enough_commits = num_new_commits < num_commits_threshold + # checking if the commits are not too recent to start the review + recent_commits_threshold = datetime.datetime.now() - datetime.timedelta( + minutes=get_settings().pr_reviewer.minimal_minutes_for_incremental_review + ) + last_seen_commit_date = ( + self.incremental.last_seen_commit.commit.author.date if self.incremental.last_seen_commit else None + ) + all_commits_too_recent = ( + last_seen_commit_date > recent_commits_threshold if self.incremental.last_seen_commit else False + ) + # check all the thresholds or just one to start the review + condition = any if get_settings().pr_reviewer.require_all_thresholds_for_incremental_review else all + if condition((not_enough_commits, all_commits_too_recent)): + get_logger().info( + f"Incremental review is enabled for {self.pr_url} but didn't pass the threshold check to run:" + f"\n* Number of new commits = {num_new_commits} (threshold is {num_commits_threshold})" + f"\n* Last seen commit date = {last_seen_commit_date} (threshold is {recent_commits_threshold})" + ) + return False + return True From 06d030637c32f649774173ed0bf2fedcb50d53c5 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Mon, 6 Nov 2023 09:32:46 +0200 Subject: [PATCH 13/18] fix prompt --- pr_agent/settings/pr_description_prompts.toml | 7 ++++--- pr_agent/tools/pr_description.py | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pr_agent/settings/pr_description_prompts.toml b/pr_agent/settings/pr_description_prompts.toml index 3d9c3f0b..29a6e095 100644 --- a/pr_agent/settings/pr_description_prompts.toml +++ b/pr_agent/settings/pr_description_prompts.toml @@ -1,9 +1,10 @@ [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). +Your task is to provide full description of the Pull Request (PR) content. +- Make sure to focus the new PR code (the '+' lines). - Notice that the 'Previous title', 'Previous description' and 'Commit messages' sections may be partial, simplistic, non-informative or not up-to-date. Hence, compare them to the PR diff code, and use them only as a reference. -- If needed, each YAML output should be in block scalar format ('|-') +- Emphasize first the most important changes, and then the less important ones. +- If needed, each YAML output should be in block scalar format ('|-') {%- if extra_instructions %} Extra instructions from the user: diff --git a/pr_agent/tools/pr_description.py b/pr_agent/tools/pr_description.py index 4f0081fb..d7967e80 100644 --- a/pr_agent/tools/pr_description.py +++ b/pr_agent/tools/pr_description.py @@ -162,7 +162,7 @@ class PRDescription: def _prepare_data(self): # Load the AI prediction data into a dictionary - self.data = load_yaml(self.prediction.strip()) + self.data = load_yaml(self.prediction.strip('\n').strip('` ')) if get_settings().pr_description.add_original_user_description and self.user_description: self.data["User Description"] = self.user_description From 5d2bdadb4515bbb493f8d82c560133cc3cee79f2 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Mon, 6 Nov 2023 09:33:10 +0200 Subject: [PATCH 14/18] fix prompt --- pr_agent/settings/pr_description_prompts.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr_agent/settings/pr_description_prompts.toml b/pr_agent/settings/pr_description_prompts.toml index 29a6e095..44a36c65 100644 --- a/pr_agent/settings/pr_description_prompts.toml +++ b/pr_agent/settings/pr_description_prompts.toml @@ -1,6 +1,6 @@ [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 Pull Request (PR) content. +Your task is to provide full description of a Pull Request (PR) content. - Make sure to focus the new PR code (the '+' lines). - Notice that the 'Previous title', 'Previous description' and 'Commit messages' sections may be partial, simplistic, non-informative or not up-to-date. Hence, compare them to the PR diff code, and use them only as a reference. - Emphasize first the most important changes, and then the less important ones. From 62412f8cd471b5da3e30f5c72397d7a02fd81b99 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Mon, 6 Nov 2023 09:38:39 +0200 Subject: [PATCH 15/18] fix prompt --- pr_agent/settings/pr_description_prompts.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr_agent/settings/pr_description_prompts.toml b/pr_agent/settings/pr_description_prompts.toml index 44a36c65..36a6f0db 100644 --- a/pr_agent/settings/pr_description_prompts.toml +++ b/pr_agent/settings/pr_description_prompts.toml @@ -1,7 +1,7 @@ [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 a Pull Request (PR) content. -- Make sure to focus the new PR code (the '+' lines). +- Make sure to focus on the new PR code (the '+' lines). - Notice that the 'Previous title', 'Previous description' and 'Commit messages' sections may be partial, simplistic, non-informative or not up-to-date. Hence, compare them to the PR diff code, and use them only as a reference. - Emphasize first the most important changes, and then the less important ones. - If needed, each YAML output should be in block scalar format ('|-') From 7238c81f0ceafab41e7f1293d5d4b25b7433f69f Mon Sep 17 00:00:00 2001 From: mrT23 Date: Mon, 6 Nov 2023 09:41:26 +0200 Subject: [PATCH 16/18] fix prompt --- pr_agent/settings/pr_description_prompts.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pr_agent/settings/pr_description_prompts.toml b/pr_agent/settings/pr_description_prompts.toml index 36a6f0db..6a50efac 100644 --- a/pr_agent/settings/pr_description_prompts.toml +++ b/pr_agent/settings/pr_description_prompts.toml @@ -52,6 +52,7 @@ PR Main Files Walkthrough: changes in file: type: string description: minimal and concise description of the changes in the relevant file +``` Example output: From b286c8ed2063c61e1a596478cbe1afa75ed9483c Mon Sep 17 00:00:00 2001 From: zmeir Date: Mon, 6 Nov 2023 09:44:04 +0200 Subject: [PATCH 17/18] Added documentation for the new configurations --- docs/REVIEW.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/docs/REVIEW.md b/docs/REVIEW.md index 7f2f42cb..ac4d1b4a 100644 --- a/docs/REVIEW.md +++ b/docs/REVIEW.md @@ -29,12 +29,26 @@ Under the section 'pr_reviewer', the [configuration file](./../pr_agent/settings #### Incremental Mode For an incremental review, which only considers changes since the last PR-Agent review, this can be useful when working on the PR in an iterative manner, and you want to focus on the changes since the last review instead of reviewing the entire PR again, the following command can be used: ``` -/improve -i +/review -i ``` Note that the incremental mode is only available for GitHub. +Under the section 'pr_reviewer', the [configuration file](./../pr_agent/settings/configuration.toml#L16) contains options to customize the 'review -i' tool. +These configurations can be used to control the rate at which the incremental review tool will create new review comments when invoked automatically, to prevent making too much noise in the PR. +- `minimal_commits_for_incremental_review`: Minimal number of commits since the last review that are required to create incremental review. +If there are less than the specified number of commits since the last review, the tool will not perform any action. +Default is 0 - the tool will always run, no matter how many commits since the last review. +- `minimal_minutes_for_incremental_review`: Minimal number of minutes that need to pass since the last reviewed commit to create incremental review. +If less that the specified number of minutes have passed between the last reviewed commit and running this command, the tool will not perform any action. +Default is 0 - the tool will always run, no matter how much time have passed since the last reviewed commit. +- `require_all_thresholds_for_incremental_review`: If set to true, all the previous thresholds must be met for incremental review to run. If false, only one is enough to run the tool. +For example, if `minimal_commits_for_incremental_review=2` and `minimal_minutes_for_incremental_review=2`, and we have 3 commits since the last review, but the last reviewed commit is from 1 minute ago: +When `require_all_thresholds_for_incremental_review=true` the incremental review __will not__ run, because only 1 out of 2 conditions were met (we have enough commits but the last review is too recent), +but when `require_all_thresholds_for_incremental_review=false` the incremental review __will__ run, because one condition is enough (we have 3 commits which is more than the configured 2). +Default is false - the tool will run as long as at least once conditions is met. + #### PR Reflection By invoking: ``` From 6d6d8644176c7b1d31715565432708c7d4326ac9 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Mon, 6 Nov 2023 09:44:59 +0200 Subject: [PATCH 18/18] fix prompt --- pr_agent/tools/pr_description.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr_agent/tools/pr_description.py b/pr_agent/tools/pr_description.py index d7967e80..4f0081fb 100644 --- a/pr_agent/tools/pr_description.py +++ b/pr_agent/tools/pr_description.py @@ -162,7 +162,7 @@ class PRDescription: def _prepare_data(self): # Load the AI prediction data into a dictionary - self.data = load_yaml(self.prediction.strip('\n').strip('` ')) + self.data = load_yaml(self.prediction.strip()) if get_settings().pr_description.add_original_user_description and self.user_description: self.data["User Description"] = self.user_description