mirror of
https://github.com/qodo-ai/pr-agent.git
synced 2025-07-08 23:00:43 +08:00
Compare commits
10 Commits
feature/be
...
ok/fix_bit
Author | SHA1 | Date | |
---|---|---|---|
ff04d459d7 | |||
88ca501c0c | |||
fe284a8f91 | |||
d41fe0cf79 | |||
d5c098de73 | |||
9f5c0daa8e | |||
bce2262d4e | |||
e6f1e0520a | |||
d8de89ae33 | |||
428c38e3d9 |
@ -1,18 +0,0 @@
|
|||||||
FROM python:3.10 as base
|
|
||||||
|
|
||||||
ENV OPENAI_API_KEY=${OPENAI_API_KEY} \
|
|
||||||
BITBUCKET_BEARER_TOKEN=${BITBUCKET_BEARER_TOKEN} \
|
|
||||||
BITBUCKET_PR_ID=${BITBUCKET_PR_ID} \
|
|
||||||
BITBUCKET_REPO_SLUG=${BITBUCKET_REPO_SLUG} \
|
|
||||||
BITBUCKET_WORKSPACE=${BITBUCKET_WORKSPACE}
|
|
||||||
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
ADD pyproject.toml .
|
|
||||||
ADD requirements.txt .
|
|
||||||
RUN pip install . && rm pyproject.toml requirements.txt
|
|
||||||
ENV PYTHONPATH=/app
|
|
||||||
ADD pr_agent pr_agent
|
|
||||||
ADD bitbucket_pipeline/entrypoint.sh /
|
|
||||||
RUN chmod +x /entrypoint.sh
|
|
||||||
ENTRYPOINT ["/entrypoint.sh"]
|
|
45
INSTALL.md
45
INSTALL.md
@ -375,59 +375,28 @@ In the "Trigger" section, check the ‘comments’ and ‘merge request events
|
|||||||
### Method 9: Run as a Bitbucket Pipeline
|
### Method 9: Run as a Bitbucket Pipeline
|
||||||
|
|
||||||
|
|
||||||
You can use our pre-build Bitbucket-Pipeline docker image to run as Bitbucket-Pipeline.
|
You can use the Bitbucket Pipeline system to run PR-Agent on every pull request open or update.
|
||||||
|
|
||||||
1. Add the following file in your repository bitbucket_pipelines.yml
|
1. Add the following file in your repository bitbucket_pipelines.yml
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
pipelines:
|
pipelines:
|
||||||
pull-requests:
|
pull-requests:
|
||||||
'**':
|
'**':
|
||||||
- step:
|
- step:
|
||||||
name: PR Agent Pipeline
|
name: PR Agent Review
|
||||||
caches:
|
image: python:3.10
|
||||||
- pip
|
|
||||||
image: python:3.8
|
|
||||||
services:
|
services:
|
||||||
- docker
|
- docker
|
||||||
script:
|
script:
|
||||||
- git clone https://github.com/Codium-ai/pr-agent.git
|
- docker run -e CONFIG.GIT_PROVIDER=bitbucket -e OPENAI.KEY=$OPENAI_API_KEY -e BITBUCKET.BEARER_TOKEN=$BITBUCKET_BEARER_TOKEN codiumai/pr-agent:latest --pr_url=https://bitbucket.org/$BITBUCKET_WORKSPACE/$BITBUCKET_REPO_SLUG/pull-requests/$BITBUCKET_PR_ID review
|
||||||
- cd pr-agent
|
|
||||||
- docker build -t bitbucket_runner:latest -f Dockerfile.bitbucket_pipeline .
|
|
||||||
- docker run -e OPENAI_API_KEY=$OPENAI_API_KEY -e BITBUCKET_BEARER_TOKEN=$BITBUCKET_BEARER_TOKEN -e BITBUCKET_PR_ID=$BITBUCKET_PR_ID -e BITBUCKET_REPO_SLUG=$BITBUCKET_REPO_SLUG -e BITBUCKET_WORKSPACE=$BITBUCKET_WORKSPACE bitbucket_runner:latest
|
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Add the following secret to your repository under Repository settings > Pipelines > Repository variables.
|
2. Add the following secure variables to your repository under Repository settings > Pipelines > Repository variables.
|
||||||
OPENAI_API_KEY: <your key>
|
OPENAI_API_KEY: <your key>
|
||||||
BITBUCKET_BEARER_TOKEN: <your token>
|
BITBUCKET_BEARER_TOKEN: <your token>
|
||||||
|
|
||||||
3. To get BITBUCKET_BEARER_TOKEN follow these steps
|
You can get a Bitbucket token for your repository by following Repository Settings -> Security -> Access Tokens
|
||||||
So here is my step by step tutorial
|
|
||||||
i) Insert your workspace name instead of {workspace_name} and go to the following link in order to create an OAuth consumer.
|
|
||||||
|
|
||||||
https://bitbucket.org/{workspace_name}/workspace/settings/api
|
|
||||||
|
|
||||||
set callback URL to http://localhost:8976 (doesn't need to be a real server there)
|
|
||||||
select permissions: repository -> read
|
|
||||||
|
|
||||||
ii) use consumer's Key as a {client_id} and open the following URL in the browser
|
|
||||||
|
|
||||||
https://bitbucket.org/site/oauth2/authorize?client_id={client_id}&response_type=code
|
|
||||||
|
|
||||||
iii)
|
|
||||||
after you press "Grant access" in the browser it will redirect you to
|
|
||||||
|
|
||||||
http://localhost:8976?code=<CODE>
|
|
||||||
|
|
||||||
iv) use the code from the previous step and consumer's Key as a {client_id}, and consumer's Secret as {client_secret}
|
|
||||||
|
|
||||||
curl -X POST -u "{client_id}:{client_secret}" \
|
|
||||||
https://bitbucket.org/site/oauth2/access_token \
|
|
||||||
-d grant_type=authorization_code \
|
|
||||||
-d code={code} \
|
|
||||||
|
|
||||||
|
|
||||||
After completing this steps, you just to place this access token in the repository varibles.
|
|
||||||
|
|
||||||
|
|
||||||
=======
|
=======
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
python /app/pr_agent/servers/bitbucket_pipeline_runner.py
|
|
@ -236,9 +236,6 @@ class AzureDevopsProvider:
|
|||||||
def _parse_pr_url(pr_url: str) -> Tuple[str, int]:
|
def _parse_pr_url(pr_url: str) -> Tuple[str, int]:
|
||||||
parsed_url = urlparse(pr_url)
|
parsed_url = urlparse(pr_url)
|
||||||
|
|
||||||
if 'azure.com' not in parsed_url.netloc:
|
|
||||||
raise ValueError("The provided URL is not a valid Azure DevOps URL")
|
|
||||||
|
|
||||||
path_parts = parsed_url.path.strip('/').split('/')
|
path_parts = parsed_url.path.strip('/').split('/')
|
||||||
|
|
||||||
if len(path_parts) < 6 or path_parts[4] != 'pullrequest':
|
if len(path_parts) < 6 or path_parts[4] != 'pullrequest':
|
||||||
|
@ -77,7 +77,7 @@ class GithubProvider(GitProvider):
|
|||||||
self.previous_review = None
|
self.previous_review = None
|
||||||
self.comments = list(self.pr.get_issue_comments())
|
self.comments = list(self.pr.get_issue_comments())
|
||||||
for index in range(len(self.comments) - 1, -1, -1):
|
for index in range(len(self.comments) - 1, -1, -1):
|
||||||
if self.comments[index].body.startswith("## PR Analysis"):
|
if self.comments[index].body.startswith("## PR Analysis") or self.comments[index].body.startswith("## Incremental PR Review"):
|
||||||
self.previous_review = self.comments[index]
|
self.previous_review = self.comments[index]
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
import os
|
|
||||||
from pr_agent.agent.pr_agent import PRAgent
|
|
||||||
from pr_agent.config_loader import get_settings
|
|
||||||
from pr_agent.tools.pr_reviewer import PRReviewer
|
|
||||||
import asyncio
|
|
||||||
|
|
||||||
async def run_action():
|
|
||||||
try:
|
|
||||||
pull_request_id = os.environ.get("BITBUCKET_PR_ID", '')
|
|
||||||
slug = os.environ.get("BITBUCKET_REPO_SLUG", '')
|
|
||||||
workspace = os.environ.get("BITBUCKET_WORKSPACE", '')
|
|
||||||
bearer_token = os.environ.get('BITBUCKET_BEARER_TOKEN', None)
|
|
||||||
OPENAI_KEY = os.environ.get('OPENAI_API_KEY') or os.environ.get('OPENAI.KEY')
|
|
||||||
OPENAI_ORG = os.environ.get('OPENAI_ORG') or os.environ.get('OPENAI.ORG')
|
|
||||||
# Check if required environment variables are set
|
|
||||||
if not bearer_token:
|
|
||||||
print("BITBUCKET_BEARER_TOKEN not set")
|
|
||||||
return
|
|
||||||
|
|
||||||
if not OPENAI_KEY:
|
|
||||||
print("OPENAI_KEY not set")
|
|
||||||
return
|
|
||||||
# Set the environment variables in the settings
|
|
||||||
get_settings().set("BITBUCKET.BEARER_TOKEN", bearer_token)
|
|
||||||
get_settings().set("OPENAI.KEY", OPENAI_KEY)
|
|
||||||
if OPENAI_ORG:
|
|
||||||
get_settings().set("OPENAI.ORG", OPENAI_ORG)
|
|
||||||
if pull_request_id and slug and workspace:
|
|
||||||
pr_url = f"https://bitbucket.org/{workspace}/{slug}/pull-requests/{pull_request_id}"
|
|
||||||
await PRReviewer(pr_url).run()
|
|
||||||
except Exception as e:
|
|
||||||
print(f"An error occurred: {e}")
|
|
||||||
if __name__ == "__main__":
|
|
||||||
asyncio.run(run_action())
|
|
@ -1,3 +1,4 @@
|
|||||||
|
import time
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
@ -46,6 +47,13 @@ class PRSimilarIssue:
|
|||||||
|
|
||||||
# check if index exists, and if repo is already indexed
|
# check if index exists, and if repo is already indexed
|
||||||
run_from_scratch = False
|
run_from_scratch = False
|
||||||
|
if run_from_scratch: # for debugging
|
||||||
|
if not index_name in pinecone.list_indexes():
|
||||||
|
get_logger().info('Removing index...')
|
||||||
|
pinecone.init(api_key=api_key, environment=environment)
|
||||||
|
pinecone.delete_index(index_name)
|
||||||
|
get_logger().info('Done')
|
||||||
|
|
||||||
upsert = True
|
upsert = True
|
||||||
pinecone.init(api_key=api_key, environment=environment)
|
pinecone.init(api_key=api_key, environment=environment)
|
||||||
if not index_name in pinecone.list_indexes():
|
if not index_name in pinecone.list_indexes():
|
||||||
@ -116,7 +124,16 @@ class PRSimilarIssue:
|
|||||||
relevant_comment_number_list = []
|
relevant_comment_number_list = []
|
||||||
score_list = []
|
score_list = []
|
||||||
for r in res['matches']:
|
for r in res['matches']:
|
||||||
issue_number = int(r["id"].split('.')[0].split('_')[-1])
|
# skip example issue
|
||||||
|
if 'example_issue_' in r["id"]:
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
issue_number = int(r["id"].split('.')[0].split('_')[-1])
|
||||||
|
except:
|
||||||
|
get_logger().debug(f"Failed to parse issue number from {r['id']}")
|
||||||
|
continue
|
||||||
|
|
||||||
if original_issue_number == issue_number:
|
if original_issue_number == issue_number:
|
||||||
continue
|
continue
|
||||||
if issue_number not in relevant_issues_number_list:
|
if issue_number not in relevant_issues_number_list:
|
||||||
@ -237,6 +254,7 @@ class PRSimilarIssue:
|
|||||||
if not upsert:
|
if not upsert:
|
||||||
get_logger().info('Creating index from scratch...')
|
get_logger().info('Creating index from scratch...')
|
||||||
ds.to_pinecone_index(self.index_name, api_key=api_key, environment=environment)
|
ds.to_pinecone_index(self.index_name, api_key=api_key, environment=environment)
|
||||||
|
time.sleep(15) # wait for pinecone to finalize indexing before querying
|
||||||
else:
|
else:
|
||||||
get_logger().info('Upserting index...')
|
get_logger().info('Upserting index...')
|
||||||
namespace = ""
|
namespace = ""
|
||||||
@ -244,6 +262,7 @@ class PRSimilarIssue:
|
|||||||
concurrency: int = 10
|
concurrency: int = 10
|
||||||
pinecone.init(api_key=api_key, environment=environment)
|
pinecone.init(api_key=api_key, environment=environment)
|
||||||
ds._upsert_to_index(self.index_name, namespace, batch_size, concurrency)
|
ds._upsert_to_index(self.index_name, namespace, batch_size, concurrency)
|
||||||
|
time.sleep(5) # wait for pinecone to finalize upserting before querying
|
||||||
get_logger().info('Done')
|
get_logger().info('Done')
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user