Github Provider: Support publishing a comment on a non pr issue

This commit is contained in:
Eyal Sharon
2025-03-26 13:36:37 +02:00
parent b42841fcc4
commit 7117e9fe0e

View File

@ -10,6 +10,7 @@ from datetime import datetime
from typing import Optional, Tuple from typing import Optional, Tuple
from urllib.parse import urlparse from urllib.parse import urlparse
from github.Issue import Issue
from github import AppAuthentication, Auth, Github, GithubException from github import AppAuthentication, Auth, Github, GithubException
from retry import retry from retry import retry
from starlette_context import context from starlette_context import context
@ -51,9 +52,29 @@ class GithubProvider(GitProvider):
self.pr_commits = list(self.pr.get_commits()) self.pr_commits = list(self.pr.get_commits())
self.last_commit_id = self.pr_commits[-1] 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 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
else: elif pr_url and 'issue' in pr_url: #url is an issue
self.issue_main = self._get_issue_handle(pr_url)
else: #Instantiated the provider without a PR / Issue
self.pr_commits = None self.pr_commits = None
def _get_issue_handle(self, issue_url) -> Optional[Issue]:
repo_name, issue_number = self._parse_issue_url(issue_url)
if not repo_name or not issue_number:
get_logger().error(f"Given url: {issue_url} is not a valid issue.")
return None
# else: Check if can get a valid Repo handle:
try:
repo_obj = self.github_client.get_repo(repo_name)
if not repo_obj:
get_logger().error(f"Given url: {issue_url}, belonging to owner/repo: {repo_name} does "
f"not have a valid repository: {self.get_git_repo_url(issue_url)}")
return None
# else: Valid repo handle:
return repo_obj.get_issue(issue_number)
except Exception as e:
get_logger().exception(f"Failed to get an issue object for issue: {issue_url}, belonging to owner/repo: {repo_name}")
return None
def get_incremental_commits(self, incremental=IncrementalPR(False)): def get_incremental_commits(self, incremental=IncrementalPR(False)):
self.incremental = incremental self.incremental = incremental
if self.incremental.is_incremental: if self.incremental.is_incremental:
@ -344,10 +365,19 @@ class GithubProvider(GitProvider):
self.publish_persistent_comment_full(pr_comment, initial_header, update_header, name, final_update_message) self.publish_persistent_comment_full(pr_comment, initial_header, update_header, name, final_update_message)
def publish_comment(self, pr_comment: str, is_temporary: bool = False): def publish_comment(self, pr_comment: str, is_temporary: bool = False):
if not self.pr and not self.issue_main:
get_logger().error("Cannot publish a comment if missing PR/Issue context")
return None
if is_temporary and not get_settings().config.publish_output_progress: if is_temporary and not get_settings().config.publish_output_progress:
get_logger().debug(f"Skipping publish_comment for temporary comment: {pr_comment}") get_logger().debug(f"Skipping publish_comment for temporary comment: {pr_comment}")
return None return None
pr_comment = self.limit_output_characters(pr_comment, self.max_comment_chars) pr_comment = self.limit_output_characters(pr_comment, self.max_comment_chars)
# In case this is an issue, can publish the comment on the issue.
if self.issue_main:
return self.issue_main.create_comment(pr_comment)
response = self.pr.create_issue_comment(pr_comment) response = self.pr.create_issue_comment(pr_comment)
if hasattr(response, "user") and hasattr(response.user, "login"): if hasattr(response, "user") and hasattr(response.user, "login"):
self.github_user_id = response.user.login self.github_user_id = response.user.login
@ -731,11 +761,11 @@ class GithubProvider(GitProvider):
def _parse_issue_url(self, issue_url: str) -> Tuple[str, int]: def _parse_issue_url(self, issue_url: str) -> Tuple[str, int]:
parsed_url = urlparse(issue_url) parsed_url = urlparse(issue_url)
if 'github.com' not in parsed_url.netloc: if parsed_url.path.startswith('/api/v3'): #Check if came from github app
raise ValueError("The provided URL is not a valid GitHub URL") parsed_url = urlparse(issue_url.replace("/api/v3", ""))
path_parts = parsed_url.path.strip('/').split('/') path_parts = parsed_url.path.strip('/').split('/')
if 'api.github.com' in parsed_url.netloc: if 'api.github.com' in parsed_url.netloc or '/api/v3' in issue_url: #Check if came from github app
if len(path_parts) < 5 or path_parts[3] != 'issues': if len(path_parts) < 5 or path_parts[3] != 'issues':
raise ValueError("The provided URL does not appear to be a GitHub ISSUE URL") raise ValueError("The provided URL does not appear to be a GitHub ISSUE URL")
repo_name = '/'.join(path_parts[1:3]) repo_name = '/'.join(path_parts[1:3])