From 73624148a53d52c14a9e782826cc8fcdae4799f7 Mon Sep 17 00:00:00 2001 From: Dan Anstis Date: Fri, 8 Mar 2024 04:39:57 +0000 Subject: [PATCH 01/26] Fix URL encoding in Azure DevOps webhook handler --- pr_agent/servers/azuredevops_server_webhook.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pr_agent/servers/azuredevops_server_webhook.py b/pr_agent/servers/azuredevops_server_webhook.py index a7ba8659..2b926886 100644 --- a/pr_agent/servers/azuredevops_server_webhook.py +++ b/pr_agent/servers/azuredevops_server_webhook.py @@ -6,6 +6,8 @@ import json import os import re import secrets +from urllib.parse import unquote + import uvicorn from fastapi import APIRouter, Depends, FastAPI, HTTPException from fastapi.security import HTTPBasic, HTTPBasicCredentials @@ -81,7 +83,7 @@ async def handle_webhook(background_tasks: BackgroundTasks, request: Request): actions = [] if data["eventType"] == "git.pullrequest.created": # API V1 (latest) - pr_url = data["resource"]["_links"]["web"]["href"].replace("_apis/git/repositories", "_git") + pr_url = unquote(data["resource"]["_links"]["web"]["href"].replace("_apis/git/repositories", "_git")) log_context["event"] = data["eventType"] log_context["api_url"] = pr_url await _perform_commands_azure("pr_commands", PRAgent(), pr_url, log_context) @@ -90,7 +92,7 @@ async def handle_webhook(background_tasks: BackgroundTasks, request: Request): if available_commands_rgx.match(data["resource"]["comment"]["content"]): if(data["resourceVersion"] == "2.0"): repo = data["resource"]["pullRequest"]["repository"]["webUrl"] - pr_url = f'{repo}/pullrequest/{data["resource"]["pullRequest"]["pullRequestId"]}' + pr_url = unquote(f'{repo}/pullrequest/{data["resource"]["pullRequest"]["pullRequestId"]}') actions = [data["resource"]["comment"]["content"]] else: # API V1 not supported as it does not contain the PR URL From ff2346eacc2f0962cf08cef3c48c9785d3e8f34b Mon Sep 17 00:00:00 2001 From: "Hussam.lawen" Date: Sun, 10 Mar 2024 14:18:29 +0200 Subject: [PATCH 02/26] update markdown --- pr_agent/algo/utils.py | 8 ++++++-- pr_agent/tools/pr_reviewer.py | 8 +++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/pr_agent/algo/utils.py b/pr_agent/algo/utils.py index 6932d7bd..dede9850 100644 --- a/pr_agent/algo/utils.py +++ b/pr_agent/algo/utils.py @@ -60,7 +60,7 @@ def unique_strings(input_list: List[str]) -> List[str]: return unique_list -def convert_to_markdown(output_data: dict, gfm_supported: bool = True) -> str: +def convert_to_markdown(output_data: dict, gfm_supported: bool = True, incremental_review=None) -> str: """ Convert a dictionary of data into markdown format. Args: @@ -80,7 +80,11 @@ def convert_to_markdown(output_data: dict, gfm_supported: bool = True) -> str: "Estimated effort to review [1-5]": "⏱️", } markdown_text = "" - markdown_text += f"## PR Review\n\n" + if not incremental_review: + markdown_text += f"## PR Review\n\n" + else: + markdown_text += f"## Incremental PR Review\n\n" + markdown_text += f"⏮️ Review for commits since previous PR-Agent review {incremental_review}.\n\n" if gfm_supported: markdown_text += "\n\n" # markdown_text += """""" diff --git a/pr_agent/tools/pr_reviewer.py b/pr_agent/tools/pr_reviewer.py index 5fc82fda..d0f21ec5 100644 --- a/pr_agent/tools/pr_reviewer.py +++ b/pr_agent/tools/pr_reviewer.py @@ -207,6 +207,7 @@ class PRReviewer: pass + incremental_review_markdown_text = None # Add incremental review section if self.incremental.is_incremental: last_commit_url = f"{self.git_provider.get_pr_url()}/commits/" \ @@ -216,12 +217,9 @@ class PRReviewer: if last_commit_msg: replacement = last_commit_msg.splitlines(keepends=False)[0].replace('_', r'\_') incremental_review_markdown_text += f" \n_({replacement})_" - data = OrderedDict(data) - data.update({'Incremental PR Review': { - "⏮️ Review for commits since previous PR-Agent review": incremental_review_markdown_text}}) - data.move_to_end('Incremental PR Review', last=False) - markdown_text = convert_to_markdown(data, self.git_provider.is_supported("gfm_markdown")) + markdown_text = convert_to_markdown(data, self.git_provider.is_supported("gfm_markdown"), + incremental_review_markdown_text) # Add help text if gfm_markdown is supported if self.git_provider.is_supported("gfm_markdown") and get_settings().pr_reviewer.enable_help_text: From 003c49052eb3ed1db978b7f3bd517af1cf9b38d9 Mon Sep 17 00:00:00 2001 From: "Hussam.lawen" Date: Sun, 10 Mar 2024 17:15:25 +0200 Subject: [PATCH 03/26] skip incremental review if no file changed since last review --- pr_agent/git_providers/github_provider.py | 3 ++- pr_agent/tools/pr_reviewer.py | 13 +++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/pr_agent/git_providers/github_provider.py b/pr_agent/git_providers/github_provider.py index fab4fd5b..92983baf 100644 --- a/pr_agent/git_providers/github_provider.py +++ b/pr_agent/git_providers/github_provider.py @@ -38,6 +38,7 @@ class GithubProvider(GitProvider): self.set_pr(pr_url) self.pr_commits = list(self.pr.get_commits()) if self.incremental.is_incremental: + self.file_set = dict() self.get_incremental_commits() self.last_commit_id = self.pr_commits[-1] self.pr_url = self.get_pr_url() # pr_url for github actions can be as api.github.com, so we need to get the url from the pr object @@ -62,7 +63,7 @@ class GithubProvider(GitProvider): if self.previous_review: self.incremental.commits_range = self.get_commit_range() # Get all files changed during the commit range - self.file_set = dict() + for commit in self.incremental.commits_range: if commit.commit.message.startswith(f"Merge branch '{self._get_repo().default_branch}'"): get_logger().info(f"Skipping merge commit {commit.commit.message}") diff --git a/pr_agent/tools/pr_reviewer.py b/pr_agent/tools/pr_reviewer.py index d0f21ec5..5ea1d20f 100644 --- a/pr_agent/tools/pr_reviewer.py +++ b/pr_agent/tools/pr_reviewer.py @@ -107,6 +107,15 @@ class PRReviewer: relevant_configs = {'pr_reviewer': dict(get_settings().pr_reviewer), 'config': dict(get_settings().config)} get_logger().debug("Relevant configs", artifacts=relevant_configs) + + if self.incremental.is_incremental and hasattr(self.git_provider, "file_set") and not self.git_provider.file_set: + get_logger().info(f"Incremental review is enabled for {self.pr_url} but there are no new files") + if hasattr(self.git_provider, "previous_review"): + previous_review_url = self.git_provider.previous_review.html_url + if get_settings().config.publish_output: + self.git_provider.publish_comment(f"Incremental Review Skipped\nNo files were changed since the [previous PR Review]({previous_review_url})", is_temporary=True) + return None + if get_settings().config.publish_output: self.git_provider.publish_comment("Preparing review...", is_temporary=True) @@ -212,11 +221,7 @@ class PRReviewer: if self.incremental.is_incremental: last_commit_url = f"{self.git_provider.get_pr_url()}/commits/" \ f"{self.git_provider.incremental.first_new_commit_sha}" - last_commit_msg = self.incremental.commits_range[0].commit.message if self.incremental.commits_range else "" incremental_review_markdown_text = f"Starting from commit {last_commit_url}" - if last_commit_msg: - replacement = last_commit_msg.splitlines(keepends=False)[0].replace('_', r'\_') - incremental_review_markdown_text += f" \n_({replacement})_" markdown_text = convert_to_markdown(data, self.git_provider.is_supported("gfm_markdown"), incremental_review_markdown_text) From 54535070974e1aca4c41cfa1185fcd0366c72917 Mon Sep 17 00:00:00 2001 From: "Hussam.lawen" Date: Sun, 10 Mar 2024 17:19:27 +0200 Subject: [PATCH 04/26] small fix --- pr_agent/tools/pr_reviewer.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pr_agent/tools/pr_reviewer.py b/pr_agent/tools/pr_reviewer.py index 5ea1d20f..4a9d5ca1 100644 --- a/pr_agent/tools/pr_reviewer.py +++ b/pr_agent/tools/pr_reviewer.py @@ -110,10 +110,12 @@ class PRReviewer: if self.incremental.is_incremental and hasattr(self.git_provider, "file_set") and not self.git_provider.file_set: get_logger().info(f"Incremental review is enabled for {self.pr_url} but there are no new files") + previous_review_url = "" if hasattr(self.git_provider, "previous_review"): previous_review_url = self.git_provider.previous_review.html_url if get_settings().config.publish_output: - self.git_provider.publish_comment(f"Incremental Review Skipped\nNo files were changed since the [previous PR Review]({previous_review_url})", is_temporary=True) + self.git_provider.publish_comment(f"Incremental Review Skipped\n" + f"No files were changed since the [previous PR Review]({previous_review_url})", is_temporary=True) return None if get_settings().config.publish_output: From 6c5697b07c18ceb6ab3e44709524ce128518dad3 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Mon, 11 Mar 2024 08:50:19 +0200 Subject: [PATCH 05/26] Enhance logging and refactor code in gitlab_webhook.py, update logger level in bitbucket_app.py and github_polling.py, remove redundant section in github.md --- docs/docs/installation/github.md | 12 ------- pr_agent/servers/bitbucket_app.py | 2 +- pr_agent/servers/github_polling.py | 2 +- pr_agent/servers/gitlab_webhook.py | 55 +++++++++++++++++++----------- 4 files changed, 37 insertions(+), 34 deletions(-) diff --git a/docs/docs/installation/github.md b/docs/docs/installation/github.md index f4d08447..9cd2f7e6 100644 --- a/docs/docs/installation/github.md +++ b/docs/docs/installation/github.md @@ -67,18 +67,6 @@ When you open your next PR, you should see a comment from `github-actions` bot w PR_CODE_SUGGESTIONS.NUM_CODE_SUGGESTIONS: 6 # Increase number of code suggestions ``` ---- -## Run as a polling server -Request reviews by tagging your GitHub user on a PR - -Follow [steps 1-3](#run-as-a-github-action) of the GitHub Action setup. - -Run the following command to start the server: - -``` -python pr_agent/servers/github_polling.py -``` - --- ## Run as a GitHub App diff --git a/pr_agent/servers/bitbucket_app.py b/pr_agent/servers/bitbucket_app.py index ccc53525..a0104cf0 100644 --- a/pr_agent/servers/bitbucket_app.py +++ b/pr_agent/servers/bitbucket_app.py @@ -28,7 +28,7 @@ from pr_agent.tools.pr_code_suggestions import PRCodeSuggestions from pr_agent.tools.pr_description import PRDescription from pr_agent.tools.pr_reviewer import PRReviewer -setup_logger(fmt=LoggingFormat.JSON) +setup_logger(fmt=LoggingFormat.JSON, level="DEBUG") router = APIRouter() secret_provider = get_secret_provider() if get_settings().get("CONFIG.SECRET_PROVIDER") else None diff --git a/pr_agent/servers/github_polling.py b/pr_agent/servers/github_polling.py index 46c21e06..a0e875bc 100644 --- a/pr_agent/servers/github_polling.py +++ b/pr_agent/servers/github_polling.py @@ -8,7 +8,7 @@ from pr_agent.config_loader import get_settings from pr_agent.git_providers import get_git_provider from pr_agent.log import LoggingFormat, get_logger, setup_logger -setup_logger(fmt=LoggingFormat.JSON) +setup_logger(fmt=LoggingFormat.JSON, level="DEBUG") NOTIFICATION_URL = "https://api.github.com/notifications" diff --git a/pr_agent/servers/gitlab_webhook.py b/pr_agent/servers/gitlab_webhook.py index 2779f80d..a0dc220b 100644 --- a/pr_agent/servers/gitlab_webhook.py +++ b/pr_agent/servers/gitlab_webhook.py @@ -17,7 +17,7 @@ from pr_agent.git_providers.utils import apply_repo_settings from pr_agent.log import LoggingFormat, get_logger, setup_logger from pr_agent.secret_providers import get_secret_provider -setup_logger(fmt=LoggingFormat.JSON) +setup_logger(fmt=LoggingFormat.JSON, level="DEBUG") router = APIRouter() secret_provider = get_secret_provider() if get_settings().get("CONFIG.SECRET_PROVIDER") else None @@ -51,6 +51,9 @@ async def _perform_commands_gitlab(commands_conf: str, agent: PRAgent, api_url: @router.post("/webhook") async def gitlab_webhook(background_tasks: BackgroundTasks, request: Request): log_context = {"server_type": "gitlab_app"} + get_logger().debug("Received a GitLab webhook") + + # Check if the request is authorized if request.headers.get("X-Gitlab-Token") and secret_provider: request_token = request.headers.get("X-Gitlab-Token") secret = secret_provider.get_secret(request_token) @@ -66,46 +69,58 @@ async def gitlab_webhook(background_tasks: BackgroundTasks, request: Request): elif get_settings().get("GITLAB.SHARED_SECRET"): secret = get_settings().get("GITLAB.SHARED_SECRET") if not request.headers.get("X-Gitlab-Token") == secret: + get_logger().error(f"Failed to validate secret") return JSONResponse(status_code=status.HTTP_401_UNAUTHORIZED, content=jsonable_encoder({"message": "unauthorized"})) else: + get_logger().error(f"Failed to validate secret") return JSONResponse(status_code=status.HTTP_401_UNAUTHORIZED, content=jsonable_encoder({"message": "unauthorized"})) gitlab_token = get_settings().get("GITLAB.PERSONAL_ACCESS_TOKEN", None) if not gitlab_token: + get_logger().error(f"No gitlab token found") return JSONResponse(status_code=status.HTTP_401_UNAUTHORIZED, content=jsonable_encoder({"message": "unauthorized"})) + data = await request.json() - get_logger().info(json.dumps(data)) + get_logger().info("GitLab data", json.dumps(data)) + if data.get('object_kind') == 'merge_request' and data['object_attributes'].get('action') in ['open', 'reopen']: get_logger().info(f"A merge request has been opened: {data['object_attributes'].get('title')}") url = data['object_attributes'].get('url') + get_logger().info(f"New merge request: {url}") await _perform_commands_gitlab("pr_commands", PRAgent(), url, log_context) - # handle_request(background_tasks, url, "/review", log_context) - elif data.get('object_kind') == 'note' and data['event_type'] == 'note': + elif data.get('object_kind') == 'note' and data['event_type'] == 'note': # comment on MR if 'merge_request' in data: mr = data['merge_request'] url = mr.get('url') + get_logger().info(f"A comment has been added to a merge request: {url}") body = data.get('object_attributes', {}).get('note') - if data.get('object_attributes', {}).get('type') == 'DiffNote' and '/ask' in body: - line_range_ = data['object_attributes']['position']['line_range'] - - # if line_range_['start']['type'] == 'new': - start_line = line_range_['start']['new_line'] - end_line = line_range_['end']['new_line'] - # else: - # start_line = line_range_['start']['old_line'] - # end_line = line_range_['end']['old_line'] - - question = body.replace('/ask', '').strip() - path = data['object_attributes']['position']['new_path'] - side = 'RIGHT'# if line_range_['start']['type'] == 'new' else 'LEFT' - comment_id = data['object_attributes']["discussion_id"] - get_logger().info(f"Handling line comment") - body = f"/ask_line --line_start={start_line} --line_end={end_line} --side={side} --file_name={path} --comment_id={comment_id} {question}" + if data.get('object_attributes', {}).get('type') == 'DiffNote' and '/ask' in body: # /ask_line + body = handle_ask_line(body, data) handle_request(background_tasks, url, body, log_context) return JSONResponse(status_code=status.HTTP_200_OK, content=jsonable_encoder({"message": "success"})) +def handle_ask_line(body, data): + try: + line_range_ = data['object_attributes']['position']['line_range'] + # if line_range_['start']['type'] == 'new': + start_line = line_range_['start']['new_line'] + end_line = line_range_['end']['new_line'] + # else: + # start_line = line_range_['start']['old_line'] + # end_line = line_range_['end']['old_line'] + question = body.replace('/ask', '').strip() + path = data['object_attributes']['position']['new_path'] + side = 'RIGHT' # if line_range_['start']['type'] == 'new' else 'LEFT' + comment_id = data['object_attributes']["discussion_id"] + get_logger().info(f"Handling line comment") + body = f"/ask_line --line_start={start_line} --line_end={end_line} --side={side} --file_name={path} --comment_id={comment_id} {question}" + except Exception as e: + get_logger().error(f"Failed to handle ask line comment: {e}") + return body + + @router.get("/") async def root(): return {"status": "ok"} From a27ad0feb668e37a103d26e9a662aa65469889f8 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Mon, 11 Mar 2024 08:55:07 +0200 Subject: [PATCH 06/26] log --- pr_agent/servers/gitlab_webhook.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pr_agent/servers/gitlab_webhook.py b/pr_agent/servers/gitlab_webhook.py index a0dc220b..809bd8ff 100644 --- a/pr_agent/servers/gitlab_webhook.py +++ b/pr_agent/servers/gitlab_webhook.py @@ -83,7 +83,6 @@ async def gitlab_webhook(background_tasks: BackgroundTasks, request: Request): get_logger().info("GitLab data", json.dumps(data)) if data.get('object_kind') == 'merge_request' and data['object_attributes'].get('action') in ['open', 'reopen']: - get_logger().info(f"A merge request has been opened: {data['object_attributes'].get('title')}") url = data['object_attributes'].get('url') get_logger().info(f"New merge request: {url}") await _perform_commands_gitlab("pr_commands", PRAgent(), url, log_context) From 33a911da4ce6871ce361ddb3dd18dd291d521a6f Mon Sep 17 00:00:00 2001 From: mrT23 Date: Mon, 11 Mar 2024 08:56:48 +0200 Subject: [PATCH 07/26] log --- pr_agent/servers/gitlab_webhook.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr_agent/servers/gitlab_webhook.py b/pr_agent/servers/gitlab_webhook.py index 809bd8ff..715185a8 100644 --- a/pr_agent/servers/gitlab_webhook.py +++ b/pr_agent/servers/gitlab_webhook.py @@ -80,7 +80,7 @@ async def gitlab_webhook(background_tasks: BackgroundTasks, request: Request): return JSONResponse(status_code=status.HTTP_401_UNAUTHORIZED, content=jsonable_encoder({"message": "unauthorized"})) data = await request.json() - get_logger().info("GitLab data", json.dumps(data)) + get_logger().info("GitLab data", artifact=data) if data.get('object_kind') == 'merge_request' and data['object_attributes'].get('action') in ['open', 'reopen']: url = data['object_attributes'].get('url') From 4739fd3d37c6816400d096a8c78dc66e54df6247 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Mon, 11 Mar 2024 09:13:35 +0200 Subject: [PATCH 08/26] readme --- README.md | 2 +- docs/docs/index.md | 2 +- docs/docs/installation/github.md | 2 +- docs/docs/installation/gitlab.md | 6 +++++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a09b341f..da5159c4 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ CodiumAI PR-Agent is an open-source tool to help efficiently review and handle p - See the [Usage Guide](https://pr-agent-docs.codium.ai/usage-guide/) for instructions on running the PR-Agent commands via different interfaces, including _CLI_, _online usage_, or by _automatically triggering_ them when a new PR is opened. -- See the [Tools Guide](https://pr-agent-docs.codium.ai/tools/) for a detailed description of the different tools (tools are run via the commands). +- See the [Tools Guide](https://pr-agent-docs.codium.ai/tools/) for a detailed description of the different tools. Supported commands per platform: diff --git a/docs/docs/index.md b/docs/docs/index.md index f604fd25..caa52ded 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -6,7 +6,7 @@ CodiumAI PR-Agent is an open-source tool to help efficiently review and handle p - See the [Usage Guide](./usage-guide/index.md) for instructions on running the PR-Agent commands via different interfaces, including _CLI_, _online usage_, or by _automatically triggering_ them when a new PR is opened. -- See the [Tools Guide](./tools/index.md) for a detailed description of the different tools (tools are run via the commands). +- See the [Tools Guide](./tools/index.md) for a detailed description of the different tools. ## PR-Agent Features diff --git a/docs/docs/installation/github.md b/docs/docs/installation/github.md index 9cd2f7e6..dcc624d9 100644 --- a/docs/docs/installation/github.md +++ b/docs/docs/installation/github.md @@ -157,7 +157,7 @@ docker push codiumai/pr-agent:github_app # Push to your Docker repository ## Deploy as a Lambda Function -1. Follow steps 1-5 of [Method 5](#run-as-a-github-app). +1. Follow steps 1-5 from [here](#run-as-a-github-app). 2. Build a docker image that can be used as a lambda function ```shell docker buildx build --platform=linux/amd64 . -t codiumai/pr-agent:serverless -f docker/Dockerfile.lambda diff --git a/docs/docs/installation/gitlab.md b/docs/docs/installation/gitlab.md index e768e850..cb3b7931 100644 --- a/docs/docs/installation/gitlab.md +++ b/docs/docs/installation/gitlab.md @@ -1,16 +1,20 @@ ## Run a GitLab webhook server 1. From the GitLab workspace or group, create an access token. Enable the "api" scope only. + 2. Generate a random secret for your app, and save it for later. For example, you can use: ``` WEBHOOK_SECRET=$(python -c "import secrets; print(secrets.token_hex(10))") ``` -3. Follow the instructions to build the Docker image, setup a secrets file and deploy on your own server from [Method 5](#run-as-a-github-app) steps 4-7. +3. Follow the instructions to build the Docker image, setup a secrets file and deploy on your own server from [here](https://pr-agent-docs.codium.ai/installation/github/#run-as-a-github-app) steps 4-7. + 4. In the secrets file, fill in the following: - Your OpenAI key. - In the [gitlab] section, fill in personal_access_token and shared_secret. The access token can be a personal access token, or a group or project access token. - Set deployment_type to 'gitlab' in [configuration.toml](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml) + 5. Create a webhook in GitLab. Set the URL to the URL of your app's server. Set the secret token to the generated secret from step 2. In the "Trigger" section, check the ‘comments’ and ‘merge request events’ boxes. + 6. Test your installation by opening a merge request or commenting or a merge request using one of CodiumAI's commands. \ No newline at end of file From 86dc87831bab5e5c6f55857cbbdd85c9a775dbb0 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Mon, 11 Mar 2024 09:37:51 +0200 Subject: [PATCH 09/26] remove is_temporary --- pr_agent/tools/pr_reviewer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr_agent/tools/pr_reviewer.py b/pr_agent/tools/pr_reviewer.py index 4a9d5ca1..ff0c6582 100644 --- a/pr_agent/tools/pr_reviewer.py +++ b/pr_agent/tools/pr_reviewer.py @@ -115,7 +115,7 @@ class PRReviewer: previous_review_url = self.git_provider.previous_review.html_url if get_settings().config.publish_output: self.git_provider.publish_comment(f"Incremental Review Skipped\n" - f"No files were changed since the [previous PR Review]({previous_review_url})", is_temporary=True) + f"No files were changed since the [previous PR Review]({previous_review_url})") return None if get_settings().config.publish_output: From 84dadb0469a9adf3c72ea78424511b82dacd0f5e Mon Sep 17 00:00:00 2001 From: "Hussam.lawen" Date: Mon, 11 Mar 2024 09:42:10 +0200 Subject: [PATCH 10/26] rename + check github --- pr_agent/git_providers/github_provider.py | 12 ++++++------ pr_agent/tools/pr_reviewer.py | 8 ++++++-- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/pr_agent/git_providers/github_provider.py b/pr_agent/git_providers/github_provider.py index 92983baf..facf156a 100644 --- a/pr_agent/git_providers/github_provider.py +++ b/pr_agent/git_providers/github_provider.py @@ -38,7 +38,7 @@ class GithubProvider(GitProvider): self.set_pr(pr_url) self.pr_commits = list(self.pr.get_commits()) if self.incremental.is_incremental: - self.file_set = dict() + self.unreviewed_files_set = dict() self.get_incremental_commits() self.last_commit_id = self.pr_commits[-1] self.pr_url = self.get_pr_url() # pr_url for github actions can be as api.github.com, so we need to get the url from the pr object @@ -68,7 +68,7 @@ class GithubProvider(GitProvider): if commit.commit.message.startswith(f"Merge branch '{self._get_repo().default_branch}'"): get_logger().info(f"Skipping merge commit {commit.commit.message}") continue - self.file_set.update({file.filename: file for file in commit.files}) + self.unreviewed_files_set.update({file.filename: file for file in commit.files}) else: raise ValueError("No previous review found") @@ -99,8 +99,8 @@ class GithubProvider(GitProvider): return self.comments[index] def get_files(self): - if self.incremental.is_incremental and self.file_set: - return self.file_set.values() + if self.incremental.is_incremental and self.unreviewed_files_set: + return self.unreviewed_files_set.values() try: git_files = context.get("git_files", None) if git_files: @@ -146,10 +146,10 @@ class GithubProvider(GitProvider): new_file_content_str = self._get_pr_file_content(file, self.pr.head.sha) # communication with GitHub patch = file.patch - if self.incremental.is_incremental and self.file_set: + if self.incremental.is_incremental and self.unreviewed_files_set: original_file_content_str = self._get_pr_file_content(file, self.incremental.last_seen_commit_sha) patch = load_large_diff(file.filename, new_file_content_str, original_file_content_str) - self.file_set[file.filename] = patch + self.unreviewed_files_set[file.filename] = patch else: original_file_content_str = self._get_pr_file_content(file, self.pr.base.sha) if not patch: diff --git a/pr_agent/tools/pr_reviewer.py b/pr_agent/tools/pr_reviewer.py index 4a9d5ca1..b7f1f54e 100644 --- a/pr_agent/tools/pr_reviewer.py +++ b/pr_agent/tools/pr_reviewer.py @@ -108,14 +108,14 @@ class PRReviewer: 'config': dict(get_settings().config)} get_logger().debug("Relevant configs", artifacts=relevant_configs) - if self.incremental.is_incremental and hasattr(self.git_provider, "file_set") and not self.git_provider.file_set: + if self.incremental.is_incremental and hasattr(self.git_provider, "file_set") and not self.git_provider.unreviewed_files_set: get_logger().info(f"Incremental review is enabled for {self.pr_url} but there are no new files") previous_review_url = "" if hasattr(self.git_provider, "previous_review"): previous_review_url = self.git_provider.previous_review.html_url if get_settings().config.publish_output: self.git_provider.publish_comment(f"Incremental Review Skipped\n" - f"No files were changed since the [previous PR Review]({previous_review_url})", is_temporary=True) + f"No files were changed since the [previous PR Review]({previous_review_url})") return None if get_settings().config.publish_output: @@ -324,6 +324,10 @@ class PRReviewer: if self.is_auto and not self.incremental.first_new_commit_sha: get_logger().info(f"Incremental review is enabled for {self.pr_url} but there are no new commits") return False + + if not hasattr(self.git_provider, "get_incremental_commits"): + get_logger().info(f"Incremental review is not supported for {get_settings().config.git_provider}") + return False # checking if there are enough commits to start the review num_new_commits = len(self.incremental.commits_range) num_commits_threshold = get_settings().pr_reviewer.minimal_commits_for_incremental_review From 5c20fffee995aa0dbdd4ba1875e88b3966439e54 Mon Sep 17 00:00:00 2001 From: "Hussam.lawen" Date: Mon, 11 Mar 2024 09:59:16 +0200 Subject: [PATCH 11/26] fix when no previous review where found, reivew -i should run as regular review --- pr_agent/git_providers/github_provider.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pr_agent/git_providers/github_provider.py b/pr_agent/git_providers/github_provider.py index facf156a..2f928f82 100644 --- a/pr_agent/git_providers/github_provider.py +++ b/pr_agent/git_providers/github_provider.py @@ -70,7 +70,8 @@ class GithubProvider(GitProvider): continue self.unreviewed_files_set.update({file.filename: file for file in commit.files}) else: - raise ValueError("No previous review found") + get_logger().info("No previous review found, will review the entire PR") + self.incremental.is_incremental = False def get_commit_range(self): last_review_time = self.previous_review.created_at From ad240f764073c56300f59b5eab5c9e7824211776 Mon Sep 17 00:00:00 2001 From: "Hussam.lawen" Date: Mon, 11 Mar 2024 10:13:41 +0200 Subject: [PATCH 12/26] small fix --- pr_agent/tools/pr_reviewer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr_agent/tools/pr_reviewer.py b/pr_agent/tools/pr_reviewer.py index b7f1f54e..59500005 100644 --- a/pr_agent/tools/pr_reviewer.py +++ b/pr_agent/tools/pr_reviewer.py @@ -115,7 +115,7 @@ class PRReviewer: previous_review_url = self.git_provider.previous_review.html_url if get_settings().config.publish_output: self.git_provider.publish_comment(f"Incremental Review Skipped\n" - f"No files were changed since the [previous PR Review]({previous_review_url})") + f"No files were changed since the [previous PR Review]({previous_review_url})") return None if get_settings().config.publish_output: From 476d64bc1863fcdb5e2399365a3477a45643c709 Mon Sep 17 00:00:00 2001 From: "Hussam.lawen" Date: Mon, 11 Mar 2024 11:30:05 +0200 Subject: [PATCH 13/26] fix --- pr_agent/tools/pr_reviewer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr_agent/tools/pr_reviewer.py b/pr_agent/tools/pr_reviewer.py index 59500005..854e351c 100644 --- a/pr_agent/tools/pr_reviewer.py +++ b/pr_agent/tools/pr_reviewer.py @@ -108,7 +108,7 @@ class PRReviewer: 'config': dict(get_settings().config)} get_logger().debug("Relevant configs", artifacts=relevant_configs) - if self.incremental.is_incremental and hasattr(self.git_provider, "file_set") and not self.git_provider.unreviewed_files_set: + if self.incremental.is_incremental and hasattr(self.git_provider, "unreviewed_files_set") and not self.git_provider.unreviewed_files_set: get_logger().info(f"Incremental review is enabled for {self.pr_url} but there are no new files") previous_review_url = "" if hasattr(self.git_provider, "previous_review"): From d83643083fdb5658e31429712c13597f41f9b4aa Mon Sep 17 00:00:00 2001 From: mrT23 Date: Mon, 11 Mar 2024 11:58:35 +0200 Subject: [PATCH 14/26] fixed numbers --- docs/docs/installation/github.md | 76 ++++++++++++++++---------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/docs/docs/installation/github.md b/docs/docs/installation/github.md index dcc624d9..b405b020 100644 --- a/docs/docs/installation/github.md +++ b/docs/docs/installation/github.md @@ -2,7 +2,7 @@ You can use our pre-built Github Action Docker image to run PR-Agent as a Github Action. -1. Add the following file to your repository under `.github/workflows/pr_agent.yml`: +1) Add the following file to your repository under `.github/workflows/pr_agent.yml`: ```yaml on: @@ -46,7 +46,7 @@ jobs: OPENAI_KEY: ${{ secrets.OPENAI_KEY }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} ``` -2. Add the following secret to your repository under `Settings > Secrets and variables > Actions > New repository secret > Add secret`: +2) Add the following secret to your repository under `Settings > Secrets and variables > Actions > New repository secret > Add secret`: ``` Name = OPENAI_KEY @@ -55,10 +55,10 @@ Secret = The GITHUB_TOKEN secret is automatically created by GitHub. -3. Merge this change to your main branch. +3) Merge this change to your main branch. When you open your next PR, you should see a comment from `github-actions` bot with a review of your PR, and instructions on how to use the rest of the tools. -4. You may configure PR-Agent by adding environment variables under the env section corresponding to any configurable property in the [configuration](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml) file. Some examples: +4) You may configure PR-Agent by adding environment variables under the env section corresponding to any configurable property in the [configuration](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml) file. Some examples: ```yaml env: # ... previous environment values @@ -72,7 +72,7 @@ When you open your next PR, you should see a comment from `github-actions` bot w ## Run as a GitHub App Allowing you to automate the review process on your private or public repositories. -1. Create a GitHub App from the [Github Developer Portal](https://docs.github.com/en/developers/apps/creating-a-github-app). +1) Create a GitHub App from the [Github Developer Portal](https://docs.github.com/en/developers/apps/creating-a-github-app). - Set the following permissions: - Pull requests: Read & write @@ -84,60 +84,62 @@ Allowing you to automate the review process on your private or public repositori - Pull request - Push (if you need to enable triggering on PR update) -2. Generate a random secret for your app, and save it for later. For example, you can use: +2) Generate a random secret for your app, and save it for later. For example, you can use: ``` WEBHOOK_SECRET=$(python -c "import secrets; print(secrets.token_hex(10))") ``` -3. Acquire the following pieces of information from your app's settings page: +3) Acquire the following pieces of information from your app's settings page: - App private key (click "Generate a private key" and save the file) - App ID -4. Clone this repository: +4) Clone this repository: ``` git clone https://github.com/Codium-ai/pr-agent.git ``` -5. Copy the secrets template file and fill in the following: - ``` - cp pr_agent/settings/.secrets_template.toml pr_agent/settings/.secrets.toml - # Edit .secrets.toml file - ``` +5) Copy the secrets template file and fill in the following: + +``` +cp pr_agent/settings/.secrets_template.toml pr_agent/settings/.secrets.toml +# Edit .secrets.toml file +``` + - Your OpenAI key. - Copy your app's private key to the private_key field. - Copy your app's ID to the app_id field. - Copy your app's webhook secret to the webhook_secret field. - Set deployment_type to 'app' in [configuration.toml](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml) -> The .secrets.toml file is not copied to the Docker image by default, and is only used for local development. -> If you want to use the .secrets.toml file in your Docker image, you can add remove it from the .dockerignore file. -> In most production environments, you would inject the secrets file as environment variables or as mounted volumes. -> For example, in order to inject a secrets file as a volume in a Kubernetes environment you can update your pod spec to include the following, -> assuming you have a secret named `pr-agent-settings` with a key named `.secrets.toml`: -``` - volumes: - - name: settings-volume - secret: - secretName: pr-agent-settings -// ... - containers: -// ... - volumeMounts: - - mountPath: /app/pr_agent/settings_prod - name: settings-volume -``` + > The .secrets.toml file is not copied to the Docker image by default, and is only used for local development. + > If you want to use the .secrets.toml file in your Docker image, you can add remove it from the .dockerignore file. + > In most production environments, you would inject the secrets file as environment variables or as mounted volumes. + > For example, in order to inject a secrets file as a volume in a Kubernetes environment you can update your pod spec to include the following, + > assuming you have a secret named `pr-agent-settings` with a key named `.secrets.toml`: + ``` + volumes: + - name: settings-volume + secret: + secretName: pr-agent-settings + // ... + containers: + // ... + volumeMounts: + - mountPath: /app/pr_agent/settings_prod + name: settings-volume + ``` + + > Another option is to set the secrets as environment variables in your deployment environment, for example `OPENAI.KEY` and `GITHUB.USER_TOKEN`. -> Another option is to set the secrets as environment variables in your deployment environment, for example `OPENAI.KEY` and `GITHUB.USER_TOKEN`. +6) Build a Docker image for the app and optionally push it to a Docker repository. We'll use Dockerhub as an example: -6. Build a Docker image for the app and optionally push it to a Docker repository. We'll use Dockerhub as an example: - -``` -docker build . -t codiumai/pr-agent:github_app --target github_app -f docker/Dockerfile -docker push codiumai/pr-agent:github_app # Push to your Docker repository -``` + ``` + docker build . -t codiumai/pr-agent:github_app --target github_app -f docker/Dockerfile + docker push codiumai/pr-agent:github_app # Push to your Docker repository + ``` 7. Host the app using a server, serverless function, or container environment. Alternatively, for development and debugging, you may use tools like smee.io to forward webhooks to your local machine. From 8fb75c16af3f88065aab2a58fba16a4c35e021b3 Mon Sep 17 00:00:00 2001 From: Ori Kotek Date: Mon, 11 Mar 2024 20:08:16 +0200 Subject: [PATCH 15/26] doc update --- docs/docs/installation/gitlab_pro.md | 37 ++++++++++++++++++++++++++++ docs/mkdocs.yml | 1 + 2 files changed, 38 insertions(+) create mode 100644 docs/docs/installation/gitlab_pro.md diff --git a/docs/docs/installation/gitlab_pro.md b/docs/docs/installation/gitlab_pro.md new file mode 100644 index 00000000..20902b74 --- /dev/null +++ b/docs/docs/installation/gitlab_pro.md @@ -0,0 +1,37 @@ +## Install Hosted PR-Agent Pro for GitLab (Teams & Enterprise) + +### Step 1 + +Acquire a personal, project or group level access token. Enable the “api” scope in order to allow PR-Agent to read pull requests, comment and respond to requests. + + + +Store the token in a safe place, you won’t be able to access it again after it was generated. + +### Step 2 + +Generate a shared secret and link it to the access token. Browse to [https://register.gitlab.pr-agent.codium.ai](https://register.gitlab.pr-agent.codium.ai). +Fill in your generated GitLab token and your company or personal name in the appropriate fields and click "Submit". + +You should see "Success!" displayed above the Submit button, and a shared secret will be generated. Store it in a safe place, you won’t be able to access it again after it was generated. + +### Step 3 + +Install a webhook for your repository or groups, by clicking “webhooks” on the settings menu. Click the “Add new webhook” button. + + + +In the webhook definition form, fill in the following fields: +URL: https://pro.gitlab.pr-agent.codium.ai/webhook + +Secret token: Your CodiumAI key +Trigger: Check the ‘comments’ and ‘merge request events’ boxes. +Enable SSL verification: Check the box. + + + +### Step 4 + +You’re all set! + +Open a new merge request or add a MR comment with one of PR-Agent’s commands such as /review, /describe or /improve. \ No newline at end of file diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index b71bf125..6e8153cf 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -7,6 +7,7 @@ nav: - Locally: 'installation/locally.md' - GitHub: 'installation/github.md' - GitLab: 'installation/gitlab.md' + - 💎 GitLab Pro: 'installation/gitlab_pro.md' - BitBucket: 'installation/bitbucket.md' - Azure DevOps: 'installation/azure.md' - Usage Guide: From 5f98a0c5398ef247ea97cf4dabbdec55709748e6 Mon Sep 17 00:00:00 2001 From: Almog Lavi Date: Tue, 12 Mar 2024 10:22:48 +0200 Subject: [PATCH 16/26] Update footer title and improve responsive design in footer.html --- docs/overrides/partials/footer.html | 49 +++++++++++++++++++---------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/docs/overrides/partials/footer.html b/docs/overrides/partials/footer.html index 96ba7e86..b3235a69 100644 --- a/docs/overrides/partials/footer.html +++ b/docs/overrides/partials/footer.html @@ -3,7 +3,7 @@ -Footer Customization +Footer From 31a8f5302abbbcd7b2862dac793745f892a0f7c7 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Tue, 12 Mar 2024 17:02:45 +0200 Subject: [PATCH 17/26] Update get_pr_labels method to support label updates and prevent unnecessary label republishing --- pr_agent/git_providers/azuredevops_provider.py | 2 +- pr_agent/git_providers/bitbucket_provider.py | 2 +- pr_agent/git_providers/bitbucket_server_provider.py | 2 +- pr_agent/git_providers/codecommit_provider.py | 2 +- pr_agent/git_providers/gerrit_provider.py | 2 +- pr_agent/git_providers/git_provider.py | 2 +- pr_agent/git_providers/github_provider.py | 11 +++++++++-- pr_agent/git_providers/gitlab_provider.py | 2 +- pr_agent/git_providers/local_git_provider.py | 2 +- pr_agent/tools/pr_description.py | 10 +++++++--- pr_agent/tools/pr_reviewer.py | 11 +++++++---- 11 files changed, 31 insertions(+), 17 deletions(-) diff --git a/pr_agent/git_providers/azuredevops_provider.py b/pr_agent/git_providers/azuredevops_provider.py index 3cded721..a710c254 100644 --- a/pr_agent/git_providers/azuredevops_provider.py +++ b/pr_agent/git_providers/azuredevops_provider.py @@ -165,7 +165,7 @@ class AzureDevopsProvider(GitProvider): except Exception as e: get_logger().exception(f"Failed to publish labels, error: {e}") - def get_pr_labels(self): + def get_pr_labels(self, update=False): try: labels = self.azure_devops_client.get_pull_request_labels( project=self.workspace_slug, diff --git a/pr_agent/git_providers/bitbucket_provider.py b/pr_agent/git_providers/bitbucket_provider.py index c4873f88..3516516c 100644 --- a/pr_agent/git_providers/bitbucket_provider.py +++ b/pr_agent/git_providers/bitbucket_provider.py @@ -404,5 +404,5 @@ class BitbucketProvider(GitProvider): pass # bitbucket does not support labels - def get_pr_labels(self): + def get_pr_labels(self, update=False): pass diff --git a/pr_agent/git_providers/bitbucket_server_provider.py b/pr_agent/git_providers/bitbucket_server_provider.py index 3b8168ea..0f9e58d4 100644 --- a/pr_agent/git_providers/bitbucket_server_provider.py +++ b/pr_agent/git_providers/bitbucket_server_provider.py @@ -347,7 +347,7 @@ class BitbucketServerProvider(GitProvider): pass # bitbucket does not support labels - def get_pr_labels(self): + def get_pr_labels(self, update=False): pass def _get_pr_comments_url(self): diff --git a/pr_agent/git_providers/codecommit_provider.py b/pr_agent/git_providers/codecommit_provider.py index cbaf75f1..f035351d 100644 --- a/pr_agent/git_providers/codecommit_provider.py +++ b/pr_agent/git_providers/codecommit_provider.py @@ -216,7 +216,7 @@ class CodeCommitProvider(GitProvider): def publish_labels(self, labels): return [""] # not implemented yet - def get_pr_labels(self): + def get_pr_labels(self, update=False): return [""] # not implemented yet def remove_initial_comment(self): diff --git a/pr_agent/git_providers/gerrit_provider.py b/pr_agent/git_providers/gerrit_provider.py index 5a6da1a2..8e33151a 100644 --- a/pr_agent/git_providers/gerrit_provider.py +++ b/pr_agent/git_providers/gerrit_provider.py @@ -208,7 +208,7 @@ class GerritProvider(GitProvider): Comment = namedtuple('Comment', ['body']) return Comments([Comment(c['message']) for c in reversed(comments)]) - def get_pr_labels(self): + def get_pr_labels(self, update=False): raise NotImplementedError( 'Getting labels is not implemented for the gerrit provider') diff --git a/pr_agent/git_providers/git_provider.py b/pr_agent/git_providers/git_provider.py index e8a78b4b..9eb09a1a 100644 --- a/pr_agent/git_providers/git_provider.py +++ b/pr_agent/git_providers/git_provider.py @@ -164,7 +164,7 @@ class GitProvider(ABC): pass @abstractmethod - def get_pr_labels(self): + def get_pr_labels(self, update=False): pass def get_repo_labels(self): diff --git a/pr_agent/git_providers/github_provider.py b/pr_agent/git_providers/github_provider.py index 2f928f82..b6d04bc0 100644 --- a/pr_agent/git_providers/github_provider.py +++ b/pr_agent/git_providers/github_provider.py @@ -650,9 +650,16 @@ class GithubProvider(GitProvider): except Exception as e: get_logger().exception(f"Failed to publish labels, error: {e}") - def get_pr_labels(self): + def get_pr_labels(self, update=False): try: - return [label.name for label in self.pr.labels] + if not update: + labels =self.pr.labels + return [label.name for label in labels] + else: # obtain the latest labels. Maybe they changed while the AI was running + headers, labels = self.pr._requester.requestJsonAndCheck( + "GET", f"{self.pr.issue_url}/labels") + return [label['name'] for label in labels] + except Exception as e: get_logger().exception(f"Failed to get labels, error: {e}") return [] diff --git a/pr_agent/git_providers/gitlab_provider.py b/pr_agent/git_providers/gitlab_provider.py index 5021896d..3a2e1c85 100644 --- a/pr_agent/git_providers/gitlab_provider.py +++ b/pr_agent/git_providers/gitlab_provider.py @@ -419,7 +419,7 @@ class GitLabProvider(GitProvider): def publish_inline_comments(self, comments: list[dict]): pass - def get_pr_labels(self): + def get_pr_labels(self, update=False): return self.mr.labels def get_repo_labels(self): diff --git a/pr_agent/git_providers/local_git_provider.py b/pr_agent/git_providers/local_git_provider.py index 83c50791..678a519c 100644 --- a/pr_agent/git_providers/local_git_provider.py +++ b/pr_agent/git_providers/local_git_provider.py @@ -176,5 +176,5 @@ class LocalGitProvider(GitProvider): def get_issue_comments(self): raise NotImplementedError('Getting issue comments is not implemented for the local git provider') - def get_pr_labels(self): + def get_pr_labels(self, update=False): raise NotImplementedError('Getting labels is not implemented for the local git provider') diff --git a/pr_agent/tools/pr_description.py b/pr_agent/tools/pr_description.py index 33674d00..d5ca914c 100644 --- a/pr_agent/tools/pr_description.py +++ b/pr_agent/tools/pr_description.py @@ -118,11 +118,15 @@ class PRDescription: if get_settings().config.publish_output: # publish labels if get_settings().pr_description.publish_labels and self.git_provider.is_supported("get_labels"): - original_labels = self.git_provider.get_pr_labels() + original_labels = self.git_provider.get_pr_labels(update=True) get_logger().debug(f"original labels", artifact=original_labels) user_labels = get_user_labels(original_labels) - get_logger().debug(f"published labels:\n{pr_labels + user_labels}") - self.git_provider.publish_labels(pr_labels + user_labels) + new_labels = pr_labels + user_labels + get_logger().debug(f"published labels", artifact=new_labels) + if new_labels != original_labels: + self.git_provider.publish_labels(new_labels) + else: + get_logger().debug(f"Labels are the same, not updating") # publish description if get_settings().pr_description.publish_description_as_comment: diff --git a/pr_agent/tools/pr_reviewer.py b/pr_agent/tools/pr_reviewer.py index 854e351c..696b62fb 100644 --- a/pr_agent/tools/pr_reviewer.py +++ b/pr_agent/tools/pr_reviewer.py @@ -369,17 +369,20 @@ class PRReviewer: if security_concerns_bool: review_labels.append('Possible security concern') - current_labels = self.git_provider.get_pr_labels() + current_labels = self.git_provider.get_pr_labels(update=True) + get_logger().debug(f"Current labels:\n{current_labels}") if current_labels: current_labels_filtered = [label for label in current_labels if not label.lower().startswith('review effort [1-5]:') and not label.lower().startswith( 'possible security concern')] else: current_labels_filtered = [] - if current_labels or review_labels: - get_logger().debug(f"Current labels:\n{current_labels}") + new_labels = review_labels + current_labels_filtered + if (current_labels or review_labels) and new_labels != current_labels: get_logger().info(f"Setting review labels:\n{review_labels + current_labels_filtered}") - self.git_provider.publish_labels(review_labels + current_labels_filtered) + self.git_provider.publish_labels(new_labels) + else: + get_logger().info(f"Review labels are already set:\n{review_labels + current_labels_filtered}") except Exception as e: get_logger().error(f"Failed to set review labels, error: {e}") From 785fbe04aef74fa5d8c14cd099912aa5392015a2 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Tue, 12 Mar 2024 17:27:26 +0200 Subject: [PATCH 18/26] update links --- pr_agent/servers/help.py | 34 +++++++++++++++---------------- pr_agent/tools/pr_help_message.py | 28 ++++++++++++------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/pr_agent/servers/help.py b/pr_agent/servers/help.py index d93a6791..1168c743 100644 --- a/pr_agent/servers/help.py +++ b/pr_agent/servers/help.py @@ -9,7 +9,7 @@ class HelpMessage: "> - **/add_docs** 💎: Generate docstring for new components introduced in the PR. \n" \ "> - **/generate_labels** 💎: Generate labels for the PR based on the PR's contents. \n" \ "> - **/analyze** 💎: Automatically analyzes the PR, and presents changes walkthrough for each component. \n\n" \ - ">See the [tools guide](https://github.com/Codium-ai/pr-agent/blob/main/docs/TOOLS_GUIDE.md) for more details.\n" \ + ">See the [tools guide](https://pr-agent-docs.codium.ai/tools/) for more details.\n" \ ">To list the possible configuration parameters, add a **/config** comment. \n" return commands_text @@ -22,13 +22,13 @@ class HelpMessage: @staticmethod def get_review_usage_guide(): output ="**Overview:**\n" - output +="The `review` tool scans the PR code changes, and generates a PR review. The tool can be triggered [automatically](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#github-app-automatic-tools) every time a new PR is opened, or can be invoked manually by commenting on any PR.\n" + output +="The `review` tool scans the PR code changes, and generates a PR review. The tool can be triggered [automatically](https://pr-agent-docs.codium.ai/usage-guide/automations_and_usage/#github-app-automatic-tools-when-a-new-pr-is-opened) every time a new PR is opened, or can be invoked manually by commenting on any PR.\n" output +="""\ When commenting, to edit [configurations](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L19) related to the review tool (`pr_reviewer` section), use the following template: ``` /review --pr_reviewer.some_config1=... --pr_reviewer.some_config2=... ``` -With a [configuration file](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#working-with-github-app), use the following template: +With a [configuration file](https://pr-agent-docs.codium.ai/usage-guide/configuration_options/), use the following template: ``` [pr_reviewer] some_config1=... @@ -62,7 +62,7 @@ Use triple quotes to write multi-line instructions. Use bullet points to make th # automation output += "
      Feedback            
