From d8ea2731ea5c7e3031d0e31645bced17870de55b Mon Sep 17 00:00:00 2001 From: yochail Date: Sun, 11 Feb 2024 03:27:47 +0000 Subject: [PATCH 1/3] add support for azure inline commnets --- .../git_providers/azuredevops_provider.py | 73 ++++++++++++++----- 1 file changed, 56 insertions(+), 17 deletions(-) diff --git a/pr_agent/git_providers/azuredevops_provider.py b/pr_agent/git_providers/azuredevops_provider.py index a46c0ab2..cc116735 100644 --- a/pr_agent/git_providers/azuredevops_provider.py +++ b/pr_agent/git_providers/azuredevops_provider.py @@ -2,12 +2,13 @@ import os from typing import Optional, Tuple from urllib.parse import urlparse +from pr_agent.algo.pr_processing import find_line_number_of_relevant_line_in_file + from ..log import get_logger from ..algo.language_handler import is_valid_file from ..algo.utils import clip_tokens, load_large_diff from ..config_loader import get_settings -from .git_provider import GitProvider -from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo +from .git_provider import EDIT_TYPE, FilePatchInfo, GitProvider AZURE_DEVOPS_AVAILABLE = True @@ -163,12 +164,62 @@ class AzureDevopsProvider(GitProvider): def is_supported(self, capability: str) -> bool: if capability in [ "get_issue_comments", - "create_inline_comment", - "publish_inline_comments", ]: return False return True + + def publish_inline_comment(self, body: str, relevant_file: str, relevant_line_in_file: str): + self.publish_inline_comments([self.create_inline_comment(body, relevant_file, relevant_line_in_file)]) + + def create_inline_comment(self, body: str, relevant_file: str, relevant_line_in_file: str, + absolute_position: int = None): + position, absolute_position = find_line_number_of_relevant_line_in_file(self.get_diff_files(), + relevant_file.strip('`'), + relevant_line_in_file, + absolute_position) + if position == -1: + if get_settings().config.verbosity_level >= 2: + get_logger().info(f"Could not find position for {relevant_file} {relevant_line_in_file}") + subject_type = "FILE" + else: + subject_type = "LINE" + path = relevant_file.strip() + return dict(body=body, path=path, position=position, absolute_position=absolute_position) if subject_type == "LINE" else {} + + def publish_inline_comments(self, comments: list[dict], disable_fallback: bool = False): + try: + for comment in comments: + comment_obj = Comment(content=comment["body"], comment_type=1) + thread = CommentThread(comments=[comment_obj], + thread_context={ + "filePath": comment["path"], + "rightFileStart": { + "line": comment["absolute_position"], + "offset": 1, # TODO + }, + "rightFileEnd": { + "line": comment["absolute_position"], + "offset": 1, + }, + }, + status="active") + self.azure_devops_client.create_thread( + comment_thread=thread, + project=self.workspace_slug, + repository_id=self.repo_slug, + pull_request_id=self.pr_num + ) + if get_settings().config.verbosity_level >= 2: + get_logger().info( + f"Published code suggestion on {self.pr_num} at {comment_obj['path']}" + ) + return True + except Exception as e: + if get_settings().config.verbosity_level >= 2: + get_logger().error(f"Failed to publish code suggestion, error: {e}") + return False + def set_pr(self, pr_url: str): self.workspace_slug, self.repo_slug, self.pr_num = self._parse_pr_url(pr_url) self.pr = self._get_pr() @@ -348,18 +399,6 @@ class AzureDevopsProvider(GitProvider): except Exception as e: get_logger().exception(f"Failed to remove temp comments, error: {e}") - def publish_inline_comment( - self, body: str, relevant_file: str, relevant_line_in_file: str - ): - raise NotImplementedError( - "Azure DevOps provider does not support publishing inline comment yet" - ) - - def publish_inline_comments(self, comments: list[dict]): - raise NotImplementedError( - "Azure DevOps provider does not support publishing inline comments yet" - ) - def get_title(self): return self.pr.title @@ -476,4 +515,4 @@ class AzureDevopsProvider(GitProvider): except Exception as e: if get_settings().config.verbosity_level >= 2: get_logger().error(f"Failed to get pr id, error: {e}") - return "" + return "" \ No newline at end of file From ba854c228b5553a30c62fce3742a7942b6b26364 Mon Sep 17 00:00:00 2001 From: yochail Date: Sat, 10 Feb 2024 22:36:01 -0500 Subject: [PATCH 2/3] Update azuredevops_provider.py --- pr_agent/git_providers/azuredevops_provider.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pr_agent/git_providers/azuredevops_provider.py b/pr_agent/git_providers/azuredevops_provider.py index cc116735..5c2c126b 100644 --- a/pr_agent/git_providers/azuredevops_provider.py +++ b/pr_agent/git_providers/azuredevops_provider.py @@ -8,7 +8,8 @@ from ..log import get_logger from ..algo.language_handler import is_valid_file from ..algo.utils import clip_tokens, load_large_diff from ..config_loader import get_settings -from .git_provider import EDIT_TYPE, FilePatchInfo, GitProvider +from .git_provider import GitProvider +from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo AZURE_DEVOPS_AVAILABLE = True @@ -515,4 +516,4 @@ class AzureDevopsProvider(GitProvider): except Exception as e: if get_settings().config.verbosity_level >= 2: get_logger().error(f"Failed to get pr id, error: {e}") - return "" \ No newline at end of file + return "" From 47060ddcacd5126e19c648ed79da32fb1d35f938 Mon Sep 17 00:00:00 2001 From: yochail Date: Sun, 11 Feb 2024 12:40:36 -0500 Subject: [PATCH 3/3] fix PR comments - added line position - added try-catch per comment --- .../git_providers/azuredevops_provider.py | 105 ++++++++---------- 1 file changed, 48 insertions(+), 57 deletions(-) diff --git a/pr_agent/git_providers/azuredevops_provider.py b/pr_agent/git_providers/azuredevops_provider.py index 5c2c126b..75fa6001 100644 --- a/pr_agent/git_providers/azuredevops_provider.py +++ b/pr_agent/git_providers/azuredevops_provider.py @@ -2,11 +2,9 @@ import os from typing import Optional, Tuple from urllib.parse import urlparse -from pr_agent.algo.pr_processing import find_line_number_of_relevant_line_in_file - from ..log import get_logger from ..algo.language_handler import is_valid_file -from ..algo.utils import clip_tokens, load_large_diff +from ..algo.utils import clip_tokens, find_line_number_of_relevant_line_in_file, load_large_diff from ..config_loader import get_settings from .git_provider import GitProvider from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo @@ -169,58 +167,6 @@ class AzureDevopsProvider(GitProvider): return False return True - - def publish_inline_comment(self, body: str, relevant_file: str, relevant_line_in_file: str): - self.publish_inline_comments([self.create_inline_comment(body, relevant_file, relevant_line_in_file)]) - - def create_inline_comment(self, body: str, relevant_file: str, relevant_line_in_file: str, - absolute_position: int = None): - position, absolute_position = find_line_number_of_relevant_line_in_file(self.get_diff_files(), - relevant_file.strip('`'), - relevant_line_in_file, - absolute_position) - if position == -1: - if get_settings().config.verbosity_level >= 2: - get_logger().info(f"Could not find position for {relevant_file} {relevant_line_in_file}") - subject_type = "FILE" - else: - subject_type = "LINE" - path = relevant_file.strip() - return dict(body=body, path=path, position=position, absolute_position=absolute_position) if subject_type == "LINE" else {} - - def publish_inline_comments(self, comments: list[dict], disable_fallback: bool = False): - try: - for comment in comments: - comment_obj = Comment(content=comment["body"], comment_type=1) - thread = CommentThread(comments=[comment_obj], - thread_context={ - "filePath": comment["path"], - "rightFileStart": { - "line": comment["absolute_position"], - "offset": 1, # TODO - }, - "rightFileEnd": { - "line": comment["absolute_position"], - "offset": 1, - }, - }, - status="active") - self.azure_devops_client.create_thread( - comment_thread=thread, - project=self.workspace_slug, - repository_id=self.repo_slug, - pull_request_id=self.pr_num - ) - if get_settings().config.verbosity_level >= 2: - get_logger().info( - f"Published code suggestion on {self.pr_num} at {comment_obj['path']}" - ) - return True - except Exception as e: - if get_settings().config.verbosity_level >= 2: - get_logger().error(f"Failed to publish code suggestion, error: {e}") - return False - def set_pr(self, pr_url: str): self.workspace_slug, self.repo_slug, self.pr_num = self._parse_pr_url(pr_url) self.pr = self._get_pr() @@ -363,9 +309,9 @@ class AzureDevopsProvider(GitProvider): print(f"Error: {str(e)}") return [] - def publish_comment(self, pr_comment: str, is_temporary: bool = False): + def publish_comment(self, pr_comment: str, is_temporary: bool = False, thread_context=None): comment = Comment(content=pr_comment) - thread = CommentThread(comments=[comment]) + thread = CommentThread(comments=[comment], thread_context=thread_context, status=1) thread_response = self.azure_devops_client.create_thread( comment_thread=thread, project=self.workspace_slug, @@ -400,6 +346,51 @@ class AzureDevopsProvider(GitProvider): except Exception as e: get_logger().exception(f"Failed to remove temp comments, error: {e}") + def publish_inline_comment(self, body: str, relevant_file: str, relevant_line_in_file: str): + self.publish_inline_comments([self.create_inline_comment(body, relevant_file, relevant_line_in_file)]) + + + def create_inline_comment(self, body: str, relevant_file: str, relevant_line_in_file: str, + absolute_position: int = None): + position, absolute_position = find_line_number_of_relevant_line_in_file(self.get_diff_files(), + relevant_file.strip('`'), + relevant_line_in_file, + absolute_position) + if position == -1: + if get_settings().config.verbosity_level >= 2: + get_logger().info(f"Could not find position for {relevant_file} {relevant_line_in_file}") + subject_type = "FILE" + else: + subject_type = "LINE" + path = relevant_file.strip() + return dict(body=body, path=path, position=position, absolute_position=absolute_position) if subject_type == "LINE" else {} + + def publish_inline_comments(self, comments: list[dict], disable_fallback: bool = False): + overall_sucess = True + for comment in comments: + try: + self.publish_comment(comment["body"], + thread_context={ + "filePath": comment["path"], + "rightFileStart": { + "line": comment["absolute_position"], + "offset": comment["position"], + }, + "rightFileEnd": { + "line": comment["absolute_position"], + "offset": comment["position"], + }, + }) + if get_settings().config.verbosity_level >= 2: + get_logger().info( + f"Published code suggestion on {self.pr_num} at {comment['path']}" + ) + except Exception as e: + if get_settings().config.verbosity_level >= 2: + get_logger().error(f"Failed to publish code suggestion, error: {e}") + overall_sucess = False + return overall_sucess + def get_title(self): return self.pr.title