minor fixes

minor fixes
This commit is contained in:
mrT23
2023-07-17 08:18:42 +03:00
parent 2dfd34bd61
commit 8f3520807c
9 changed files with 56 additions and 37 deletions

View File

@ -72,20 +72,20 @@ To set up your own PR-Agent, see the [Quickstart](#Quickstart) section
## Overview ## Overview
`PR-Agent` offers extensive pull request functionalities across various git providers: `PR-Agent` offers extensive pull request functionalities across various git providers:
| | | GitHub | Gitlab | Bitbucket | | | | GitHub | Gitlab | Bitbucket |
|-------|---------------------------------------------|--------|--------|-----------| |-------|---------------------------------------------|:------:|:------:|:---------:|
| TOOLS | Review | | | | | TOOLS | Review | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| | ⮑ Inline review | | | | | | ⮑ Inline review | :white_check_mark: | :white_check_mark: | |
| | Ask | | | | | | Ask | :white_check_mark: | :white_check_mark: | |
| | Auto-Description | | | | | | Auto-Description | :white_check_mark: | | |
| | Improve Code | | | | | | Improve Code | :white_check_mark: | :white_check_mark: | |
| | | | | | | | | | | |
| USAGE | CLI | | | | | USAGE | CLI | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| | Tagging bot | | | | | | Tagging bot | :white_check_mark: | :white_check_mark: | |
| | Actions | | | | | | Actions | :white_check_mark: | | |
| | | | | | | | | | | |
| CORE | PR compression | | | | | CORE | PR compression | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| | Repo language prioritization | | | | | | Repo language prioritization | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| | Adaptive and token-aware<br />file patch fitting | | | | | | Adaptive and token-aware<br />file patch fitting | :white_check_mark: | :white_check_mark: | :white_check_mark: |
Examples for invoking the different tools via the [CLI](#quickstart): Examples for invoking the different tools via the [CLI](#quickstart):
- **Review**: python cli.py --pr-url=<pr_url> review - **Review**: python cli.py --pr-url=<pr_url> review
@ -122,8 +122,8 @@ Here are several ways to install and run PR-Agent:
**PR-Agent** provides four types of interactions ("tools"): `"PR Reviewer"`, `"PR Q&A"`, `"PR Description"` and `"PR Code Sueggestions"`. **PR-Agent** provides four types of interactions ("tools"): `"PR Reviewer"`, `"PR Q&A"`, `"PR Description"` and `"PR Code Sueggestions"`.
- The "PR Reviewer" tool automatically analyzes PRs, and provides different types of feedback. - The "PR Reviewer" tool automatically analyzes PRs, and provides various types of feedback.
- The "PR Ask" tool answers free-text questions about the PR. - The "PR Q&A" tool answers free-text questions about the PR.
- The "PR Description" tool automatically sets the PR Title and body. - The "PR Description" tool automatically sets the PR Title and body.
- The "PR Code Suggestion" tool provide inline code suggestions for the PR that can be applied and committed. - The "PR Code Suggestion" tool provide inline code suggestions for the PR that can be applied and committed.

View File

@ -14,10 +14,10 @@ def run():
parser = argparse.ArgumentParser(description='AI based pull request analyzer', usage="""\ parser = argparse.ArgumentParser(description='AI based pull request analyzer', usage="""\
Usage: cli.py --pr-url <URL on supported git hosting service> <command> [<args>]. Usage: cli.py --pr-url <URL on supported git hosting service> <command> [<args>].
For example: For example:
- cli.py --pr-url xxx review - cli.py --pr-url=... review
- cli.py --pr-url xxx describe - cli.py --pr-url=... describe
- cli.py --pr-url xxx improve - cli.py --pr-url=... improve
- cli.py --pr-url xxx ask "write me a poem about this PR" - cli.py --pr-url=... ask "write me a poem about this PR"
Supported commands: Supported commands:
review / review_pr - Add a review that includes a summary of the PR and specific suggestions for improvement. review / review_pr - Add a review that includes a summary of the PR and specific suggestions for improvement.

View File

@ -1,8 +1,8 @@
[config] [config]
model="gpt-4-0613" model="gpt-4-0613"
git_provider="github" git_provider="github"
publish_review=true publish_output=true
verbosity_level=2 # 0,1,2 verbosity_level=0 # 0,1,2
[pr_reviewer] [pr_reviewer]
require_focused_review=true require_focused_review=true
@ -11,6 +11,9 @@ require_security_review=true
num_code_suggestions=3 num_code_suggestions=3
inline_code_comments = true inline_code_comments = true
[pr_description]
publish_description_as_comment=false
[pr_questions] [pr_questions]
[pr_code_suggestions] [pr_code_suggestions]

View File

@ -2,8 +2,11 @@
system="""You are CodiumAI-PR-Reviewer, a language model designed to review git pull requests. system="""You are CodiumAI-PR-Reviewer, a language model designed to review git pull requests.
Your task is to provide constructive and concise feedback for the PR, and also provide meaningfull code suggestions to improve the new PR code (the '+' lines). Your task is to provide constructive and concise feedback for the PR, and also provide meaningfull code suggestions to improve the new PR code (the '+' lines).
- Provide up to {{ num_code_suggestions }} code suggestions. - Provide up to {{ num_code_suggestions }} code suggestions.
{%- if num_code_suggestions > 0 %}
- Try to focus on important suggestions like fixing code problems, issues and bugs. As a second priority, provide suggestions for meaningfull code improvements, like performance, vulnerability, modularity, and best practices. - Try to focus on important suggestions like fixing code problems, issues and bugs. As a second priority, provide suggestions for meaningfull code improvements, like performance, vulnerability, modularity, and best practices.
- Suggestions should focus on improving the new added code lines.
- Make sure not to provide suggestions repeating modifications already implemented in the new PR code (the '+' lines). - Make sure not to provide suggestions repeating modifications already implemented in the new PR code (the '+' lines).
{%- endif %}
You must use the following JSON schema to format your answer: You must use the following JSON schema to format your answer:
```json ```json
@ -35,6 +38,7 @@ You must use the following JSON schema to format your answer:
"type": "string", "type": "string",
"description": "General suggestions and feedback for the contributors and maintainers of this PR. May include important suggestions for the overall structure, primary purpose, best practices, critical bugs, and other aspects of the PR. Explain your suggestions." "description": "General suggestions and feedback for the contributors and maintainers of this PR. May include important suggestions for the overall structure, primary purpose, best practices, critical bugs, and other aspects of the PR. Explain your suggestions."
}, },
{%- if num_code_suggestions > 0 %}
"Code suggestions": { "Code suggestions": {
"type": "array", "type": "array",
"maxItems": {{ num_code_suggestions }}, "maxItems": {{ num_code_suggestions }},
@ -54,6 +58,7 @@ You must use the following JSON schema to format your answer:
} }
} }
}, },
{%- endif %}
{%- if require_security %} {%- if require_security %}
"Security concerns": { "Security concerns": {
"type": "string", "type": "string",
@ -82,6 +87,7 @@ Example output:
"PR Feedback": "PR Feedback":
{ {
"General PR suggestions": "..., `xxx`...", "General PR suggestions": "..., `xxx`...",
{%- if num_code_suggestions > 0 %}
"Code suggestions": [ "Code suggestions": [
{ {
"relevant file": "directory/xxx.py", "relevant file": "directory/xxx.py",
@ -90,6 +96,7 @@ Example output:
}, },
... ...
] ]
{%- endif %}
{%- if require_security %}, {%- if require_security %},
"Security concerns": "No, because ..." "Security concerns": "No, because ..."
{%- endif %} {%- endif %}

View File

@ -42,7 +42,7 @@ class PRCodeSuggestions:
assert type(self.git_provider) != BitbucketProvider, "Bitbucket is not supported for now" assert type(self.git_provider) != BitbucketProvider, "Bitbucket is not supported for now"
logging.info('Generating code suggestions for PR...') logging.info('Generating code suggestions for PR...')
if settings.config.publish_review: if settings.config.publish_output:
self.git_provider.publish_comment("Preparing review...", is_temporary=True) self.git_provider.publish_comment("Preparing review...", is_temporary=True)
logging.info('Getting PR diff...') logging.info('Getting PR diff...')
@ -56,7 +56,7 @@ class PRCodeSuggestions:
self.prediction = await self._get_prediction() self.prediction = await self._get_prediction()
logging.info('Preparing PR review...') logging.info('Preparing PR review...')
data = self._prepare_pr_code_suggestions() data = self._prepare_pr_code_suggestions()
if settings.config.publish_review: if settings.config.publish_output:
logging.info('Pushing PR review...') logging.info('Pushing PR review...')
self.git_provider.remove_initial_comment() self.git_provider.remove_initial_comment()
logging.info('Pushing inline code comments...') logging.info('Pushing inline code comments...')

View File

@ -36,16 +36,19 @@ class PRDescription:
async def describe(self): async def describe(self):
logging.info('Generating a PR description...') logging.info('Generating a PR description...')
if settings.config.publish_review: if settings.config.publish_output:
self.git_provider.publish_comment("Preparing pr description...", is_temporary=True) self.git_provider.publish_comment("Preparing pr description...", is_temporary=True)
logging.info('Getting PR diff...') logging.info('Getting PR diff...')
self.patches_diff = get_pr_diff(self.git_provider, self.token_handler) self.patches_diff = get_pr_diff(self.git_provider, self.token_handler)
logging.info('Getting AI prediction...') logging.info('Getting AI prediction...')
self.prediction = await self._get_prediction() self.prediction = await self._get_prediction()
logging.info('Preparing answer...') logging.info('Preparing answer...')
pr_title, pr_body = self._prepare_pr_answer() pr_title, pr_body, markdown_text = self._prepare_pr_answer()
if settings.config.publish_review: if settings.config.publish_output:
logging.info('Pushing answer...') logging.info('Pushing answer...')
if settings.pr_description.publish_description_as_comment:
self.git_provider.publish_comment(markdown_text)
else:
self.git_provider.publish_description(pr_title, pr_body) self.git_provider.publish_description(pr_title, pr_body)
self.git_provider.remove_initial_comment() self.git_provider.remove_initial_comment()
return "" return ""
@ -66,10 +69,11 @@ class PRDescription:
def _prepare_pr_answer(self): def _prepare_pr_answer(self):
data = json.loads(self.prediction) data = json.loads(self.prediction)
markdown_text = ""
for key, value in data.items():
markdown_text += f"## {key}\n\n"
markdown_text += f"{value}\n\n"
pr_body = "" pr_body = ""
# for key, value in data.items():
# markdown_text += f"## {key}\n\n"
# markdown_text += f"{value}\n\n"
title = data['PR Title'] title = data['PR Title']
del data['PR Title'] del data['PR Title']
for key, value in data.items(): for key, value in data.items():
@ -80,4 +84,4 @@ class PRDescription:
pr_body += f"**{value}**\n\n___\n" pr_body += f"**{value}**\n\n___\n"
if settings.config.verbosity_level >= 2: if settings.config.verbosity_level >= 2:
logging.info(f"title:\n{title}\n{pr_body}") logging.info(f"title:\n{title}\n{pr_body}")
return title, pr_body return title, pr_body, markdown_text

View File

@ -34,7 +34,7 @@ class PRInformationFromUser:
async def generate_questions(self): async def generate_questions(self):
logging.info('Generating question to the user...') logging.info('Generating question to the user...')
if settings.config.publish_review: if settings.config.publish_output:
self.git_provider.publish_comment("Preparing answer...", is_temporary=True) self.git_provider.publish_comment("Preparing answer...", is_temporary=True)
logging.info('Getting PR diff...') logging.info('Getting PR diff...')
self.patches_diff = get_pr_diff(self.git_provider, self.token_handler) self.patches_diff = get_pr_diff(self.git_provider, self.token_handler)
@ -42,7 +42,7 @@ class PRInformationFromUser:
self.prediction = await self._get_prediction() self.prediction = await self._get_prediction()
logging.info('Preparing questions...') logging.info('Preparing questions...')
pr_comment = self._prepare_pr_answer() pr_comment = self._prepare_pr_answer()
if settings.config.publish_review: if settings.config.publish_output:
logging.info('Pushing questions...') logging.info('Pushing questions...')
self.git_provider.publish_comment(pr_comment) self.git_provider.publish_comment(pr_comment)
self.git_provider.remove_initial_comment() self.git_provider.remove_initial_comment()

View File

@ -36,7 +36,7 @@ class PRQuestions:
async def answer(self): async def answer(self):
logging.info('Answering a PR question...') logging.info('Answering a PR question...')
if settings.config.publish_review: if settings.config.publish_output:
self.git_provider.publish_comment("Preparing answer...", is_temporary=True) self.git_provider.publish_comment("Preparing answer...", is_temporary=True)
logging.info('Getting PR diff...') logging.info('Getting PR diff...')
self.patches_diff = get_pr_diff(self.git_provider, self.token_handler) self.patches_diff = get_pr_diff(self.git_provider, self.token_handler)
@ -44,7 +44,7 @@ class PRQuestions:
self.prediction = await self._get_prediction() self.prediction = await self._get_prediction()
logging.info('Preparing answer...') logging.info('Preparing answer...')
pr_comment = self._prepare_pr_answer() pr_comment = self._prepare_pr_answer()
if settings.config.publish_review: if settings.config.publish_output:
logging.info('Pushing answer...') logging.info('Pushing answer...')
self.git_provider.publish_comment(pr_comment) self.git_provider.publish_comment(pr_comment)
self.git_provider.remove_initial_comment() self.git_provider.remove_initial_comment()

View File

@ -43,7 +43,7 @@ class PRReviewer:
async def review(self): async def review(self):
logging.info('Reviewing PR...') logging.info('Reviewing PR...')
if settings.config.publish_review: if settings.config.publish_output:
self.git_provider.publish_comment("Preparing review...", is_temporary=True) self.git_provider.publish_comment("Preparing review...", is_temporary=True)
logging.info('Getting PR diff...') logging.info('Getting PR diff...')
self.patches_diff = get_pr_diff(self.git_provider, self.token_handler) self.patches_diff = get_pr_diff(self.git_provider, self.token_handler)
@ -51,7 +51,7 @@ class PRReviewer:
self.prediction = await self._get_prediction() self.prediction = await self._get_prediction()
logging.info('Preparing PR review...') logging.info('Preparing PR review...')
pr_comment = self._prepare_pr_review() pr_comment = self._prepare_pr_review()
if settings.config.publish_review: if settings.config.publish_output:
logging.info('Pushing PR review...') logging.info('Pushing PR review...')
self.git_provider.publish_comment(pr_comment) self.git_provider.publish_comment(pr_comment)
self.git_provider.remove_initial_comment() self.git_provider.remove_initial_comment()
@ -89,7 +89,9 @@ class PRReviewer:
del data['PR Feedback']['Security concerns'] del data['PR Feedback']['Security concerns']
data['PR Analysis']['Security concerns'] = val data['PR Analysis']['Security concerns'] = val
if settings.config.git_provider == 'github' and settings.pr_reviewer.inline_code_comments: if settings.config.git_provider == 'github' and \
settings.pr_reviewer.inline_code_comments and \
'Code suggestions' in data['PR Feedback']:
del data['PR Feedback']['Code suggestions'] del data['PR Feedback']['Code suggestions']
markdown_text = convert_to_markdown(data) markdown_text = convert_to_markdown(data)
@ -107,6 +109,9 @@ class PRReviewer:
return markdown_text return markdown_text
def _publish_inline_code_comments(self): def _publish_inline_code_comments(self):
if settings.pr_reviewer.num_code_suggestions == 0:
return
review = self.prediction.strip() review = self.prediction.strip()
try: try:
data = json.loads(review) data = json.loads(review)