How to enable\\disable automation
\n\n" output += """\ -- When you first install PR-Agent app, the [default mode](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#github-app-automatic-tools) for the `review` tool is: +- When you first install PR-Agent app, the [default mode](https://pr-agent-docs.codium.ai/usage-guide/automations_and_usage/#github-app-automatic-tools-when-a-new-pr-is-opened) for the `review` tool is: ``` pr_commands = ["/review", ...] ``` @@ -93,7 +93,7 @@ The `review` tool can auto-generate two specific types of labels for a PR: output += "
Extra sub-tools
\n\n" output += """\ The `review` tool provides a collection of possible feedbacks about a PR. -It is recommended to review the [possible options](https://github.com/Codium-ai/pr-agent/blob/main/docs/REVIEW.md#enabledisable-features), and choose the ones relevant for your use case. +It is recommended to review the [possible options](https://pr-agent-docs.codium.ai/tools/review/#enabledisable-features), and choose the ones relevant for your use case. Some of the feature that are disabled by default are quite useful, and should be considered for enabling. For example: `require_score_review`, `require_soc2_ticket`, and more. """ @@ -131,7 +131,7 @@ maximal_review_effort = 5 output += "
" - output += f"\n\nSee the [review usage](https://github.com/Codium-ai/pr-agent/blob/main/docs/REVIEW.md) page for a comprehensive guide on using this tool.\n\n" + output += f"\n\nSee the [review usage](https://pr-agent-docs.codium.ai/tools/review/) page for a comprehensive guide on using this tool.\n\n" return output @@ -141,14 +141,14 @@ maximal_review_effort = 5 def get_describe_usage_guide(): output = "**Overview:**\n" output += "The `describe` tool scans the PR code changes, and generates a description for the PR - title, type, summary, walkthrough and labels. " - output += "The tool can be triggered [automatically](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#github-app-automatic-tools) every time a new PR is opened, or can be invoked manually by commenting on a PR.\n" + output += "The tool can be triggered [automatically](https://pr-agent-docs.codium.ai/usage-guide/automations_and_usage/#github-app-automatic-tools-when-a-new-pr-is-opened) every time a new PR is opened, or can be invoked manually by commenting on a PR.\n" output += """\ When commenting, to edit [configurations](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L46) related to the describe tool (`pr_description` section), use the following template: ``` /describe --pr_description.some_config1=... --pr_description.some_config2=... ``` -With a [configuration file](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#working-with-github-app), use the following template: +With a [configuration file](https://pr-agent-docs.codium.ai/usage-guide/configuration_options/), use the following template: ``` [pr_description] some_config1=... @@ -160,7 +160,7 @@ some_config2=... # automation output += "
Enabling\\disabling automation
\n\n" output += """\ -- When you first install the app, the [default mode](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#github-app-automatic-tools) for the describe tool is: +- When you first install the app, the [default mode](https://pr-agent-docs.codium.ai/usage-guide/automations_and_usage/#github-app-automatic-tools-when-a-new-pr-is-opened) for the describe tool is: ``` pr_commands = ["/describe --pr_description.add_original_user_description=true" "--pr_description.keep_original_user_title=true", ...] @@ -186,7 +186,7 @@ Note that when markers are enabled, if the original PR description does not cont output += """\ The default labels of the `describe` tool are quite generic: [`Bug fix`, `Tests`, `Enhancement`, `Documentation`, `Other`]. -If you specify [custom labels](https://github.com/Codium-ai/pr-agent/blob/main/docs/DESCRIBE.md#handle-custom-labels-from-the-repos-labels-page-gem) in the repo's labels page or via configuration file, you can get tailored labels for your use cases. +If you specify [custom labels](https://pr-agent-docs.codium.ai/tools/describe/#handle-custom-labels-from-the-repos-labels-page) in the repo's labels page or via configuration file, you can get tailored labels for your use cases. Examples for custom labels: - `Main topic:performance` - pr_agent:The main topic of this PR is performance - `New endpoint` - pr_agent:A new endpoint was added in this PR @@ -240,7 +240,7 @@ Use triple quotes to write multi-line instructions. Use bullet points to make th output += "" - output += f"\n\nSee the [describe usage](https://github.com/Codium-ai/pr-agent/blob/main/docs/DESCRIBE.md) page for a comprehensive guide on using this tool.\n\n" + output += f"\n\nSee the [describe usage](https://pr-agent-docs.codium.ai/tools/describe/) page for a comprehensive guide on using this tool.\n\n" return output @@ -265,7 +265,7 @@ Note that the tool does not have "memory" of previous questions, and answers eac output += "" - output += f"\n\nSee the [ask usage](https://github.com/Codium-ai/pr-agent/blob/main/docs/ASK.md) page for a comprehensive guide on using this tool.\n\n" + output += f"\n\nSee the [ask usage](https://pr-agent-docs.codium.ai/tools/ask/) page for a comprehensive guide on using this tool.\n\n" return output @@ -274,7 +274,7 @@ Note that the tool does not have "memory" of previous questions, and answers eac def get_improve_usage_guide(): output = "**Overview:**\n" output += "The `improve` tool scans the PR code changes, and automatically generates suggestions for improving the PR code. " - output += "The tool can be triggered [automatically](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#github-app-automatic-tools) every time a new PR is opened, or can be invoked manually by commenting on a PR.\n" + output += "The tool can be triggered [automatically](https://pr-agent-docs.codium.ai/usage-guide/automations_and_usage/#github-app-automatic-tools-when-a-new-pr-is-opened) every time a new PR is opened, or can be invoked manually by commenting on a PR.\n" output += """\ When commenting, to edit [configurations](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L69) related to the improve tool (`pr_code_suggestions` section), use the following template: @@ -282,7 +282,7 @@ When commenting, to edit [configurations](https://github.com/Codium-ai/pr-agent/ /improve --pr_code_suggestions.some_config1=... --pr_code_suggestions.some_config2=... ``` -With a [configuration file](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#working-with-github-app), use the following template: +With a [configuration file](https://pr-agent-docs.codium.ai/usage-guide/configuration_options/), use the following template: ``` [pr_code_suggestions] @@ -296,7 +296,7 @@ some_config2=... # automation output += "
Enabling\\disabling automation
\n\n" output += """\ -When you first install the app, the [default mode](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#github-app-automatic-tools) for the improve tool is: +When you first install the app, the [default mode](https://pr-agent-docs.codium.ai/usage-guide/automations_and_usage/#github-app-automatic-tools-when-a-new-pr-is-opened) for the improve tool is: ``` pr_commands = ["/improve --pr_code_suggestions.summarize=true", ...] @@ -335,7 +335,7 @@ Use triple quotes to write multi-line instructions. Use bullet points to make th output += """\ - While the current AI for code is getting better and better (GPT-4), it's not flawless. Not all the suggestions will be perfect, and a user should not accept all of them automatically. - Suggestions are not meant to be simplistic. Instead, they aim to give deep feedback and raise questions, ideas and thoughts to the user, who can then use his judgment, experience, and understanding of the code base. -- Recommended to use the 'extra_instructions' field to guide the model to suggestions that are more relevant to the specific needs of the project, or use the [custom suggestions :gem:](https://github.com/Codium-ai/pr-agent/blob/main/docs/CUSTOM_SUGGESTIONS.md) tool +- Recommended to use the 'extra_instructions' field to guide the model to suggestions that are more relevant to the specific needs of the project, or use the [custom suggestions :gem:](https://pr-agent-docs.codium.ai/tools/custom_suggestions/) tool - With large PRs, best quality will be obtained by using 'improve --extended' mode. @@ -349,6 +349,6 @@ Use triple quotes to write multi-line instructions. Use bullet points to make th output += "" - output += f"\n\nSee the [improve usage](https://github.com/Codium-ai/pr-agent/blob/main/docs/IMPROVE.md) page for a more comprehensive guide on using this tool.\n\n" + output += f"\n\nSee the [improve usage](https://pr-agent-docs.codium.ai/tools/improve/) page for a more comprehensive guide on using this tool.\n\n" return output \ No newline at end of file diff --git a/pr_agent/tools/pr_help_message.py b/pr_agent/tools/pr_help_message.py index 357a9112..3204d8e4 100644 --- a/pr_agent/tools/pr_help_message.py +++ b/pr_agent/tools/pr_help_message.py @@ -21,21 +21,21 @@ class PRHelpMessage: pr_comment = "## PR Agent Walkthrough\n\n" pr_comment += "🤖 Welcome to the PR Agent, an AI-powered tool for automated pull request analysis, feedback, suggestions and more.""" pr_comment += "\n\nHere is a list of tools you can use to interact with the PR Agent:\n" - base_path = "https://github.com/Codium-ai/pr-agent/tree/main/docs" + base_path = "https://pr-agent-docs.codium.ai/tools" tool_names = [] - tool_names.append(f"[DESCRIBE]({base_path}/DESCRIBE.md)") - tool_names.append(f"[REVIEW]({base_path}/REVIEW.md)") - tool_names.append(f"[IMPROVE]({base_path}/IMPROVE.md)") - tool_names.append(f"[ANALYZE]({base_path}/Analyze.md) 💎") - tool_names.append(f"[UPDATE CHANGELOG]({base_path}/UPDATE_CHANGELOG.md)") - tool_names.append(f"[ADD DOCUMENTATION]({base_path}/ADD_DOCUMENTATION.md) 💎") - tool_names.append(f"[ASK]({base_path}/ASK.md)") - tool_names.append(f"[GENERATE CUSTOM LABELS]({base_path}/GENERATE_CUSTOM_LABELS.md)") - tool_names.append(f"[TEST]({base_path}/TEST.md) 💎") - tool_names.append(f"[CI FEEDBACK]({base_path}/CI_FEEDBACK.md) 💎") - tool_names.append(f"[CUSTOM SUGGESTIONS]({base_path}/CUSTOM_SUGGESTIONS.md) 💎") - tool_names.append(f"[SIMILAR ISSUE]({base_path}/SIMILAR_ISSUE.md)") + tool_names.append(f"[DESCRIBE]({base_path}/describe/)") + tool_names.append(f"[REVIEW]({base_path}/review/)") + tool_names.append(f"[IMPROVE]({base_path}/improve/)") + tool_names.append(f"[ANALYZE]({base_path}/analyze/) 💎") + tool_names.append(f"[UPDATE CHANGELOG]({base_path}/update_changelog/)") + tool_names.append(f"[ADD DOCUMENTATION]({base_path}/documentation/) 💎") + tool_names.append(f"[ASK]({base_path}/ask/)") + tool_names.append(f"[GENERATE CUSTOM LABELS]({base_path}/custom_labels/)") + tool_names.append(f"[TEST]({base_path}/test/) 💎") + tool_names.append(f"[CI FEEDBACK]({base_path}/ci_feedback/) 💎") + tool_names.append(f"[CUSTOM SUGGESTIONS]({base_path}/custom_suggestions/) 💎") + tool_names.append(f"[SIMILAR ISSUE]({base_path}/similar_issue/)") descriptions = [] descriptions.append("Generates PR description - title, type, summary, code walkthrough and labels") @@ -91,7 +91,7 @@ class PRHelpMessage: for i in range(len(tool_names)): pr_comment += f"\n\n\n{tool_names[i]}{commands[i]}{descriptions[i]}" pr_comment += "\n\n" - pr_comment += f"""\n\nNote that each tool be [invoked automatically](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#github-app-automatic-tools-for-pr-actions) when a new PR is opened, or called manually by [commenting on a PR](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#online-usage).""" + pr_comment += f"""\n\nNote that each tool be [invoked automatically](https://pr-agent-docs.codium.ai/usage-guide/automations_and_usage/) when a new PR is opened, or called manually by [commenting on a PR](https://pr-agent-docs.codium.ai/usage-guide/automations_and_usage/#online-usage).""" if get_settings().config.publish_output: self.git_provider.publish_comment(pr_comment) except Exception as e: From 8b29c3a2be70bc3dab5b51ab6e2acb00337f4545 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Tue, 12 Mar 2024 18:18:08 +0200 Subject: [PATCH 19/26] typo --- pr_agent/tools/pr_help_message.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr_agent/tools/pr_help_message.py b/pr_agent/tools/pr_help_message.py index 3204d8e4..f7a5ff13 100644 --- a/pr_agent/tools/pr_help_message.py +++ b/pr_agent/tools/pr_help_message.py @@ -35,7 +35,7 @@ class PRHelpMessage: tool_names.append(f"[TEST]({base_path}/test/) 💎") tool_names.append(f"[CI FEEDBACK]({base_path}/ci_feedback/) 💎") tool_names.append(f"[CUSTOM SUGGESTIONS]({base_path}/custom_suggestions/) 💎") - tool_names.append(f"[SIMILAR ISSUE]({base_path}/similar_issue/)") + tool_names.append(f"[SIMILAR ISSUE]({base_path}/similar_issues/)") descriptions = [] descriptions.append("Generates PR description - title, type, summary, code walkthrough and labels") From 78cabf28a49daa4ac22a8953786f5263d5f6e508 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Tue, 12 Mar 2024 18:25:42 +0200 Subject: [PATCH 20/26] Update label comparison logic in pr_reviewer.py and pr_description.py to consider unordered lists --- pr_agent/tools/pr_description.py | 2 +- pr_agent/tools/pr_reviewer.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pr_agent/tools/pr_description.py b/pr_agent/tools/pr_description.py index d5ca914c..28df555f 100644 --- a/pr_agent/tools/pr_description.py +++ b/pr_agent/tools/pr_description.py @@ -123,7 +123,7 @@ class PRDescription: user_labels = get_user_labels(original_labels) new_labels = pr_labels + user_labels get_logger().debug(f"published labels", artifact=new_labels) - if new_labels != original_labels: + if sorted(new_labels) != sorted(original_labels): self.git_provider.publish_labels(new_labels) else: get_logger().debug(f"Labels are the same, not updating") diff --git a/pr_agent/tools/pr_reviewer.py b/pr_agent/tools/pr_reviewer.py index 696b62fb..19f9a163 100644 --- a/pr_agent/tools/pr_reviewer.py +++ b/pr_agent/tools/pr_reviewer.py @@ -378,7 +378,7 @@ class PRReviewer: else: current_labels_filtered = [] new_labels = review_labels + current_labels_filtered - if (current_labels or review_labels) and new_labels != current_labels: + if (current_labels or review_labels) and sorted(new_labels) != sorted(current_labels): get_logger().info(f"Setting review labels:\n{review_labels + current_labels_filtered}") self.git_provider.publish_labels(new_labels) else: From 50d0af0372176e8190aa846f686ca32b438a91fa Mon Sep 17 00:00:00 2001 From: Almog Lavi Date: Thu, 14 Mar 2024 13:56:10 +0200 Subject: [PATCH 21/26] Added Google Analytics to mkdocs configuration --- docs/mkdocs.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 6e8153cf..1062c6c3 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -93,6 +93,9 @@ extra: link: https://twitter.com/CodiumAI - icon: fontawesome/brands/instagram link: https://www.instagram.com/codiumai/ + analytics: + provider: google + property: G-9LJSZ77MJF extra_css: - css/custom.css From b472149714463f8c69ce57745dce2d124160065e Mon Sep 17 00:00:00 2001 From: Almog Lavi Date: Thu, 14 Mar 2024 16:13:08 +0200 Subject: [PATCH 22/26] Replace hardcoded Google Analytics ID with environment variable in mkdocs.yml --- docs/mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 1062c6c3..0a76acf1 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -95,7 +95,7 @@ extra: link: https://www.instagram.com/codiumai/ analytics: provider: google - property: G-9LJSZ77MJF + property: ${{ secrets.GOOGLE_ANALYTICS_ID }} extra_css: - css/custom.css From 1593d8932baf10e9fc044ce45b9b5a6032404ced Mon Sep 17 00:00:00 2001 From: mrT23 Date: Fri, 15 Mar 2024 12:37:50 +0200 Subject: [PATCH 23/26] Refactor code in pr_code_suggestions.py and remove 'use_repo_settings_file' from azure.md and automations_and_usage.md --- docs/docs/installation/azure.md | 1 - docs/docs/usage-guide/automations_and_usage.md | 1 - pr_agent/tools/pr_code_suggestions.py | 8 ++------ 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/docs/docs/installation/azure.md b/docs/docs/installation/azure.md index 8c111581..e8c11664 100644 --- a/docs/docs/installation/azure.md +++ b/docs/docs/installation/azure.md @@ -4,7 +4,6 @@ To use Azure DevOps provider use the following settings in configuration.toml: ``` [config] git_provider="azure" -use_repo_settings_file=false ``` Azure DevOps provider supports [PAT token](https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=Windows) or [DefaultAzureCredential](https://learn.microsoft.com/en-us/azure/developer/python/sdk/authentication-overview#authentication-in-server-environments) authentication. diff --git a/docs/docs/usage-guide/automations_and_usage.md b/docs/docs/usage-guide/automations_and_usage.md index 81f182b5..b39f7e02 100644 --- a/docs/docs/usage-guide/automations_and_usage.md +++ b/docs/docs/usage-guide/automations_and_usage.md @@ -170,7 +170,6 @@ To use Azure DevOps provider use the following settings in configuration.toml: ``` [config] git_provider="azure" -use_repo_settings_file=false ``` Azure DevOps provider supports [PAT token](https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=Windows) or [DefaultAzureCredential](https://learn.microsoft.com/en-us/azure/developer/python/sdk/authentication-overview#authentication-in-server-environments) authentication. diff --git a/pr_agent/tools/pr_code_suggestions.py b/pr_agent/tools/pr_code_suggestions.py index 51dbe130..d4f3556a 100644 --- a/pr_agent/tools/pr_code_suggestions.py +++ b/pr_agent/tools/pr_code_suggestions.py @@ -393,11 +393,7 @@ class PRCodeSuggestions: for label, suggestions in suggestions_labels.items(): num_suggestions=len(suggestions) - # pr_body += f"""{label}""" pr_body += f"""{label.capitalize()}\n""" - # pr_body += f"""""" - # pr_body += f"""
{len(suggestions)} suggestions""" - # pr_body += f"""""" for i, suggestion in enumerate(suggestions): relevant_file = suggestion['relevant_file'].strip() @@ -444,11 +440,11 @@ class PRCodeSuggestions: {example_code} """ pr_body += f"" - pr_body += f"" + # pr_body += "" - pr_body += """""" + # pr_body += """""" pr_body += """
""" return pr_body except Exception as e: From 44386573eb95e695dc06b1a97e5772639ce761f8 Mon Sep 17 00:00:00 2001 From: Tom Brews Views Date: Fri, 15 Mar 2024 12:04:07 +0100 Subject: [PATCH 24/26] ad dcorect size logo to the header and adjust title spacing --- docs/docs/assets/logo.svg | 140 ++++++++++++++++++++++++++++++++++++++ docs/docs/css/custom.css | 88 ++---------------------- docs/mkdocs.yml | 2 +- 3 files changed, 145 insertions(+), 85 deletions(-) create mode 100644 docs/docs/assets/logo.svg diff --git a/docs/docs/assets/logo.svg b/docs/docs/assets/logo.svg new file mode 100644 index 00000000..5de22677 --- /dev/null +++ b/docs/docs/assets/logo.svg @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/docs/css/custom.css b/docs/docs/css/custom.css index 0e9b26fe..2f963ccd 100644 --- a/docs/docs/css/custom.css +++ b/docs/docs/css/custom.css @@ -5,94 +5,14 @@ --md-accent-fg-color: #AEA1F1; } .md-nav__title, .md-nav__link { - font-size: 16px; /* Adjust the font size as needed */ + font-size: 16px; } .md-tabs__link { - font-size: 16px; /* Adjust the font size as needed */ + font-size: 16px; } .md-header__title { - font-size: 20px; /* Adjust the font size as needed */ + font-size: 20px; + margin-left: 0px !important; } - -/* -@media (prefers-color-scheme: light) { - body { - --md-primary-fg-color: #00ffee !important; - --md-primary-bg-color: #ff0000 !important; - } - - body, .md-main, .md-content { - background-color: #4312f5 !important; - } -} - -@media (prefers-color-scheme: dark) { - body { - --md-primary-fg-color: #171518 !important; - --md-primary-bg-color: #171518 !important; - } - - body, .md-main, .md-content { - background-color: #171518 !important; - } - - .md-header__title { - color: #ffffff !important; - } - - .md-tabs .md-tabs__link { - color: #ffffff !important; - } - - .md-tabs .md-tabs__link:hover, - .md-tabs .md-tabs__link:focus { - color: #ffffff !important; - } - - .md-header__button { - color: #ffffff !important; - } - - .md-header__button svg { - fill: currentColor !important; - } - - .md-header__button:hover, - .md-header__button:focus { - color: #ffffff !important; - } - - .md-header__button:hover svg, - .md-header__button:focus svg { - fill: currentColor !important; - } - - .md-search__icon svg { - fill: #ffffff !important; - } - - .md-search__input { - color: #ffffff !important; - } - - .md-nav__item--active > .md-nav__link--active, - .md-nav__link--active { - color: #AEA1F1 !important; - } - - .md-nav--secondary .md-nav__title { - background: #171518; - box-shadow: 0 0 0.4rem 0.4rem #171518; - } - - .md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link { - background: #171518; - box-shadow: 0 0 0.4rem 0.4rem #171518; - } - - .md-content a { - color: #AEA1F1 !important; - } -} */ \ No newline at end of file diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 0a76acf1..8da53d48 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -35,7 +35,7 @@ nav: - Core Abilities: 'core-abilities/index.md' theme: - logo: assets/logo.png + logo: assets/logo.svg favicon: assets/favicon.ico name: material features: From 74345284bdc537caf2dba073bbeda55f063327d5 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Sat, 16 Mar 2024 13:47:44 +0200 Subject: [PATCH 25/26] Enhance AI handler logging and add main PR language attribute to AI handler in various tools --- pr_agent/algo/ai_handlers/litellm_ai_handler.py | 15 +++++++++++++-- pr_agent/tools/pr_add_docs.py | 2 ++ pr_agent/tools/pr_code_suggestions.py | 1 + pr_agent/tools/pr_description.py | 1 + pr_agent/tools/pr_generate_labels.py | 3 ++- pr_agent/tools/pr_information_from_user.py | 2 ++ pr_agent/tools/pr_line_questions.py | 5 ++++- pr_agent/tools/pr_questions.py | 2 ++ pr_agent/tools/pr_reviewer.py | 2 ++ pr_agent/tools/pr_update_changelog.py | 3 +++ 10 files changed, 32 insertions(+), 4 deletions(-) diff --git a/pr_agent/algo/ai_handlers/litellm_ai_handler.py b/pr_agent/algo/ai_handlers/litellm_ai_handler.py index 51f72960..666db1b1 100644 --- a/pr_agent/algo/ai_handlers/litellm_ai_handler.py +++ b/pr_agent/algo/ai_handlers/litellm_ai_handler.py @@ -125,10 +125,21 @@ class LiteLLMAIHandler(BaseAiHandler): else: resp = response["choices"][0]['message']['content'] finish_reason = response["choices"][0]["finish_reason"] - # usage = response.get("usage") get_logger().debug(f"\nAI response:\n{resp}") - get_logger().debug("Full_response", artifact=response) + # log the full response for debugging, including the system and user prompts + response_log = response.dict() + response_log['system'] = system + response_log['user'] = user + response_log['output'] = resp + response_log['finish_reason'] = finish_reason + if hasattr(self, 'main_pr_language'): + response_log['main_pr_language'] = self.main_pr_language + else: + response_log['main_pr_language'] = 'unknown' + get_logger().debug("Full_response", artifact=response_log) + + # for CLI debugging if get_settings().config.verbosity_level >= 2: get_logger().info(f"\nAI response:\n{resp}") diff --git a/pr_agent/tools/pr_add_docs.py b/pr_agent/tools/pr_add_docs.py index d13a829d..a671dd3b 100644 --- a/pr_agent/tools/pr_add_docs.py +++ b/pr_agent/tools/pr_add_docs.py @@ -26,6 +26,8 @@ class PRAddDocs: ) self.ai_handler = ai_handler() + self.ai_handler.main_pr_language = self.main_language + self.patches_diff = None self.prediction = None self.cli_mode = cli_mode diff --git a/pr_agent/tools/pr_code_suggestions.py b/pr_agent/tools/pr_code_suggestions.py index d4f3556a..33628123 100644 --- a/pr_agent/tools/pr_code_suggestions.py +++ b/pr_agent/tools/pr_code_suggestions.py @@ -46,6 +46,7 @@ class PRCodeSuggestions: num_code_suggestions = get_settings().pr_code_suggestions.num_code_suggestions self.ai_handler = ai_handler() + self.ai_handler.main_pr_language = self.main_language self.patches_diff = None self.prediction = None self.cli_mode = cli_mode diff --git a/pr_agent/tools/pr_description.py b/pr_agent/tools/pr_description.py index 28df555f..7500efa7 100644 --- a/pr_agent/tools/pr_description.py +++ b/pr_agent/tools/pr_description.py @@ -41,6 +41,7 @@ class PRDescription: # Initialize the AI handler self.ai_handler = ai_handler() + self.ai_handler.main_pr_language = self.main_pr_language # Initialize the variables dictionary diff --git a/pr_agent/tools/pr_generate_labels.py b/pr_agent/tools/pr_generate_labels.py index 1d91d5e0..4111f7c2 100644 --- a/pr_agent/tools/pr_generate_labels.py +++ b/pr_agent/tools/pr_generate_labels.py @@ -35,7 +35,8 @@ class PRGenerateLabels: # Initialize the AI handler self.ai_handler = ai_handler() - + self.ai_handler.main_pr_language = self.main_pr_language + # Initialize the variables dictionary self.vars = { "title": self.git_provider.pr.title, diff --git a/pr_agent/tools/pr_information_from_user.py b/pr_agent/tools/pr_information_from_user.py index 1523d737..03537181 100644 --- a/pr_agent/tools/pr_information_from_user.py +++ b/pr_agent/tools/pr_information_from_user.py @@ -21,6 +21,8 @@ class PRInformationFromUser: self.git_provider.get_languages(), self.git_provider.get_files() ) self.ai_handler = ai_handler() + self.ai_handler.main_pr_language = self.main_pr_language + self.vars = { "title": self.git_provider.pr.title, "branch": self.git_provider.get_pr_branch(), diff --git a/pr_agent/tools/pr_line_questions.py b/pr_agent/tools/pr_line_questions.py index e6386fd1..e26e06d5 100644 --- a/pr_agent/tools/pr_line_questions.py +++ b/pr_agent/tools/pr_line_questions.py @@ -22,8 +22,11 @@ class PR_LineQuestions: def __init__(self, pr_url: str, args=None, ai_handler: partial[BaseAiHandler,] = LiteLLMAIHandler): self.question_str = self.parse_args(args) self.git_provider = get_git_provider()(pr_url) - + self.main_pr_language = get_main_pr_language( + self.git_provider.get_languages(), self.git_provider.get_files() + ) self.ai_handler = ai_handler() + self.ai_handler.main_pr_language = self.main_pr_language self.vars = { "title": self.git_provider.pr.title, diff --git a/pr_agent/tools/pr_questions.py b/pr_agent/tools/pr_questions.py index 7d789e2b..3849029d 100644 --- a/pr_agent/tools/pr_questions.py +++ b/pr_agent/tools/pr_questions.py @@ -22,6 +22,8 @@ class PRQuestions: self.git_provider.get_languages(), self.git_provider.get_files() ) self.ai_handler = ai_handler() + self.ai_handler.main_pr_language = self.main_pr_language + self.question_str = question_str self.vars = { "title": self.git_provider.pr.title, diff --git a/pr_agent/tools/pr_reviewer.py b/pr_agent/tools/pr_reviewer.py index 19f9a163..f0475b82 100644 --- a/pr_agent/tools/pr_reviewer.py +++ b/pr_agent/tools/pr_reviewer.py @@ -46,6 +46,8 @@ class PRReviewer: if self.is_answer and not self.git_provider.is_supported("get_issue_comments"): raise Exception(f"Answer mode is not supported for {get_settings().config.git_provider} for now") self.ai_handler = ai_handler() + self.ai_handler.main_pr_language = self.main_language + self.patches_diff = None self.prediction = None diff --git a/pr_agent/tools/pr_update_changelog.py b/pr_agent/tools/pr_update_changelog.py index 4e168d5d..399e0599 100644 --- a/pr_agent/tools/pr_update_changelog.py +++ b/pr_agent/tools/pr_update_changelog.py @@ -26,7 +26,10 @@ class PRUpdateChangelog: ) self.commit_changelog = get_settings().pr_update_changelog.push_changelog_changes self._get_changlog_file() # self.changelog_file_str + self.ai_handler = ai_handler() + self.ai_handler.main_pr_language = self.main_language + self.patches_diff = None self.prediction = None self.cli_mode = cli_mode From 669e0769380f88bb00ac8ace34bcd050bdd4482f Mon Sep 17 00:00:00 2001 From: mrT23 Date: Sat, 16 Mar 2024 13:52:02 +0200 Subject: [PATCH 26/26] Enhance AI handler logging and add main PR language attribute to AI handler in various tools --- .../algo/ai_handlers/litellm_ai_handler.py | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/pr_agent/algo/ai_handlers/litellm_ai_handler.py b/pr_agent/algo/ai_handlers/litellm_ai_handler.py index 666db1b1..527a20a8 100644 --- a/pr_agent/algo/ai_handlers/litellm_ai_handler.py +++ b/pr_agent/algo/ai_handlers/litellm_ai_handler.py @@ -73,6 +73,18 @@ class LiteLLMAIHandler(BaseAiHandler): region_name=get_settings().aws.bedrock_region, ) + def prepare_logs(self, response, system, user, resp, finish_reason): + response_log = response.dict().copy() + response_log['system'] = system + response_log['user'] = user + response_log['output'] = resp + response_log['finish_reason'] = finish_reason + if hasattr(self, 'main_pr_language'): + response_log['main_pr_language'] = self.main_pr_language + else: + response_log['main_pr_language'] = 'unknown' + return response_log + @property def deployment_id(self): """ @@ -127,16 +139,8 @@ class LiteLLMAIHandler(BaseAiHandler): finish_reason = response["choices"][0]["finish_reason"] get_logger().debug(f"\nAI response:\n{resp}") - # log the full response for debugging, including the system and user prompts - response_log = response.dict() - response_log['system'] = system - response_log['user'] = user - response_log['output'] = resp - response_log['finish_reason'] = finish_reason - if hasattr(self, 'main_pr_language'): - response_log['main_pr_language'] = self.main_pr_language - else: - response_log['main_pr_language'] = 'unknown' + # log the full response for debugging + response_log = self.prepare_logs(response, system, user, resp, finish_reason) get_logger().debug("Full_response", artifact=response_log) # for CLI debugging