workflows/merico/pr/providers/devchat_provider.py

262 lines
8.8 KiB
Python
Raw Normal View History

2024-05-19 15:34:26 +08:00
import json
2024-05-18 22:05:51 +08:00
import os
import sys
from typing import Optional, Tuple
2024-05-19 15:34:26 +08:00
import pr_agent.git_providers as git_providers
2024-05-18 22:05:51 +08:00
from pr_agent.git_providers.git_provider import GitProvider, IncrementalPR
from pr_agent.git_providers.github_provider import GithubProvider
2024-05-19 15:34:26 +08:00
from lib.chatmark import Button, Form, TextEditor
2024-05-18 22:05:51 +08:00
class DevChatProvider(GitProvider):
def __init__(self, pr_url: Optional[str] = None, incremental=IncrementalPR(False)):
# 根据某个状态创建正确的GitProvider
2024-05-19 15:34:26 +08:00
provider_type = os.environ.get("CONFIG.GIT_PROVIDER_TYPE")
self.provider: GitProvider = git_providers._GIT_PROVIDERS[provider_type](
pr_url, incremental
)
2024-05-18 22:05:51 +08:00
@property
def pr(self):
return self.provider.pr
2024-05-19 15:34:26 +08:00
2024-05-18 22:05:51 +08:00
@property
def diff_files(self):
return self.provider.diff_files
2024-05-19 15:34:26 +08:00
2024-05-18 22:05:51 +08:00
@property
def github_client(self):
return self.provider.github_client
def is_supported(self, capability: str) -> bool:
return self.provider.is_supported(capability)
def get_diff_files(self):
return self.provider.get_diff_files()
2024-05-19 15:34:26 +08:00
2024-05-18 22:05:51 +08:00
def need_edit(self):
button = Button(
2024-05-19 15:34:26 +08:00
["Commit", "Edit"],
2024-05-18 22:05:51 +08:00
)
button.render()
return 1 == button.clicked
def publish_description(self, pr_title: str, pr_body: str):
# Preview pr title and body
print(f"\n\nPR Title: {pr_title}", end="\n\n", flush=True)
print("PR Body:", end="\n\n", flush=True)
print(pr_body, end="\n\n", flush=True)
# Need Edit?
if self.need_edit():
# Edit pr title and body
title_editor = TextEditor(pr_title)
body_editor = TextEditor(pr_body)
2024-05-19 15:34:26 +08:00
form = Form(["Edit pr title:", title_editor, "Edit pr body:", body_editor])
2024-05-18 22:05:51 +08:00
form.render()
2024-05-19 15:34:26 +08:00
2024-05-18 22:05:51 +08:00
pr_title = title_editor.new_text
pr_body = body_editor.new_text
if not pr_title or not pr_body:
print("Title or body is empty, please fill in the title and body.")
sys.exit(0)
return self.provider.publish_description(pr_title, pr_body)
def publish_code_suggestions(self, code_suggestions: list) -> bool:
code_suggestions_json_str = json.dumps(code_suggestions, indent=4)
code_suggestions_editor = TextEditor(
2024-05-19 15:34:26 +08:00
code_suggestions_json_str, "Edit code suggestions in JSON format:"
2024-05-18 22:05:51 +08:00
)
code_suggestions_editor.render()
code_suggestions_json_new = code_suggestions_editor.new_text
if not code_suggestions_json_new:
print("Code suggestions are empty, please fill in the code suggestions.")
sys.exit(0)
2024-05-19 15:34:26 +08:00
2024-05-18 22:05:51 +08:00
code_suggestions = json.loads(code_suggestions_json_new)
return self.provider.publish_code_suggestions(code_suggestions)
def get_languages(self):
return self.provider.get_languages()
def get_pr_branch(self):
return self.provider.get_pr_branch()
2024-05-19 15:34:26 +08:00
2024-05-18 22:05:51 +08:00
def get_files(self):
return self.provider.get_files()
def get_user_id(self):
return self.provider.get_user_id()
def get_pr_description_full(self) -> str:
return self.provider.get_pr_description_full()
def edit_comment(self, comment, body: str):
if body.find("## PR Code Suggestions") == -1:
return self.provider.edit_comment(comment, body)
print(f"\n\n{body}", end="\n\n", flush=True)
if self.need_edit():
2024-05-19 15:34:26 +08:00
comment_editor = TextEditor(body, "Edit Comment:")
2024-05-18 22:05:51 +08:00
comment_editor.render()
body = comment_editor.new_text
if not body:
print("Comment is empty, please fill in the comment.")
sys.exit(0)
return self.provider.edit_comment(comment, body)
def reply_to_comment_from_comment_id(self, comment_id: int, body: str):
return self.provider.reply_to_comment_from_comment_id(comment_id, body)
def get_pr_description(self, *, full: bool = True) -> str:
return self.provider.get_pr_description(full=full)
def get_user_description(self) -> str:
return self.provider.get_user_description()
def _possible_headers(self):
return self.provider._possible_headers()
def _is_generated_by_pr_agent(self, description_lowercase: str) -> bool:
return self.provider._is_generated_by_pr_agent(description_lowercase)
def get_repo_settings(self):
return self.provider.get_repo_settings()
def get_pr_id(self):
return self.provider.get_pr_id()
2024-05-19 15:34:26 +08:00
def get_line_link(
self, relevant_file: str, relevant_line_start: int, relevant_line_end: int = None
) -> str:
2024-05-18 22:05:51 +08:00
return self.provider.get_line_link(relevant_file, relevant_line_start, relevant_line_end)
#### comments operations ####
def publish_comment(self, pr_comment: str, is_temporary: bool = False):
if is_temporary:
return None
if pr_comment.find("## Generating PR code suggestions") != -1:
return None
2024-05-19 15:34:26 +08:00
if (
not is_temporary
and pr_comment.find("## Generating PR code suggestions") == -1
and pr_comment.find("**[PR Description]") == -1
):
2024-05-18 22:05:51 +08:00
print(f"\n\n{pr_comment}", end="\n\n", flush=True)
if self.need_edit():
2024-05-19 15:34:26 +08:00
pr_comment_editor = TextEditor(pr_comment)
form = Form(["Edit pr comment:", pr_comment_editor])
2024-05-18 22:05:51 +08:00
form.render()
2024-05-19 15:34:26 +08:00
2024-05-18 22:05:51 +08:00
pr_comment = pr_comment_editor.new_text
if not pr_comment:
print("Comment is empty, please fill in the comment.")
sys.exit(0)
return self.provider.publish_comment(pr_comment, is_temporary=is_temporary)
2024-05-19 15:34:26 +08:00
def publish_persistent_comment(
self,
pr_comment: str,
initial_header: str,
update_header: bool = True,
name="review",
final_update_message=True,
):
2024-05-18 22:05:51 +08:00
print(f"\n\n{initial_header}", end="\n\n", flush=True)
print(pr_comment, end="\n\n", flush=True)
if self.need_edit():
2024-05-19 15:34:26 +08:00
pr_comment_editor = TextEditor(pr_comment)
form = Form(["Edit pr comment:", pr_comment_editor])
2024-05-18 22:05:51 +08:00
form.render()
pr_comment = pr_comment_editor.new_text
if not pr_comment:
print("Comment is empty, please fill in the comment.")
sys.exit(0)
2024-05-19 15:34:26 +08:00
return self.provider.publish_persistent_comment(
pr_comment, initial_header, update_header, name, final_update_message
)
2024-05-18 22:05:51 +08:00
def publish_inline_comment(self, body: str, relevant_file: str, relevant_line_in_file: str):
return self.provider.publish_inline_comment(body, relevant_file, relevant_line_in_file)
2024-05-19 15:34:26 +08:00
def create_inline_comment(
self,
body: str,
relevant_file: str,
relevant_line_in_file: str,
absolute_position: int = None,
):
return self.provider.create_inline_comment(
body, relevant_file, relevant_line_in_file, absolute_position
)
2024-05-18 22:05:51 +08:00
def publish_inline_comments(self, comments: list[dict]):
return self.provider.publish_inline_comments(comments)
def remove_initial_comment(self):
return self.provider.remove_initial_comment()
def remove_comment(self, comment):
return self.provider.remove_comment(comment)
def get_issue_comments(self):
return self.provider.get_issue_comments()
def get_comment_url(self, comment) -> str:
return self.provider.get_comment_url(comment)
#### labels operations ####
def publish_labels(self, labels):
2024-05-19 15:34:26 +08:00
if not os.environ.get("ENABLE_PUBLISH_LABELS", None):
2024-05-18 22:05:51 +08:00
return None
return self.provider.publish_labels(labels)
def get_pr_labels(self, update=False):
return self.provider.get_pr_labels(update=update)
def get_repo_labels(self):
return self.provider.get_repo_labels()
def add_eyes_reaction(self, issue_comment_id: int, disable_eyes: bool = False) -> Optional[int]:
return self.provider.add_eyes_reaction(issue_comment_id, disable_eyes=disable_eyes)
def remove_reaction(self, issue_comment_id: int, reaction_id: int) -> bool:
return self.provider.remove_reaction(issue_comment_id, reaction_id)
#### commits operations ####
def get_commit_messages(self):
return self.provider.get_commit_messages()
def get_pr_url(self) -> str:
return self.provider.get_pr_url()
def get_latest_commit_url(self) -> str:
return self.provider.get_latest_commit_url()
def auto_approve(self) -> bool:
return self.provider.auto_approve()
def calc_pr_statistics(self, pull_request_data: dict):
return self.provider.calc_pr_statistics(pull_request_data)
def get_num_of_files(self):
return self.provider.get_num_of_files()
2024-05-19 15:34:26 +08:00
2024-05-18 22:05:51 +08:00
@staticmethod
def _parse_issue_url(issue_url: str) -> Tuple[str, int]:
return GithubProvider._parse_issue_url(issue_url)