mirror of
https://github.com/qodo-ai/pr-agent.git
synced 2025-07-06 05:40:38 +08:00
Compare commits
6 Commits
ok/gitlab_
...
ok/gitlab_
Author | SHA1 | Date | |
---|---|---|---|
2c03a67312 | |||
c9c95d60d4 | |||
dd8f6eb923 | |||
b9c25e487a | |||
1f987380ed | |||
cd8bbbf889 |
@ -1,11 +0,0 @@
|
|||||||
bot-review:
|
|
||||||
stage: test
|
|
||||||
variables:
|
|
||||||
MR_URL: ${CI_MERGE_REQUEST_PROJECT_URL}/-/merge_requests/${CI_MERGE_REQUEST_IID}
|
|
||||||
image: docker:latest
|
|
||||||
services:
|
|
||||||
- docker:19-dind
|
|
||||||
script:
|
|
||||||
- docker run --rm -e OPENAI.KEY=${OPEN_API_KEY} -e OPENAI.ORG=${OPEN_API_ORG} -e GITLAB.PERSONAL_ACCESS_TOKEN=${GITLAB_PAT} -e CONFIG.GIT_PROVIDER=gitlab codiumai/pr-agent --pr_url ${MR_URL} describe
|
|
||||||
rules:
|
|
||||||
- if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
|
|
@ -83,6 +83,7 @@ CodiumAI `PR-Agent` is an open-source tool aiming to help developers review pull
|
|||||||
| | Reflect and Review | :white_check_mark: | | |
|
| | Reflect and Review | :white_check_mark: | | |
|
||||||
| | | | | |
|
| | | | | |
|
||||||
| USAGE | CLI | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
| USAGE | CLI | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||||
|
| | App / webhook | :white_check_mark: | :white_check_mark: | |
|
||||||
| | Tagging bot | :white_check_mark: | | |
|
| | Tagging bot | :white_check_mark: | | |
|
||||||
| | Actions | :white_check_mark: | | |
|
| | Actions | :white_check_mark: | | |
|
||||||
| | | | | |
|
| | | | | |
|
||||||
|
@ -55,7 +55,7 @@ def get_pr_diff(git_provider: GitProvider, token_handler: TokenHandler, model: s
|
|||||||
|
|
||||||
# if we are over the limit, start pruning
|
# if we are over the limit, start pruning
|
||||||
patches_compressed, modified_file_names, deleted_file_names = \
|
patches_compressed, modified_file_names, deleted_file_names = \
|
||||||
pr_generate_compressed_diff(pr_languages, token_handler, add_line_numbers_to_hunks)
|
pr_generate_compressed_diff(pr_languages, token_handler, model, add_line_numbers_to_hunks)
|
||||||
|
|
||||||
final_diff = "\n".join(patches_compressed)
|
final_diff = "\n".join(patches_compressed)
|
||||||
if modified_file_names:
|
if modified_file_names:
|
||||||
|
@ -27,7 +27,7 @@ class BitbucketProvider:
|
|||||||
self.set_pr(pr_url)
|
self.set_pr(pr_url)
|
||||||
|
|
||||||
def is_supported(self, capability: str) -> bool:
|
def is_supported(self, capability: str) -> bool:
|
||||||
if capability in ['get_issue_comments', 'create_inline_comment', 'publish_inline_comments']:
|
if capability in ['get_issue_comments', 'create_inline_comment', 'publish_inline_comments', 'get_labels']:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -60,6 +60,10 @@ class GitProvider(ABC):
|
|||||||
def publish_labels(self, labels):
|
def publish_labels(self, labels):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_labels(self):
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def remove_initial_comment(self):
|
def remove_initial_comment(self):
|
||||||
pass
|
pass
|
||||||
|
@ -322,5 +322,12 @@ class GithubProvider(GitProvider):
|
|||||||
headers, data = self.pr._requester.requestJsonAndCheck(
|
headers, data = self.pr._requester.requestJsonAndCheck(
|
||||||
"PUT", f"{self.pr.issue_url}/labels", input=post_parameters
|
"PUT", f"{self.pr.issue_url}/labels", input=post_parameters
|
||||||
)
|
)
|
||||||
except:
|
except Exception as e:
|
||||||
logging.exception("Failed to publish labels")
|
logging.exception(f"Failed to publish labels, error: {e}")
|
||||||
|
|
||||||
|
def get_labels(self):
|
||||||
|
try:
|
||||||
|
return [label.name for label in self.pr.labels]
|
||||||
|
except Exception as e:
|
||||||
|
logging.exception(f"Failed to get labels, error: {e}")
|
||||||
|
return []
|
@ -8,11 +8,13 @@ from gitlab import GitlabGetError
|
|||||||
|
|
||||||
from pr_agent.config_loader import settings
|
from pr_agent.config_loader import settings
|
||||||
|
|
||||||
from .git_provider import EDIT_TYPE, FilePatchInfo, GitProvider
|
|
||||||
from ..algo.language_handler import is_valid_file
|
from ..algo.language_handler import is_valid_file
|
||||||
|
from .git_provider import EDIT_TYPE, FilePatchInfo, GitProvider
|
||||||
|
|
||||||
|
|
||||||
class GitLabProvider(GitProvider):
|
class GitLabProvider(GitProvider):
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, merge_request_url: Optional[str] = None, incremental: Optional[bool] = False):
|
def __init__(self, merge_request_url: Optional[str] = None, incremental: Optional[bool] = False):
|
||||||
gitlab_url = settings.get("GITLAB.URL", None)
|
gitlab_url = settings.get("GITLAB.URL", None)
|
||||||
if not gitlab_url:
|
if not gitlab_url:
|
||||||
@ -112,7 +114,7 @@ class GitLabProvider(GitProvider):
|
|||||||
def create_inline_comment(self, body: str, relevant_file: str, relevant_line_in_file: str):
|
def create_inline_comment(self, body: str, relevant_file: str, relevant_line_in_file: str):
|
||||||
raise NotImplementedError("Gitlab provider does not support creating inline comments yet")
|
raise NotImplementedError("Gitlab provider does not support creating inline comments yet")
|
||||||
|
|
||||||
def create_inline_comment(self, comments: list[dict]):
|
def create_inline_comments(self, comments: list[dict]):
|
||||||
raise NotImplementedError("Gitlab provider does not support publishing inline comments yet")
|
raise NotImplementedError("Gitlab provider does not support publishing inline comments yet")
|
||||||
|
|
||||||
def send_inline_comment(self, body, edit_type, found, relevant_file, relevant_line_in_file, source_line_no,
|
def send_inline_comment(self, body, edit_type, found, relevant_file, relevant_line_in_file, source_line_no,
|
||||||
@ -258,8 +260,15 @@ class GitLabProvider(GitProvider):
|
|||||||
def get_user_id(self):
|
def get_user_id(self):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def publish_labels(self, labels):
|
def publish_labels(self, pr_types):
|
||||||
pass
|
try:
|
||||||
|
self.mr.labels = list(set(pr_types))
|
||||||
|
self.mr.save()
|
||||||
|
except Exception as e:
|
||||||
|
logging.exception(f"Failed to publish labels, error: {e}")
|
||||||
|
|
||||||
def publish_inline_comments(self, comments: list[dict]):
|
def publish_inline_comments(self, comments: list[dict]):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def get_labels(self):
|
||||||
|
return self.mr.labels
|
||||||
|
47
pr_agent/servers/gitlab_webhook.py
Normal file
47
pr_agent/servers/gitlab_webhook.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import logging
|
||||||
|
|
||||||
|
import uvicorn
|
||||||
|
from fastapi import APIRouter, FastAPI, Request, status
|
||||||
|
from fastapi.encoders import jsonable_encoder
|
||||||
|
from fastapi.responses import JSONResponse
|
||||||
|
from starlette.background import BackgroundTasks
|
||||||
|
|
||||||
|
from pr_agent.agent.pr_agent import PRAgent
|
||||||
|
from pr_agent.config_loader import settings
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/webhook")
|
||||||
|
async def gitlab_webhook(background_tasks: BackgroundTasks, request: Request):
|
||||||
|
data = await request.json()
|
||||||
|
if data.get('object_kind') == 'merge_request' and data['object_attributes'].get('action') in ['open', 'reopen']:
|
||||||
|
logging.info(f"A merge request has been opened: {data['object_attributes'].get('title')}")
|
||||||
|
url = data['object_attributes'].get('url')
|
||||||
|
background_tasks.add_task(PRAgent().handle_request, url, "/review")
|
||||||
|
elif data.get('object_kind') == 'note' and data['event_type'] == 'note':
|
||||||
|
if 'merge_request' in data:
|
||||||
|
mr = data['merge_request']
|
||||||
|
url = mr.get('url')
|
||||||
|
body = data.get('object_attributes', {}).get('note')
|
||||||
|
background_tasks.add_task(PRAgent().handle_request, url, body)
|
||||||
|
return JSONResponse(status_code=status.HTTP_200_OK, content=jsonable_encoder({"message": "success"}))
|
||||||
|
|
||||||
|
def start():
|
||||||
|
gitlab_url = settings.get("GITLAB.URL", None)
|
||||||
|
if not gitlab_url:
|
||||||
|
raise ValueError("GITLAB.URL is not set")
|
||||||
|
gitlab_token = settings.get("GITLAB.PERSONAL_ACCESS_TOKEN", None)
|
||||||
|
if not gitlab_token:
|
||||||
|
raise ValueError("GITLAB.PERSONAL_ACCESS_TOKEN is not set")
|
||||||
|
settings.config.git_provider = "gitlab"
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
app.include_router(router)
|
||||||
|
|
||||||
|
uvicorn.run(app, host="0.0.0.0", port=3000)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
start()
|
@ -46,7 +46,11 @@ class PRDescription:
|
|||||||
self.git_provider.publish_comment(markdown_text)
|
self.git_provider.publish_comment(markdown_text)
|
||||||
else:
|
else:
|
||||||
self.git_provider.publish_description(pr_title, pr_body)
|
self.git_provider.publish_description(pr_title, pr_body)
|
||||||
self.git_provider.publish_labels(pr_types)
|
if self.git_provider.is_supported("get_labels"):
|
||||||
|
current_labels = self.git_provider.get_labels()
|
||||||
|
if current_labels is None:
|
||||||
|
current_labels = []
|
||||||
|
self.git_provider.publish_labels(pr_types + current_labels)
|
||||||
self.git_provider.remove_initial_comment()
|
self.git_provider.remove_initial_comment()
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user