From c9c95d60d40455732d3a0d34d92bd9bcfd8af63c Mon Sep 17 00:00:00 2001 From: Ori Kotek Date: Mon, 24 Jul 2023 15:05:24 +0300 Subject: [PATCH 1/2] Implement gitlab webhook --- README.md | 1 + pr_agent/git_providers/gitlab_provider.py | 11 ++++-- pr_agent/servers/gitlab_webhook.py | 47 +++++++++++++++++++++++ 3 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 pr_agent/servers/gitlab_webhook.py diff --git a/README.md b/README.md index eeaa4ec9..173b7844 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,7 @@ CodiumAI `PR-Agent` is an open-source tool aiming to help developers review pull | | Reflect and Review | :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: | | | | | Actions | :white_check_mark: | | | | | | | | | diff --git a/pr_agent/git_providers/gitlab_provider.py b/pr_agent/git_providers/gitlab_provider.py index f9acf1dc..e1e65b10 100644 --- a/pr_agent/git_providers/gitlab_provider.py +++ b/pr_agent/git_providers/gitlab_provider.py @@ -8,11 +8,13 @@ from gitlab import GitlabGetError from pr_agent.config_loader import settings -from .git_provider import EDIT_TYPE, FilePatchInfo, GitProvider from ..algo.language_handler import is_valid_file +from .git_provider import EDIT_TYPE, FilePatchInfo, GitProvider class GitLabProvider(GitProvider): + + def __init__(self, merge_request_url: Optional[str] = None, incremental: Optional[bool] = False): gitlab_url = settings.get("GITLAB.URL", None) 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): 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") def send_inline_comment(self, body, edit_type, found, relevant_file, relevant_line_in_file, source_line_no, @@ -262,4 +264,7 @@ class GitLabProvider(GitProvider): pass def publish_inline_comments(self, comments: list[dict]): - pass \ No newline at end of file + pass + + def get_labels(self): + pass diff --git a/pr_agent/servers/gitlab_webhook.py b/pr_agent/servers/gitlab_webhook.py new file mode 100644 index 00000000..75bef3cc --- /dev/null +++ b/pr_agent/servers/gitlab_webhook.py @@ -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() From 2c03a673127d1352dfee30f6523161f28d4ee06e Mon Sep 17 00:00:00 2001 From: Ori Kotek Date: Mon, 24 Jul 2023 16:00:51 +0300 Subject: [PATCH 2/2] Add labels --- pr_agent/git_providers/gitlab_provider.py | 12 ++++++++---- pr_agent/tools/pr_description.py | 2 ++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/pr_agent/git_providers/gitlab_provider.py b/pr_agent/git_providers/gitlab_provider.py index e1e65b10..9ee1c0bf 100644 --- a/pr_agent/git_providers/gitlab_provider.py +++ b/pr_agent/git_providers/gitlab_provider.py @@ -37,7 +37,7 @@ class GitLabProvider(GitProvider): self.incremental = incremental def is_supported(self, capability: str) -> bool: - if capability in ['get_issue_comments', 'create_inline_comment', 'publish_inline_comments', 'get_labels']: + if capability in ['get_issue_comments', 'create_inline_comment', 'publish_inline_comments']: return False return True @@ -260,11 +260,15 @@ class GitLabProvider(GitProvider): def get_user_id(self): return None - def publish_labels(self, labels): - pass + def publish_labels(self, pr_types): + 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]): pass def get_labels(self): - pass + return self.mr.labels diff --git a/pr_agent/tools/pr_description.py b/pr_agent/tools/pr_description.py index 7a9bfb88..400cdd86 100644 --- a/pr_agent/tools/pr_description.py +++ b/pr_agent/tools/pr_description.py @@ -48,6 +48,8 @@ class PRDescription: self.git_provider.publish_description(pr_title, pr_body) 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() return ""