mirror of
https://github.com/qodo-ai/pr-agent.git
synced 2025-07-06 22:00:40 +08:00
toolbar emojis in pr-agent feedbacks
This commit is contained in:
@ -72,7 +72,7 @@ def convert_to_markdown(output_data: dict, gfm_supported: bool = True, increment
|
|||||||
|
|
||||||
emojis = {
|
emojis = {
|
||||||
"Can be split": "🔀",
|
"Can be split": "🔀",
|
||||||
"Possible issues": "🔍",
|
"Possible issues": "⚡",
|
||||||
"Score": "🏅",
|
"Score": "🏅",
|
||||||
"Relevant tests": "🧪",
|
"Relevant tests": "🧪",
|
||||||
"Focused PR": "✨",
|
"Focused PR": "✨",
|
||||||
@ -83,9 +83,9 @@ def convert_to_markdown(output_data: dict, gfm_supported: bool = True, increment
|
|||||||
}
|
}
|
||||||
markdown_text = ""
|
markdown_text = ""
|
||||||
if not incremental_review:
|
if not incremental_review:
|
||||||
markdown_text += f"## PR Review\n\n"
|
markdown_text += f"## PR Review 🔍\n\n"
|
||||||
else:
|
else:
|
||||||
markdown_text += f"## Incremental PR Review\n\n"
|
markdown_text += f"## Incremental PR Review 🔍 \n\n"
|
||||||
markdown_text += f"⏮️ Review for commits since previous PR-Agent review {incremental_review}.\n\n"
|
markdown_text += f"⏮️ Review for commits since previous PR-Agent review {incremental_review}.\n\n"
|
||||||
if gfm_supported:
|
if gfm_supported:
|
||||||
markdown_text += "<table>\n<tr>\n"
|
markdown_text += "<table>\n<tr>\n"
|
||||||
|
@ -71,7 +71,7 @@ class GitProvider(ABC):
|
|||||||
|
|
||||||
# if the existing description was generated by the pr-agent, but it doesn't contain a user description,
|
# if the existing description was generated by the pr-agent, but it doesn't contain a user description,
|
||||||
# return nothing (empty string) because it means there is no user description
|
# return nothing (empty string) because it means there is no user description
|
||||||
user_description_header = "## **user description**"
|
user_description_header = "### **user description**"
|
||||||
if user_description_header not in description_lowercase:
|
if user_description_header not in description_lowercase:
|
||||||
get_logger().info(f"Existing description was generated by the pr-agent, but it doesn't contain a user description")
|
get_logger().info(f"Existing description was generated by the pr-agent, but it doesn't contain a user description")
|
||||||
return ""
|
return ""
|
||||||
@ -102,8 +102,8 @@ class GitProvider(ABC):
|
|||||||
return original_user_description
|
return original_user_description
|
||||||
|
|
||||||
def _possible_headers(self):
|
def _possible_headers(self):
|
||||||
return ("## **user description**", "## **pr type**", "## **pr description**", "## **pr labels**", "## **type**", "## **description**",
|
return ("### **user description**", "### **pr type**", "### **pr description**", "### **pr labels**", "### **type**", "### **description**",
|
||||||
"## **labels**", "### 🤖 generated by pr agent")
|
"### **labels**", "### 🤖 generated by pr agent")
|
||||||
|
|
||||||
def _is_generated_by_pr_agent(self, description_lowercase: str) -> bool:
|
def _is_generated_by_pr_agent(self, description_lowercase: str) -> bool:
|
||||||
possible_headers = self._possible_headers()
|
possible_headers = self._possible_headers()
|
||||||
|
@ -179,7 +179,7 @@ You can ask questions about the entire PR, about specific code lines, or about a
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def get_improve_usage_guide():
|
def get_improve_usage_guide():
|
||||||
output = "**Overview:**\n"
|
output = "**Overview:**\n"
|
||||||
output += "The `improve` tool scans the PR code changes, and automatically generates suggestions for improving the PR code. "
|
output += "The code suggestions tool, named `improve`, scans the PR code changes, and automatically generates code suggestions for improving the PR."
|
||||||
output += "The tool can be triggered [automatically](https://pr-agent-docs.codium.ai/usage-guide/automations_and_usage/#github-app-automatic-tools-when-a-new-pr-is-opened) every time a new PR is opened, or can be invoked manually by commenting on a PR.\n"
|
output += "The tool can be triggered [automatically](https://pr-agent-docs.codium.ai/usage-guide/automations_and_usage/#github-app-automatic-tools-when-a-new-pr-is-opened) every time a new PR is opened, or can be invoked manually by commenting on a PR.\n"
|
||||||
output += """\
|
output += """\
|
||||||
- When commenting, to edit [configurations](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L78) related to the improve tool (`pr_code_suggestions` section), use the following template:
|
- When commenting, to edit [configurations](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L78) related to the improve tool (`pr_code_suggestions` section), use the following template:
|
||||||
|
@ -44,7 +44,7 @@ enable_review_labels_effort=true
|
|||||||
require_all_thresholds_for_incremental_review=false
|
require_all_thresholds_for_incremental_review=false
|
||||||
minimal_commits_for_incremental_review=0
|
minimal_commits_for_incremental_review=0
|
||||||
minimal_minutes_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.
|
enable_help_text=false # Determines whether to include help text in the PR review. Enabled by default.
|
||||||
# auto approval
|
# auto approval
|
||||||
enable_auto_approval=false
|
enable_auto_approval=false
|
||||||
maximal_review_effort=5
|
maximal_review_effort=5
|
||||||
@ -74,7 +74,7 @@ include_generated_by_header=true
|
|||||||
#custom_labels = ['Bug fix', 'Tests', 'Bug fix with tests', 'Enhancement', 'Documentation', 'Other']
|
#custom_labels = ['Bug fix', 'Tests', 'Bug fix with tests', 'Enhancement', 'Documentation', 'Other']
|
||||||
|
|
||||||
[pr_questions] # /ask #
|
[pr_questions] # /ask #
|
||||||
enable_help_text=true
|
enable_help_text=false
|
||||||
|
|
||||||
|
|
||||||
[pr_code_suggestions] # /improve #
|
[pr_code_suggestions] # /improve #
|
||||||
@ -83,7 +83,7 @@ num_code_suggestions=4
|
|||||||
commitable_code_suggestions = false
|
commitable_code_suggestions = false
|
||||||
extra_instructions = ""
|
extra_instructions = ""
|
||||||
rank_suggestions = false
|
rank_suggestions = false
|
||||||
enable_help_text=true
|
enable_help_text=false
|
||||||
persistent_comment=false
|
persistent_comment=false
|
||||||
# params for '/improve --extended' mode
|
# params for '/improve --extended' mode
|
||||||
auto_extended_mode=true
|
auto_extended_mode=true
|
||||||
@ -110,7 +110,7 @@ num_tests=3 # number of tests to generate. max 5.
|
|||||||
avoid_mocks=true # if true, the generated tests will prefer to use real objects instead of mocks
|
avoid_mocks=true # if true, the generated tests will prefer to use real objects instead of mocks
|
||||||
file = "" # in case there are several components with the same name, you can specify the relevant file
|
file = "" # in case there are several components with the same name, you can specify the relevant file
|
||||||
class_name = "" # in case there are several methods with the same name in the same file, you can specify the relevant class name
|
class_name = "" # in case there are several methods with the same name in the same file, you can specify the relevant class name
|
||||||
enable_help_text=true
|
enable_help_text=false
|
||||||
|
|
||||||
[pr_improve_component] # /improve_component #
|
[pr_improve_component] # /improve_component #
|
||||||
num_code_suggestions=4
|
num_code_suggestions=4
|
||||||
|
@ -90,7 +90,7 @@ class PRCodeSuggestions:
|
|||||||
|
|
||||||
if (not data) or (not 'code_suggestions' in data) or (not data['code_suggestions']):
|
if (not data) or (not 'code_suggestions' in data) or (not data['code_suggestions']):
|
||||||
get_logger().error('No code suggestions found for PR.')
|
get_logger().error('No code suggestions found for PR.')
|
||||||
pr_body = "## PR Code Suggestions\n\nNo code suggestions found for PR."
|
pr_body = "## PR Code Suggestions ✨\n\nNo code suggestions found for PR."
|
||||||
get_logger().debug(f"PR output", artifact=pr_body)
|
get_logger().debug(f"PR output", artifact=pr_body)
|
||||||
if self.progress_response:
|
if self.progress_response:
|
||||||
self.git_provider.edit_comment(self.progress_response, body=pr_body)
|
self.git_provider.edit_comment(self.progress_response, body=pr_body)
|
||||||
@ -113,14 +113,14 @@ class PRCodeSuggestions:
|
|||||||
|
|
||||||
# add usage guide
|
# add usage guide
|
||||||
if get_settings().pr_code_suggestions.enable_help_text:
|
if get_settings().pr_code_suggestions.enable_help_text:
|
||||||
pr_body += "<hr>\n\n<details> <summary><strong>✨ Improve tool usage guide:</strong></summary><hr> \n\n"
|
pr_body += "<hr>\n\n<details> <summary><strong>💡 Tool usage guide:</strong></summary><hr> \n\n"
|
||||||
pr_body += HelpMessage.get_improve_usage_guide()
|
pr_body += HelpMessage.get_improve_usage_guide()
|
||||||
pr_body += "\n</details>\n"
|
pr_body += "\n</details>\n"
|
||||||
|
|
||||||
if get_settings().pr_code_suggestions.persistent_comment:
|
if get_settings().pr_code_suggestions.persistent_comment:
|
||||||
final_update_message = False
|
final_update_message = False
|
||||||
self.git_provider.publish_persistent_comment(pr_body,
|
self.git_provider.publish_persistent_comment(pr_body,
|
||||||
initial_header="## PR Code Suggestions",
|
initial_header="## PR Code Suggestions ✨",
|
||||||
update_header=True,
|
update_header=True,
|
||||||
name="suggestions",
|
name="suggestions",
|
||||||
final_update_message=final_update_message, )
|
final_update_message=final_update_message, )
|
||||||
@ -382,7 +382,7 @@ class PRCodeSuggestions:
|
|||||||
|
|
||||||
def generate_summarized_suggestions(self, data: Dict) -> str:
|
def generate_summarized_suggestions(self, data: Dict) -> str:
|
||||||
try:
|
try:
|
||||||
pr_body = "## PR Code Suggestions\n\n"
|
pr_body = "## PR Code Suggestions ✨\n\n"
|
||||||
|
|
||||||
if len(data.get('code_suggestions', [])) == 0:
|
if len(data.get('code_suggestions', [])) == 0:
|
||||||
pr_body += "No suggestions found to improve this PR."
|
pr_body += "No suggestions found to improve this PR."
|
||||||
@ -394,7 +394,7 @@ class PRCodeSuggestions:
|
|||||||
for ext in extensions:
|
for ext in extensions:
|
||||||
extension_to_language[ext] = language
|
extension_to_language[ext] = language
|
||||||
|
|
||||||
pr_body = "## PR Code Suggestions\n\n"
|
pr_body = "## PR Code Suggestions ✨\n\n"
|
||||||
|
|
||||||
pr_body += "<table>"
|
pr_body += "<table>"
|
||||||
header = f"Suggestions"
|
header = f"Suggestions"
|
||||||
|
@ -113,7 +113,7 @@ class PRDescription:
|
|||||||
pr_body += HelpMessage.get_describe_usage_guide()
|
pr_body += HelpMessage.get_describe_usage_guide()
|
||||||
pr_body += "\n</details>\n"
|
pr_body += "\n</details>\n"
|
||||||
elif get_settings().pr_description.enable_help_comment:
|
elif get_settings().pr_description.enable_help_comment:
|
||||||
pr_body += "\n\n___\n\n> ✨ **PR-Agent usage**:"
|
pr_body += "\n\n___\n\n> 💡 **PR-Agent usage**:"
|
||||||
pr_body += "\n>Comment `/help` on the PR to get a list of all available PR-Agent tools and their descriptions\n\n"
|
pr_body += "\n>Comment `/help` on the PR to get a list of all available PR-Agent tools and their descriptions\n\n"
|
||||||
|
|
||||||
if get_settings().config.publish_output:
|
if get_settings().config.publish_output:
|
||||||
@ -317,7 +317,11 @@ class PRDescription:
|
|||||||
value = self.file_label_dict
|
value = self.file_label_dict
|
||||||
else:
|
else:
|
||||||
key_publish = key.rstrip(':').replace("_", " ").capitalize()
|
key_publish = key.rstrip(':').replace("_", " ").capitalize()
|
||||||
pr_body += f"## **{key_publish}**\n"
|
if key_publish== "Type":
|
||||||
|
key_publish = "PR Type"
|
||||||
|
# elif key_publish == "Description":
|
||||||
|
# key_publish = "PR Description"
|
||||||
|
pr_body += f"### **{key_publish}**\n"
|
||||||
if 'walkthrough' in key.lower():
|
if 'walkthrough' in key.lower():
|
||||||
if self.git_provider.is_supported("gfm_markdown"):
|
if self.git_provider.is_supported("gfm_markdown"):
|
||||||
pr_body += "<details> <summary>files:</summary>\n\n"
|
pr_body += "<details> <summary>files:</summary>\n\n"
|
||||||
@ -329,7 +333,7 @@ class PRDescription:
|
|||||||
pr_body += "</details>\n"
|
pr_body += "</details>\n"
|
||||||
elif 'pr_files' in key.lower():
|
elif 'pr_files' in key.lower():
|
||||||
changes_walkthrough, pr_file_changes = self.process_pr_files_prediction(changes_walkthrough, value)
|
changes_walkthrough, pr_file_changes = self.process_pr_files_prediction(changes_walkthrough, value)
|
||||||
changes_walkthrough = f"## **Changes walkthrough**\n{changes_walkthrough}"
|
changes_walkthrough = f"### **Changes walkthrough** 📝\n{changes_walkthrough}"
|
||||||
else:
|
else:
|
||||||
# if the value is a list, join its items by comma
|
# if the value is a list, join its items by comma
|
||||||
if isinstance(value, list):
|
if isinstance(value, list):
|
||||||
|
@ -68,7 +68,7 @@ class PRQuestions:
|
|||||||
get_logger().debug(f"PR output", artifact=pr_comment)
|
get_logger().debug(f"PR output", artifact=pr_comment)
|
||||||
|
|
||||||
if self.git_provider.is_supported("gfm_markdown") and get_settings().pr_questions.enable_help_text:
|
if self.git_provider.is_supported("gfm_markdown") and get_settings().pr_questions.enable_help_text:
|
||||||
pr_comment += "<hr>\n\n<details> <summary><strong>✨ Ask tool usage guide:</strong></summary><hr> \n\n"
|
pr_comment += "<hr>\n\n<details> <summary><strong>💡 Tool usage guide:</strong></summary><hr> \n\n"
|
||||||
pr_comment += HelpMessage.get_ask_usage_guide()
|
pr_comment += HelpMessage.get_ask_usage_guide()
|
||||||
pr_comment += "\n</details>\n"
|
pr_comment += "\n</details>\n"
|
||||||
|
|
||||||
@ -116,6 +116,6 @@ class PRQuestions:
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
def _prepare_pr_answer(self) -> str:
|
def _prepare_pr_answer(self) -> str:
|
||||||
answer_str = f"Question: {self.question_str}\n\n"
|
answer_str = f"### **Ask**❓\n{self.question_str}\n\n"
|
||||||
answer_str += f"Answer:\n{self.prediction.strip()}\n\n"
|
answer_str += f"### **Answer:**\n{self.prediction.strip()}\n\n"
|
||||||
return answer_str
|
return answer_str
|
||||||
|
@ -137,7 +137,7 @@ class PRReviewer:
|
|||||||
if get_settings().pr_reviewer.persistent_comment and not self.incremental.is_incremental:
|
if get_settings().pr_reviewer.persistent_comment and not self.incremental.is_incremental:
|
||||||
final_update_message = get_settings().pr_reviewer.final_update_message
|
final_update_message = get_settings().pr_reviewer.final_update_message
|
||||||
self.git_provider.publish_persistent_comment(pr_review,
|
self.git_provider.publish_persistent_comment(pr_review,
|
||||||
initial_header="## PR Review",
|
initial_header="## PR Review 🔍",
|
||||||
update_header=True,
|
update_header=True,
|
||||||
final_update_message=final_update_message, )
|
final_update_message=final_update_message, )
|
||||||
else:
|
else:
|
||||||
@ -234,7 +234,7 @@ class PRReviewer:
|
|||||||
|
|
||||||
# Add help text if gfm_markdown is supported
|
# Add help text if gfm_markdown is supported
|
||||||
if self.git_provider.is_supported("gfm_markdown") and get_settings().pr_reviewer.enable_help_text:
|
if self.git_provider.is_supported("gfm_markdown") and get_settings().pr_reviewer.enable_help_text:
|
||||||
markdown_text += "<hr>\n\n<details> <summary><strong>✨ Review tool usage guide:</strong></summary><hr> \n\n"
|
markdown_text += "<hr>\n\n<details> <summary><strong>💡 Tool usage guide:</strong></summary><hr> \n\n"
|
||||||
markdown_text += HelpMessage.get_review_usage_guide()
|
markdown_text += HelpMessage.get_review_usage_guide()
|
||||||
markdown_text += "\n</details>\n"
|
markdown_text += "\n</details>\n"
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ class PRUpdateChangelog:
|
|||||||
if self.commit_changelog:
|
if self.commit_changelog:
|
||||||
self._push_changelog_update(new_file_content, answer)
|
self._push_changelog_update(new_file_content, answer)
|
||||||
else:
|
else:
|
||||||
self.git_provider.publish_comment(f"**Changelog updates:**\n\n{answer}")
|
self.git_provider.publish_comment(f"**Changelog updates:** 🔄\n\n{answer}")
|
||||||
|
|
||||||
async def _prepare_prediction(self, model: str):
|
async def _prepare_prediction(self, model: str):
|
||||||
self.patches_diff = get_pr_diff(self.git_provider, self.token_handler, model)
|
self.patches_diff = get_pr_diff(self.git_provider, self.token_handler, model)
|
||||||
@ -141,7 +141,7 @@ class PRUpdateChangelog:
|
|||||||
self.git_provider.pr.create_review(commit=last_commit_id, comments=[d])
|
self.git_provider.pr.create_review(commit=last_commit_id, comments=[d])
|
||||||
except Exception:
|
except Exception:
|
||||||
# we can't create a review for some reason, let's just publish a comment
|
# we can't create a review for some reason, let's just publish a comment
|
||||||
self.git_provider.publish_comment(f"**Changelog updates:**\n\n{answer}")
|
self.git_provider.publish_comment(f"**Changelog updates: 🔄**\n\n{answer}")
|
||||||
|
|
||||||
def _get_default_changelog(self):
|
def _get_default_changelog(self):
|
||||||
example_changelog = \
|
example_changelog = \
|
||||||
|
@ -52,7 +52,7 @@ class TestConvertToMarkdown:
|
|||||||
'suggestion': "Consider raising an exception or logging a warning when 'pr_url' attribute is not found. This can help in debugging issues related to the absence of 'pr_url' in instances where it's expected. [important]\n",
|
'suggestion': "Consider raising an exception or logging a warning when 'pr_url' attribute is not found. This can help in debugging issues related to the absence of 'pr_url' in instances where it's expected. [important]\n",
|
||||||
'relevant_line': '[return ""](https://github.com/Codium-ai/pr-agent-pro/pull/102/files#diff-52d45f12b836f77ed1aef86e972e65404634ea4e2a6083fb71a9b0f9bb9e062fR199)'}]}
|
'relevant_line': '[return ""](https://github.com/Codium-ai/pr-agent-pro/pull/102/files#diff-52d45f12b836f77ed1aef86e972e65404634ea4e2a6083fb71a9b0f9bb9e062fR199)'}]}
|
||||||
|
|
||||||
expected_output = '## PR Review\n\n<table>\n<tr>\n<tr><td> ⏱️ <strong>Estimated effort to review [1-5]</strong></td><td>\n\n1, because the changes are minimal and straightforward, focusing on a single functionality addition.\n\n\n</td></tr>\n<tr><td> 🧪 <strong>Relevant tests</strong></td><td>\n\nNo\n\n\n</td></tr>\n<tr><td> 🔍 <strong>Possible issues</strong></td><td>\n\nNo\n\n</td></tr>\n<tr><td> 🔒 <strong>Security concerns</strong></td><td>\n\nNo\n\n</td></tr>\n</table>\n\n\n<details><summary> <strong>Code feedback:</strong></summary>\n\n<hr><table><tr><td>relevant file</td><td>pr_agent/git_providers/git_provider.py\n</td></tr><tr><td>suggestion </td><td>\n\n<strong>\n\nConsider raising an exception or logging a warning when \'pr_url\' attribute is not found. This can help in debugging issues related to the absence of \'pr_url\' in instances where it\'s expected. [important]\n\n</strong>\n</td></tr><tr><td>relevant line</td><td><a href=\'https://github.com/Codium-ai/pr-agent-pro/pull/102/files#diff-52d45f12b836f77ed1aef86e972e65404634ea4e2a6083fb71a9b0f9bb9e062fR199\'>return ""</a></td></tr></table><hr>\n\n</details>'
|
expected_output = '## PR Review 🔍\n\n<table>\n<tr>\n<tr><td> ⏱️ <strong>Estimated effort to review [1-5]</strong></td><td>\n\n1, because the changes are minimal and straightforward, focusing on a single functionality addition.\n\n\n</td></tr>\n<tr><td> 🧪 <strong>Relevant tests</strong></td><td>\n\nNo\n\n\n</td></tr>\n<tr><td> 🔍 <strong>Possible issues</strong></td><td>\n\nNo\n\n</td></tr>\n<tr><td> 🔒 <strong>Security concerns</strong></td><td>\n\nNo\n\n</td></tr>\n</table>\n\n\n<details><summary> <strong>Code feedback:</strong></summary>\n\n<hr><table><tr><td>relevant file</td><td>pr_agent/git_providers/git_provider.py\n</td></tr><tr><td>suggestion </td><td>\n\n<strong>\n\nConsider raising an exception or logging a warning when \'pr_url\' attribute is not found. This can help in debugging issues related to the absence of \'pr_url\' in instances where it\'s expected. [important]\n\n</strong>\n</td></tr><tr><td>relevant line</td><td><a href=\'https://github.com/Codium-ai/pr-agent-pro/pull/102/files#diff-52d45f12b836f77ed1aef86e972e65404634ea4e2a6083fb71a9b0f9bb9e062fR199\'>return ""</a></td></tr></table><hr>\n\n</details>'
|
||||||
|
|
||||||
assert convert_to_markdown(input_data).strip() == expected_output.strip()
|
assert convert_to_markdown(input_data).strip() == expected_output.strip()
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user