auto approval

This commit is contained in:
mrT23
2024-02-06 08:31:36 +02:00
parent a126ef64fc
commit b190b1879e
8 changed files with 118 additions and 1 deletions

View File

@ -45,6 +45,7 @@ commands = list(command2class.keys())
class PRAgent:
def __init__(self, ai_handler: partial[BaseAiHandler,] = LiteLLMAIHandler):
self.ai_handler = ai_handler # will be initialized in run_action
self.forbidden_cli_args = ['enable_auto_approval']
async def handle_request(self, pr_url, request, notify=None) -> bool:
# First, apply repo specific settings if exists
@ -58,6 +59,13 @@ class PRAgent:
action, *args = list(lexer)
else:
action, *args = request
if args:
for forbidden_arg in self.forbidden_cli_args:
for arg in args:
if forbidden_arg in arg:
get_logger().error(f"CLI argument '{forbidden_arg}' is forbidden")
return False
args = update_settings_from_args(args)
action = action.lstrip("/").lower()

View File

@ -171,6 +171,11 @@ class GitProvider(ABC):
def get_latest_commit_url(self) -> str:
return ""
def auto_approve(self) -> bool:
return False
def get_main_pr_language(languages, files) -> str:
"""
Get the main language of the commit. Return an empty string if cannot determine.
@ -239,7 +244,6 @@ def get_main_pr_language(languages, files) -> str:
return main_language_str
class IncrementalPR:
def __init__(self, is_incremental: bool = False):
self.is_incremental = is_incremental

View File

@ -643,3 +643,13 @@ class GithubProvider(GitProvider):
return pr_id
except:
return ""
def auto_approve(self) -> bool:
try:
res = self.pr.create_review(event="APPROVE")
if res.state == "APPROVED":
return True
return False
except Exception as e:
get_logger().exception(f"Failed to auto-approve, error: {e}")
return False

View File

@ -99,6 +99,31 @@ Some of the feature that are disabled by default are quite useful, and should be
"""
output += "\n\n</details></td></tr>\n\n"
output += "<tr><td><details> <summary><strong> Auto-approve PRs</strong></summary><hr>\n\n"
output += '''\
By invoking:
```
/review auto_approve
```
The tool will automatically approve the PR, and add a comment with the approval.
To ensure safety, the auto-approval feature is disabled by default. To enable auto-approval, you need to actively set in a pre-defined configuration file the following:
```
[pr_reviewer]
enable_auto_approval = true
```
(this specific flag cannot be set with a command line argument, only in the configuration file, committed to the repository)
You can also enable auto-approval only if the PR meets certain requirements, such as that the `estimated_review_effort` is equal or below a certain threshold, by adjusting the flag:
```
[pr_reviewer]
maximal_review_effort = 5
```
'''
output += "\n\n</details></td></tr>\n\n"
# general
output += "\n\n<tr><td><details> <summary><strong> More PR-Agent commands</strong></summary><hr> \n\n"
output += HelpMessage.get_general_bot_help_text()
@ -186,6 +211,7 @@ To enable inline file summary, set `pr_description.inline_file_summary` in the c
- `true`: A collapsable file comment with changes title and a changes summary for each file in the PR.
- `false` (default): File changes walkthrough will be added only to the "Conversation" tab.
"""
# extra instructions
output += "<tr><td><details> <summary><strong> Utilizing extra instructions</strong></summary><hr>\n\n"
output += '''\

View File

@ -43,6 +43,10 @@ require_all_thresholds_for_incremental_review=false
minimal_commits_for_incremental_review=0
minimal_minutes_for_incremental_review=0
enable_help_text=true # Determines whether to include help text in the PR review. Enabled by default.
# auto approval
enable_auto_approval=false
maximal_review_effort=5
[pr_description] # /describe #
publish_labels=true

View File

@ -36,6 +36,7 @@ class PRReviewer:
ai_handler (BaseAiHandler): The AI handler to be used for the review. Defaults to None.
args (list, optional): List of arguments passed to the PRReviewer class. Defaults to None.
"""
self.args = args
self.parse_args(args) # -i command
self.git_provider = get_git_provider()(pr_url, incremental=self.incremental)
@ -102,6 +103,11 @@ class PRReviewer:
if self.incremental.is_incremental and not self._can_run_incremental_review():
return None
if isinstance(self.args, list) and self.args and self.args[0] == 'auto_approve':
get_logger().info(f'Auto approve flow PR: {self.pr_url} ...')
self.auto_approve_logic()
return None
get_logger().info(f'Reviewing PR: {self.pr_url} ...')
if get_settings().config.publish_output:
@ -392,3 +398,30 @@ class PRReviewer:
self.git_provider.publish_labels(review_labels + current_labels_filtered)
except Exception as e:
get_logger().error(f"Failed to set review labels, error: {e}")
def auto_approve_logic(self):
"""
Auto-approve a pull request if it meets the conditions for auto-approval.
"""
if get_settings().pr_reviewer.enable_auto_approval:
maximal_review_effort = get_settings().pr_reviewer.maximal_review_effort
if maximal_review_effort < 5:
current_labels = self.git_provider.get_pr_labels()
for label in current_labels:
if label.lower().startswith('review effort [1-5]:'):
effort = int(label.split(':')[1].strip())
if effort > maximal_review_effort:
get_logger().info(
f"Auto-approve error: PR review effort ({effort}) is higher than the maximal review effort "
f"({maximal_review_effort}) allowed")
self.git_provider.publish_comment(
f"Auto-approve error: PR review effort ({effort}) is higher than the maximal review effort "
f"({maximal_review_effort}) allowed")
return
is_auto_approved = self.git_provider.auto_approve()
if is_auto_approved:
get_logger().info("Auto-approved PR")
self.git_provider.publish_comment("Auto-approved PR")
else:
get_logger().info("Auto-approval option is disabled")
self.git_provider.publish_comment("Auto-approval option for PR-Agent is disabled")