mirror of
https://github.com/qodo-ai/pr-agent.git
synced 2025-07-06 05:40:38 +08:00
Compare commits
4 Commits
feature/su
...
feature/me
Author | SHA1 | Date | |
---|---|---|---|
987befe457 | |||
aa1c32c714 | |||
f1004273ec | |||
33f859b073 |
16
README.md
16
README.md
@ -9,7 +9,6 @@ It automatically analyzes the PR, and provides feedback and suggestions, and can
|
||||
It is powered by GPT-4, and is based on the [CodiumAI](https://github.com/Codium-ai/) platform.
|
||||
</div>
|
||||
|
||||
TBD: Add screenshot of the PR Reviewer (could be gif)
|
||||
|
||||
|
||||
* [Quickstart](#Quickstart)
|
||||
@ -17,10 +16,7 @@ TBD: Add screenshot of the PR Reviewer (could be gif)
|
||||
* [Usage and Tools](#usage-and-tools)
|
||||
* [Roadmap](#roadmap)
|
||||
* [Similar projects](#similar-projects)
|
||||
* Additional files:
|
||||
* CONTRIBUTION.md
|
||||
* LICENSE
|
||||
*
|
||||
|
||||
|
||||
## Quickstart
|
||||
|
||||
@ -39,16 +35,14 @@ Python scripts from the scripts folder. Here's how:
|
||||
|
||||
1. To request a review for a PR, run the following command:
|
||||
```
|
||||
docker run --rm -it -e OPENAI.KEY=<your key> -e GITHUB.USER_TOKEN=<your token> codiumai/pr-agent \
|
||||
python pr_agent/scripts/review_pr_from_url.py --pr_url <pr url>
|
||||
docker run --rm -it -e OPENAI.KEY=<your key> -e GITHUB.USER_TOKEN=<your token> codiumai/pr-agent --pr_url <pr url>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
2. 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 \
|
||||
python pr_agent/scripts/answer_pr_questions_from_url.py --pr_url <pr url> --question "<your question>"
|
||||
docker run --rm -it -e OPENAI.KEY=<your key> -e GITHUB.USER_TOKEN=<your token> codiumai/pr-agent --pr_url <pr url> --question "<your question>"
|
||||
```
|
||||
|
||||
Possible questions you can ask include:
|
||||
@ -80,8 +74,8 @@ cp pr_agent/settings/.secrets_template.toml pr_agent/settings/.secrets
|
||||
|
||||
4. Run the appropriate Python scripts from the scripts folder:
|
||||
```
|
||||
python pr_agent/scripts/review_pr_from_url.py --pr_url <pr url>
|
||||
python pr_agent/scripts/answer_pr_questions_from_url.py --pr_url <pr url> --question "<your question>"
|
||||
python pr_agent/cli.py --pr_url <pr url>
|
||||
python pr_agent/cli.py --pr_url <pr url> --question "<your question>"
|
||||
```
|
||||
|
||||
---
|
||||
|
@ -7,14 +7,14 @@ ENV PYTHONPATH=/app
|
||||
ADD pr_agent pr_agent
|
||||
|
||||
FROM base as github_app
|
||||
CMD ["python", "servers/github_app.py"]
|
||||
CMD ["python", "pr_agent/servers/github_app.py"]
|
||||
|
||||
FROM base as github_polling
|
||||
CMD ["python", "servers/github_polling.py"]
|
||||
CMD ["python", "pr_agent/servers/github_polling.py"]
|
||||
|
||||
FROM base as test
|
||||
ADD requirements-dev.txt .
|
||||
RUN pip install -r requirements-dev.txt && rm requirements-dev.txt
|
||||
|
||||
FROM base as cli
|
||||
CMD ["bash"]
|
||||
ENTRYPOINT ["python", "pr_agent/cli.py"]
|
||||
|
27
pr_agent/cli.py
Normal file
27
pr_agent/cli.py
Normal file
@ -0,0 +1,27 @@
|
||||
import argparse
|
||||
import asyncio
|
||||
import logging
|
||||
import os
|
||||
|
||||
from pr_agent.tools.pr_questions import PRQuestions
|
||||
from pr_agent.tools.pr_reviewer import PRReviewer
|
||||
|
||||
|
||||
def run():
|
||||
parser = argparse.ArgumentParser(description='AI based pull request analyzer')
|
||||
parser.add_argument('--pr_url', type=str, help='The URL of the PR to review', required=True)
|
||||
parser.add_argument('--question', type=str, help='Optional question to ask', required=False)
|
||||
args = parser.parse_args()
|
||||
logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO"))
|
||||
if args.question:
|
||||
print(f"Question: {args.question} about PR {args.pr_url}")
|
||||
reviewer = PRQuestions(args.pr_url, args.question, None)
|
||||
asyncio.run(reviewer.answer())
|
||||
else:
|
||||
print(f"Reviewing PR: {args.pr_url}")
|
||||
reviewer = PRReviewer(args.pr_url, None)
|
||||
asyncio.run(reviewer.review())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
@ -1,3 +1,4 @@
|
||||
import logging
|
||||
from collections import namedtuple
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
@ -39,8 +40,20 @@ class GithubProvider:
|
||||
diff_files.append(FilePatchInfo(original_file_content_str, new_file_content_str, file.patch, file.filename))
|
||||
return diff_files
|
||||
|
||||
def publish_comment(self, pr_comment: str):
|
||||
self.pr.create_issue_comment(pr_comment)
|
||||
def publish_comment(self, pr_comment: str, is_temporary: bool = False):
|
||||
response = self.pr.create_issue_comment(pr_comment)
|
||||
response.is_temporary = is_temporary
|
||||
if not hasattr(self.pr, 'comments_list'):
|
||||
self.pr.comments_list = []
|
||||
self.pr.comments_list.append(response)
|
||||
|
||||
def remove_initial_comment(self):
|
||||
try:
|
||||
for comment in self.pr.comments_list:
|
||||
if comment.is_temporary:
|
||||
comment.delete()
|
||||
except Exception as e:
|
||||
logging.exception(f"Failed to remove initial comment, error: {e}")
|
||||
|
||||
def get_title(self):
|
||||
return self.pr.title
|
||||
@ -153,7 +166,9 @@ class GithubProvider:
|
||||
try:
|
||||
token = settings.github.user_token
|
||||
except AttributeError as e:
|
||||
raise ValueError("GitHub token is required when using user deployment") from e
|
||||
raise ValueError(
|
||||
"GitHub token is required when using user deployment. See: "
|
||||
"https://github.com/Codium-ai/pr-agent#method-2-run-from-source") from e
|
||||
return Github(token)
|
||||
|
||||
def _get_repo(self):
|
||||
|
@ -1,16 +0,0 @@
|
||||
import argparse
|
||||
import asyncio
|
||||
import logging
|
||||
import os
|
||||
|
||||
from pr_agent.tools.pr_questions import PRQuestions
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Review a PR from a URL')
|
||||
parser.add_argument('--pr_url', type=str, help='The URL of the PR to review', required=True)
|
||||
parser.add_argument('--question_str', type=str, help='The question to answer', required=True)
|
||||
|
||||
args = parser.parse_args()
|
||||
logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO"))
|
||||
reviewer = PRQuestions(args.pr_url, args.question_str, None)
|
||||
asyncio.run(reviewer.answer())
|
@ -1,14 +0,0 @@
|
||||
import argparse
|
||||
import asyncio
|
||||
import logging
|
||||
import os
|
||||
|
||||
from pr_agent.tools.pr_reviewer import PRReviewer
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Review a PR from a URL')
|
||||
parser.add_argument('--pr_url', type=str, help='The URL of the PR to review', required=True)
|
||||
args = parser.parse_args()
|
||||
logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO"))
|
||||
reviewer = PRReviewer(args.pr_url, None)
|
||||
asyncio.run(reviewer.review())
|
@ -35,7 +35,8 @@ class PRQuestions:
|
||||
|
||||
async def answer(self):
|
||||
logging.info('Answering a PR question...')
|
||||
self.git_provider.publish_comment("Preparing answer...")
|
||||
if settings.config.publish_review:
|
||||
self.git_provider.publish_comment("Preparing answer...", is_temporary=True)
|
||||
logging.info('Getting PR diff...')
|
||||
self.patches_diff = get_pr_diff(self.git_provider, self.token_handler)
|
||||
logging.info('Getting AI prediction...')
|
||||
@ -45,6 +46,7 @@ class PRQuestions:
|
||||
if settings.config.publish_review:
|
||||
logging.info('Pushing answer...')
|
||||
self.git_provider.publish_comment(pr_comment)
|
||||
self.git_provider.remove_initial_comment()
|
||||
return ""
|
||||
|
||||
async def _get_prediction(self):
|
||||
|
@ -42,7 +42,7 @@ class PRReviewer:
|
||||
async def review(self):
|
||||
logging.info('Reviewing PR...')
|
||||
if settings.config.publish_review:
|
||||
self.git_provider.publish_comment("Preparing review...")
|
||||
self.git_provider.publish_comment("Preparing review...", is_temporary=True)
|
||||
logging.info('Getting PR diff...')
|
||||
self.patches_diff = get_pr_diff(self.git_provider, self.token_handler)
|
||||
logging.info('Getting AI prediction...')
|
||||
@ -52,6 +52,7 @@ class PRReviewer:
|
||||
if settings.config.publish_review:
|
||||
logging.info('Pushing PR review...')
|
||||
self.git_provider.publish_comment(pr_comment)
|
||||
self.git_provider.remove_initial_comment()
|
||||
return ""
|
||||
|
||||
async def _get_prediction(self):
|
||||
|
Reference in New Issue
Block a user