mirror of
https://github.com/qodo-ai/pr-agent.git
synced 2025-07-03 12:20:38 +08:00
Support adding / removing reaction from comments in GitHub different servers
This commit is contained in:
@ -89,6 +89,12 @@ class BitbucketProvider:
|
|||||||
def get_issue_comments(self):
|
def get_issue_comments(self):
|
||||||
raise NotImplementedError("Bitbucket provider does not support issue comments yet")
|
raise NotImplementedError("Bitbucket provider does not support issue comments yet")
|
||||||
|
|
||||||
|
def add_eyes_reaction(self, issue_comment_id: int) -> Optional[int]:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def remove_reaction(self, issue_comment_id: int, reaction_id: int) -> bool:
|
||||||
|
return True
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _parse_pr_url(pr_url: str) -> Tuple[str, int]:
|
def _parse_pr_url(pr_url: str) -> Tuple[str, int]:
|
||||||
parsed_url = urlparse(pr_url)
|
parsed_url = urlparse(pr_url)
|
||||||
|
@ -3,6 +3,7 @@ from dataclasses import dataclass
|
|||||||
|
|
||||||
# enum EDIT_TYPE (ADDED, DELETED, MODIFIED, RENAMED)
|
# enum EDIT_TYPE (ADDED, DELETED, MODIFIED, RENAMED)
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
class EDIT_TYPE(Enum):
|
class EDIT_TYPE(Enum):
|
||||||
@ -88,6 +89,13 @@ class GitProvider(ABC):
|
|||||||
def get_issue_comments(self):
|
def get_issue_comments(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def add_eyes_reaction(self, issue_comment_id: int) -> Optional[int]:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def remove_reaction(self, issue_comment_id: int, reaction_id: int) -> bool:
|
||||||
|
pass
|
||||||
|
|
||||||
def get_main_pr_language(languages, files) -> str:
|
def get_main_pr_language(languages, files) -> str:
|
||||||
"""
|
"""
|
||||||
|
@ -2,10 +2,10 @@ import logging
|
|||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Optional, Tuple
|
from typing import Optional, Tuple, Any
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
from github import AppAuthentication, Auth, Github, GithubException
|
from github import AppAuthentication, Auth, Github, GithubException, Reaction
|
||||||
from retry import retry
|
from retry import retry
|
||||||
from starlette_context import context
|
from starlette_context import context
|
||||||
|
|
||||||
@ -263,6 +263,23 @@ class GithubProvider(GitProvider):
|
|||||||
except Exception:
|
except Exception:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
def add_eyes_reaction(self, issue_comment_id: int) -> Optional[int]:
|
||||||
|
try:
|
||||||
|
reaction = self.pr.get_issue_comment(issue_comment_id).create_reaction("eyes")
|
||||||
|
return reaction.id
|
||||||
|
except Exception as e:
|
||||||
|
logging.exception(f"Failed to add eyes reaction, error: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def remove_reaction(self, issue_comment_id: int, reaction_id: int) -> bool:
|
||||||
|
try:
|
||||||
|
self.pr.get_issue_comment(issue_comment_id).delete_reaction(reaction_id)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logging.exception(f"Failed to remove eyes reaction, error: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _parse_pr_url(pr_url: str) -> Tuple[str, int]:
|
def _parse_pr_url(pr_url: str) -> Tuple[str, int]:
|
||||||
parsed_url = urlparse(pr_url)
|
parsed_url = urlparse(pr_url)
|
||||||
|
@ -287,6 +287,12 @@ class GitLabProvider(GitProvider):
|
|||||||
except Exception:
|
except Exception:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
def add_eyes_reaction(self, issue_comment_id: int) -> Optional[int]:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def remove_reaction(self, issue_comment_id: int, reaction_id: int) -> bool:
|
||||||
|
return True
|
||||||
|
|
||||||
def _parse_merge_request_url(self, merge_request_url: str) -> Tuple[str, int]:
|
def _parse_merge_request_url(self, merge_request_url: str) -> Tuple[str, int]:
|
||||||
parsed_url = urlparse(merge_request_url)
|
parsed_url = urlparse(merge_request_url)
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import os
|
|||||||
|
|
||||||
from pr_agent.agent.pr_agent import PRAgent
|
from pr_agent.agent.pr_agent import PRAgent
|
||||||
from pr_agent.config_loader import get_settings
|
from pr_agent.config_loader import get_settings
|
||||||
|
from pr_agent.git_providers import get_git_provider
|
||||||
from pr_agent.tools.pr_reviewer import PRReviewer
|
from pr_agent.tools.pr_reviewer import PRReviewer
|
||||||
|
|
||||||
|
|
||||||
@ -61,7 +62,12 @@ async def run_action():
|
|||||||
pr_url = event_payload.get("issue", {}).get("pull_request", {}).get("url")
|
pr_url = event_payload.get("issue", {}).get("pull_request", {}).get("url")
|
||||||
if pr_url:
|
if pr_url:
|
||||||
body = comment_body.strip().lower()
|
body = comment_body.strip().lower()
|
||||||
|
comment_id = event_payload.get("comment", {}).get("id")
|
||||||
|
provider = get_git_provider()(pr_url=pr_url)
|
||||||
|
added_reaction = provider.add_eyes_reaction(comment_id)
|
||||||
await PRAgent().handle_request(pr_url, body)
|
await PRAgent().handle_request(pr_url, body)
|
||||||
|
if added_reaction:
|
||||||
|
provider.remove_reaction(comment_id, added_reaction)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -11,6 +11,7 @@ from starlette_context.middleware import RawContextMiddleware
|
|||||||
|
|
||||||
from pr_agent.agent.pr_agent import PRAgent
|
from pr_agent.agent.pr_agent import PRAgent
|
||||||
from pr_agent.config_loader import get_settings, global_settings
|
from pr_agent.config_loader import get_settings, global_settings
|
||||||
|
from pr_agent.git_providers import get_git_provider
|
||||||
from pr_agent.servers.utils import verify_signature
|
from pr_agent.servers.utils import verify_signature
|
||||||
|
|
||||||
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
|
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
|
||||||
@ -80,7 +81,13 @@ async def handle_request(body: Dict[str, Any]):
|
|||||||
return {}
|
return {}
|
||||||
pull_request = body["issue"]["pull_request"]
|
pull_request = body["issue"]["pull_request"]
|
||||||
api_url = pull_request.get("url")
|
api_url = pull_request.get("url")
|
||||||
|
comment_id = body.get("comment", {}).get("id")
|
||||||
|
provider = get_git_provider()(pr_url=api_url)
|
||||||
|
added_reaction = provider.add_eyes_reaction(comment_id)
|
||||||
await agent.handle_request(api_url, comment_body)
|
await agent.handle_request(api_url, comment_body)
|
||||||
|
if added_reaction:
|
||||||
|
provider.remove_reaction(comment_id, added_reaction)
|
||||||
|
|
||||||
|
|
||||||
elif action == "opened" or 'reopened' in action:
|
elif action == "opened" or 'reopened' in action:
|
||||||
pull_request = body.get("pull_request")
|
pull_request = body.get("pull_request")
|
||||||
|
@ -98,8 +98,12 @@ async def polling_loop():
|
|||||||
if user_tag not in comment_body:
|
if user_tag not in comment_body:
|
||||||
continue
|
continue
|
||||||
rest_of_comment = comment_body.split(user_tag)[1].strip()
|
rest_of_comment = comment_body.split(user_tag)[1].strip()
|
||||||
|
comment_id = comment['id']
|
||||||
|
git_provider.set_pr(pr_url)
|
||||||
|
added_reaction = git_provider.add_eyes_reaction(comment_id)
|
||||||
success = await agent.handle_request(pr_url, rest_of_comment)
|
success = await agent.handle_request(pr_url, rest_of_comment)
|
||||||
|
if added_reaction:
|
||||||
|
git_provider.remove_reaction(comment_id, added_reaction)
|
||||||
if not success:
|
if not success:
|
||||||
git_provider.set_pr(pr_url)
|
git_provider.set_pr(pr_url)
|
||||||
git_provider.publish_comment("### How to use PR-Agent\n" +
|
git_provider.publish_comment("### How to use PR-Agent\n" +
|
||||||
|
Reference in New Issue
Block a user