diff --git a/pr_agent/git_providers/bitbucket_provider.py b/pr_agent/git_providers/bitbucket_provider.py index bef33ae5..5d1d92d7 100644 --- a/pr_agent/git_providers/bitbucket_provider.py +++ b/pr_agent/git_providers/bitbucket_provider.py @@ -153,7 +153,7 @@ class BitbucketProvider(GitProvider): self.diff_files = diff_files return diff_files - def publish_persistent_comment(self, pr_comment: str, initial_header: str, update_header: str = True): + def publish_persistent_comment(self, pr_comment: str, initial_header: str, update_header: bool = True): try: for comment in self.pr.comments(): body = comment.raw diff --git a/pr_agent/git_providers/git_provider.py b/pr_agent/git_providers/git_provider.py index 98b6e4f1..05122f9c 100644 --- a/pr_agent/git_providers/git_provider.py +++ b/pr_agent/git_providers/git_provider.py @@ -40,45 +40,10 @@ class GitProvider(ABC): def publish_description(self, pr_title: str, pr_body: str): pass - @abstractmethod - def publish_comment(self, pr_comment: str, is_temporary: bool = False): - pass - - def publish_persistent_comment(self, pr_comment: str, initial_header: str, update_header: bool): - self.publish_comment(pr_comment) - - @abstractmethod - def publish_inline_comment(self, body: str, relevant_file: str, relevant_line_in_file: str): - pass - - @abstractmethod - def create_inline_comment(self, body: str, relevant_file: str, relevant_line_in_file: str): - pass - - @abstractmethod - def publish_inline_comments(self, comments: list[dict]): - pass - @abstractmethod def publish_code_suggestions(self, code_suggestions: list) -> bool: pass - @abstractmethod - def publish_labels(self, labels): - pass - - @abstractmethod - def get_labels(self): - pass - - @abstractmethod - def remove_initial_comment(self): - pass - - @abstractmethod - def remove_comment(self, comment): - pass - @abstractmethod def get_languages(self): pass @@ -117,11 +82,54 @@ class GitProvider(ABC): return description.split("## User Description:", 1)[1].strip() @abstractmethod - def get_issue_comments(self): + def get_repo_settings(self): + pass + + def get_pr_id(self): + return "" + + #### comments operations #### + @abstractmethod + def publish_comment(self, pr_comment: str, is_temporary: bool = False): + pass + + def publish_persistent_comment(self, pr_comment: str, initial_header: str, update_header: bool): + self.publish_comment(pr_comment) + + @abstractmethod + def publish_inline_comment(self, body: str, relevant_file: str, relevant_line_in_file: str): pass @abstractmethod - def get_repo_settings(self): + def create_inline_comment(self, body: str, relevant_file: str, relevant_line_in_file: str): + pass + + @abstractmethod + def publish_inline_comments(self, comments: list[dict]): + pass + + @abstractmethod + def remove_initial_comment(self): + pass + + @abstractmethod + def remove_comment(self, comment): + pass + + @abstractmethod + def get_issue_comments(self): + pass + + def get_comment_url(self, comment) -> str: + return "" + + #### labels operations #### + @abstractmethod + def publish_labels(self, labels): + pass + + @abstractmethod + def get_labels(self): pass @abstractmethod @@ -132,11 +140,12 @@ class GitProvider(ABC): def remove_reaction(self, issue_comment_id: int, reaction_id: int) -> bool: pass + #### commits operations #### @abstractmethod def get_commit_messages(self): pass - def get_pr_id(self): + def get_latest_commit_url(self) -> str: return "" def get_main_pr_language(languages, files) -> str: diff --git a/pr_agent/git_providers/github_provider.py b/pr_agent/git_providers/github_provider.py index 52924725..c9abe2b1 100644 --- a/pr_agent/git_providers/github_provider.py +++ b/pr_agent/git_providers/github_provider.py @@ -154,20 +154,28 @@ class GithubProvider(GitProvider): def publish_description(self, pr_title: str, pr_body: str): self.pr.edit(title=pr_title, body=pr_body) - def publish_persistent_comment(self, pr_comment: str, initial_header: str, update_header: bool=True): + def get_latest_commit_url(self) -> str: + return self.last_commit_id.html_url + + def get_comment_url(self, comment) -> str: + return comment.html_url + + def publish_persistent_comment(self, pr_comment: str, initial_header: str, update_header: bool = True): prev_comments = list(self.pr.get_issue_comments()) for comment in prev_comments: body = comment.body if body.startswith(initial_header): - latest_commit = self.pr.get_commits().reversed[0].html_url + latest_commit_url = self.get_latest_commit_url() + comment_url = self.get_comment_url(comment) if update_header: - updated_text = f"{initial_header}\n\n### (review updated to commit {latest_commit})\n" - pr_comment_updated = pr_comment.replace(initial_header, updated_text) + updated_header = f"{initial_header}\n\n### (review updated until commit {latest_commit_url})\n" + pr_comment_updated = pr_comment.replace(initial_header, updated_header) else: pr_comment_updated = pr_comment - get_logger().info(f"Persistent mode- updating comment {comment.html_url} to latest review message") + get_logger().info(f"Persistent mode- updating comment {comment_url} to latest review message") response = comment.edit(pr_comment_updated) - self.publish_comment(f"**[Persistent review]({comment.html_url})** updated to latest commit {latest_commit}") + self.publish_comment( + f"**[Persistent review]({comment_url})** updated to latest commit {latest_commit_url}") return self.publish_comment(pr_comment) diff --git a/pr_agent/git_providers/gitlab_provider.py b/pr_agent/git_providers/gitlab_provider.py index a4d2090c..2dc9d3ed 100644 --- a/pr_agent/git_providers/gitlab_provider.py +++ b/pr_agent/git_providers/gitlab_provider.py @@ -136,16 +136,26 @@ class GitLabProvider(GitProvider): except Exception as e: get_logger().exception(f"Could not update merge request {self.id_mr} description: {e}") - def publish_persistent_comment(self, pr_comment: str, initial_header: str, update_header: str = True): + def get_latest_commit_url(self): + return self.mr.commits().next().web_url + + def get_comment_url(self, comment): + return f"{self.mr.web_url}#note_{comment.id}" + + def publish_persistent_comment(self, pr_comment: str, initial_header: str, update_header: bool = True): try: for comment in self.mr.notes.list(get_all=True)[::-1]: if comment.body.startswith(initial_header): + latest_commit_url = self.get_latest_commit_url() + comment_url = self.get_comment_url(comment) if update_header: - updated_header = f"{initial_header}\n\n ### (updated)\n" + updated_header = f"{initial_header}\n\n### (review updated until commit {latest_commit_url})\n" pr_comment_updated = pr_comment.replace(initial_header, updated_header) else: pr_comment_updated = pr_comment response = self.mr.notes.update(comment.id, {'body': pr_comment_updated}) + self.publish_comment( + f"**[Persistent review]({comment_url})** updated to latest commit {latest_commit_url}") return except Exception as e: get_logger().exception(f"Failed to update persistent review, error: {e}")