From 4b67ee6021e31c793fb8bdc1eb2a6a82248d17f4 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Wed, 31 Jan 2024 16:55:34 +0800 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E6=97=A7=E7=9A=84issue=E5=86=8D=E5=8F=91=E9=80=81?= =?UTF-8?q?=E5=8D=A1=E7=89=87.=20close=20#125?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/tasks/lark/chat.py | 90 +++++++++++++++++++++++++++++++++++++ server/utils/github/repo.py | 22 +++++++++ server/utils/lark/parser.py | 15 +++++++ 3 files changed, 127 insertions(+) diff --git a/server/tasks/lark/chat.py b/server/tasks/lark/chat.py index ca3d1177..a04f3065 100644 --- a/server/tasks/lark/chat.py +++ b/server/tasks/lark/chat.py @@ -1,5 +1,6 @@ import json import logging +from urllib.parse import urlparse from celery_app import app, celery from model.schema import ( @@ -242,3 +243,92 @@ def create_issue( "创建 issue 失败", app_id, message_id, content, data, *args, **kwargs ) return response + + +@celery.task() +def sync_issue( + issue_id, issue_link, app_id, message_id, content, data, *args, **kwargs +): + repo_name = "" + try: + if not issue_id: + path = urlparse(issue_link).path + issue_id = int(path.split("/").pop()) + repo_name = path.split("/")[2] + except Exception as e: + logging.error(e) + + if not issue_id: + return send_chat_failed_tip( + "找不到issue", app_id, message_id, content, data, *args, **kwargs + ) + + chat_id = data["event"]["message"]["chat_id"] + chat_group = ( + db.session.query(ChatGroup) + .filter( + ChatGroup.chat_id == chat_id, + ) + .first() + ) + if not chat_group: + return send_chat_failed_tip( + "找不到项目群", app_id, message_id, content, data, *args, **kwargs + ) + + repos = ( + db.session.query(Repo) + .filter( + Repo.chat_group_id == chat_group.id, + Repo.status == 0, + ) + .all() + ) + # 如果有多个,尝试从issue_link里面拿到repo_name过滤一下 + if len(repos) > 1 and repo_name: + repos = [repo for repo in repos if repo.name == repo_name] + + if len(repos) > 1: + return send_chat_failed_tip( + "当前群有多个项目,无法唯一确定仓库", app_id, message_id, content, data, *args, **kwargs + ) + if len(repos) == 0: + return send_chat_failed_tip( + "找不到项目", app_id, message_id, content, data, *args, **kwargs + ) + + repo = repos[0] # 能找到唯一的仓库才执行 + + code_application = ( + db.session.query(CodeApplication) + .filter( + CodeApplication.id == repo.application_id, + ) + .first() + ) + if not code_application: + return send_chat_failed_tip( + "找不到对应的项目", app_id, message_id, content, data, *args, **kwargs + ) + + team = ( + db.session.query(Team) + .filter( + Team.id == code_application.team_id, + ) + .first() + ) + if not team: + return send_chat_failed_tip( + "找不到对应的项目", app_id, message_id, content, data, *args, **kwargs + ) + github_app = GitHubAppRepo( + code_application.installation_id, user_id=current_code_user_id + ) + response = github_app.get_one_issue(team.name, repo.name, issue_id) + # TODO 先测试一下看这个结果是什么样子? + # 后面需要插入记录,再发卡片,创建话题 + logging.debug("get_one_issue %r", response) + return send_chat_failed_tip( + "同步 issue 失败", app_id, message_id, content, data, *args, **kwargs + ) diff --git a/server/utils/github/repo.py b/server/utils/github/repo.py index 62d4acf1..261805af 100644 --- a/server/utils/github/repo.py +++ b/server/utils/github/repo.py @@ -201,6 +201,28 @@ def create_issue( }, ) + def get_one_issue( + self, + repo_onwer: str, + repo_name: str, + issue_number: int, + ) -> dict | None: + """Get an issue + + Args: + repo_onwer (str): The repo owner. + repo_name (str): The repo name. + issue_number (int): The issue id + + Returns: + dict: The issue info. + """ + + return self.base_github_rest_api( + f"https://api.github.com/repos/{repo_onwer}/{repo_name}/issues/{issue_number}", + auth_type="install_token", + ) + def create_issue_comment( self, repo_onwer: str, repo_name: str, issue_number: int, body: str ) -> dict | None: diff --git a/server/utils/lark/parser.py b/server/utils/lark/parser.py index ce6c1cc2..3329459e 100644 --- a/server/utils/lark/parser.py +++ b/server/utils/lark/parser.py @@ -1,5 +1,6 @@ import argparse import logging +from urllib.parse import urlparse import tasks from utils.constant import TopicType @@ -209,6 +210,20 @@ def on_issue(self, param, unkown, *args, **kwargs): } # 只有群聊才是指定的repo if "group" == chat_type: + if len(param.argv) == 1: + issue_id_or_link = param.argv[0] + try: + if issue_id_or_link.isdigit(): + tasks.sync_issue.delay(int(issue_id_or_link)) + elif urlparse(issue_id_or_link).netloc: + # 这里是否需要检查netloc==github.com?? + tasks.sync_issue.delay(None, issue_id_or_link) + else: + raise Exception("invalid issue_id or issue link.") + return "issue", param, unkown + except Exception as e: + logging.error() + title, users, labels = [], [], [] for arg in param.argv: From c8f3c5bfdb18e2bf350fdc3a3574028f1b261c4c Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Thu, 1 Feb 2024 13:17:59 +0800 Subject: [PATCH 2/6] hotfix --- server/tasks/lark/chat.py | 6 ++++++ server/utils/lark/parser.py | 10 +++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/server/tasks/lark/chat.py b/server/tasks/lark/chat.py index a04f3065..06af8213 100644 --- a/server/tasks/lark/chat.py +++ b/server/tasks/lark/chat.py @@ -322,6 +322,12 @@ def sync_issue( return send_chat_failed_tip( "找不到对应的项目", app_id, message_id, content, data, *args, **kwargs ) + openid = data["event"]["sender"]["sender_id"]["open_id"] + # 这里连三个表查询,所以一次性都查出来 + code_users = get_code_users_by_openid([openid] + users) + # 当前操作的用户 + current_code_user_id = code_users[openid][0] + github_app = GitHubAppRepo( code_application.installation_id, user_id=current_code_user_id ) diff --git a/server/utils/lark/parser.py b/server/utils/lark/parser.py index 3329459e..dc3d40b7 100644 --- a/server/utils/lark/parser.py +++ b/server/utils/lark/parser.py @@ -214,15 +214,19 @@ def on_issue(self, param, unkown, *args, **kwargs): issue_id_or_link = param.argv[0] try: if issue_id_or_link.isdigit(): - tasks.sync_issue.delay(int(issue_id_or_link)) + tasks.sync_issue.delay( + int(issue_id_or_link), None, *args, **kwargs + ) elif urlparse(issue_id_or_link).netloc: # 这里是否需要检查netloc==github.com?? - tasks.sync_issue.delay(None, issue_id_or_link) + tasks.sync_issue.delay( + None, issue_id_or_link, *args, **kwargs + ) else: raise Exception("invalid issue_id or issue link.") return "issue", param, unkown except Exception as e: - logging.error() + logging.error(e) title, users, labels = [], [], [] From 4e307a7949dfa45326b79256664ec161e114bbd8 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Thu, 1 Feb 2024 13:50:04 +0800 Subject: [PATCH 3/6] feat: sync issue and pull request --- server/tasks/lark/chat.py | 22 ++++++++++++++++++---- server/utils/github/repo.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/server/tasks/lark/chat.py b/server/tasks/lark/chat.py index 06af8213..bdb518fc 100644 --- a/server/tasks/lark/chat.py +++ b/server/tasks/lark/chat.py @@ -15,6 +15,8 @@ ) from model.team import get_code_users_by_openid from sqlalchemy.orm import aliased +from tasks.github.issue import on_issue_opened +from tasks.github.pull_request import on_pull_request_opened from utils.github.repo import GitHubAppRepo from utils.lark.chat_manual import ChatManual, ChatView from utils.lark.chat_tip_failed import ChatTipFailed @@ -250,11 +252,13 @@ def sync_issue( issue_id, issue_link, app_id, message_id, content, data, *args, **kwargs ): repo_name = "" + is_pr = False try: if not issue_id: path = urlparse(issue_link).path issue_id = int(path.split("/").pop()) repo_name = path.split("/")[2] + is_pr = path.split("/")[3] == "pull" except Exception as e: logging.error(e) @@ -324,17 +328,27 @@ def sync_issue( ) openid = data["event"]["sender"]["sender_id"]["open_id"] # 这里连三个表查询,所以一次性都查出来 - code_users = get_code_users_by_openid([openid] + users) + code_users = get_code_users_by_openid([openid]) # 当前操作的用户 current_code_user_id = code_users[openid][0] github_app = GitHubAppRepo( code_application.installation_id, user_id=current_code_user_id ) - response = github_app.get_one_issue(team.name, repo.name, issue_id) - # TODO 先测试一下看这个结果是什么样子? + # 后面需要插入记录,再发卡片,创建话题 - logging.debug("get_one_issue %r", response) + repository = github_app.get_repo_info_by_name(team.name, repo.name) + if is_pr: + pull_request = github_app.get_one_pull_requrst(team.name, repo.name, issue_id) + logging.debug("get_one_pull_requrst %r", pull_request) + on_pull_request_opened( + {"action": "opened", "pull_request": pull_request, "repository": repository} + ) + else: + issue = github_app.get_one_issue(team.name, repo.name, issue_id) + logging.debug("get_one_issue %r", issue) + on_issue_opened({"action": "opened", "issue": issue, "repository": repository}) + return send_chat_failed_tip( "同步 issue 失败", app_id, message_id, content, data, *args, **kwargs ) diff --git a/server/utils/github/repo.py b/server/utils/github/repo.py index 261805af..9783ab5f 100644 --- a/server/utils/github/repo.py +++ b/server/utils/github/repo.py @@ -36,6 +36,17 @@ def get_repo_info(self, repo_id: str) -> dict | None: if not team: return None + return self.get_repo_info_by_name(repo.name) + + def get_repo_info_by_name(self, repo_name: str) -> dict | None: + """Get repo info by repo name. + + Args: + repo_name (str): The repo name from GitHub. + + Returns: + dict: Repo info. + """ return self.base_github_rest_api( f"https://api.github.com/repos/{team.name}/{repo.name}", "GET", @@ -285,6 +296,28 @@ def update_issue( json=json, ) + def get_one_pull_request( + self, + repo_onwer: str, + repo_name: str, + pull_number: int, + ) -> dict | None: + """Get an issue + + Args: + repo_onwer (str): The repo owner. + repo_name (str): The repo name. + pull_number (int): The pull_request id + + Returns: + dict: The issue info. + """ + + return self.base_github_rest_api( + f"https://api.github.com/repos/{repo_onwer}/{repo_name}/pulls/{pull_number}", + auth_type="install_token", + ) + def requested_reviewers( self, repo_onwer: str, From 2fa4f4e7598487bad32ef4f4fcf6321985630b60 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Thu, 1 Feb 2024 13:56:17 +0800 Subject: [PATCH 4/6] feat: sync issue and pull request --- server/tasks/lark/chat.py | 10 ++++++---- server/utils/github/repo.py | 7 ++++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/server/tasks/lark/chat.py b/server/tasks/lark/chat.py index bdb518fc..64a4e3fc 100644 --- a/server/tasks/lark/chat.py +++ b/server/tasks/lark/chat.py @@ -15,8 +15,6 @@ ) from model.team import get_code_users_by_openid from sqlalchemy.orm import aliased -from tasks.github.issue import on_issue_opened -from tasks.github.pull_request import on_pull_request_opened from utils.github.repo import GitHubAppRepo from utils.lark.chat_manual import ChatManual, ChatView from utils.lark.chat_tip_failed import ChatTipFailed @@ -336,18 +334,22 @@ def sync_issue( code_application.installation_id, user_id=current_code_user_id ) + import tasks + # 后面需要插入记录,再发卡片,创建话题 repository = github_app.get_repo_info_by_name(team.name, repo.name) if is_pr: pull_request = github_app.get_one_pull_requrst(team.name, repo.name, issue_id) logging.debug("get_one_pull_requrst %r", pull_request) - on_pull_request_opened( + tasks.on_pull_request_opened( {"action": "opened", "pull_request": pull_request, "repository": repository} ) else: issue = github_app.get_one_issue(team.name, repo.name, issue_id) logging.debug("get_one_issue %r", issue) - on_issue_opened({"action": "opened", "issue": issue, "repository": repository}) + tasks.on_issue_opened( + {"action": "opened", "issue": issue, "repository": repository} + ) return send_chat_failed_tip( "同步 issue 失败", app_id, message_id, content, data, *args, **kwargs diff --git a/server/utils/github/repo.py b/server/utils/github/repo.py index 9783ab5f..de8373fc 100644 --- a/server/utils/github/repo.py +++ b/server/utils/github/repo.py @@ -36,19 +36,20 @@ def get_repo_info(self, repo_id: str) -> dict | None: if not team: return None - return self.get_repo_info_by_name(repo.name) + return self.get_repo_info_by_name(team.name, repo.name) - def get_repo_info_by_name(self, repo_name: str) -> dict | None: + def get_repo_info_by_name(self, team_name: str, repo_name: str) -> dict | None: """Get repo info by repo name. Args: + team_name (str): The organization name from GitHub. repo_name (str): The repo name from GitHub. Returns: dict: Repo info. """ return self.base_github_rest_api( - f"https://api.github.com/repos/{team.name}/{repo.name}", + f"https://api.github.com/repos/{team_name}/{repo_name}", "GET", "install_token", ) From 1020d1f48f11ae6927ecfeacb2084fa311debfa9 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Thu, 1 Feb 2024 14:11:10 +0800 Subject: [PATCH 5/6] feat: sync issue and pull request --- server/tasks/lark/chat.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/server/tasks/lark/chat.py b/server/tasks/lark/chat.py index 64a4e3fc..afa98e28 100644 --- a/server/tasks/lark/chat.py +++ b/server/tasks/lark/chat.py @@ -339,16 +339,26 @@ def sync_issue( # 后面需要插入记录,再发卡片,创建话题 repository = github_app.get_repo_info_by_name(team.name, repo.name) if is_pr: - pull_request = github_app.get_one_pull_requrst(team.name, repo.name, issue_id) + pull_request = github_app.get_one_pull_request(team.name, repo.name, issue_id) logging.debug("get_one_pull_requrst %r", pull_request) tasks.on_pull_request_opened( - {"action": "opened", "pull_request": pull_request, "repository": repository} + { + "action": "opened", + "sender": pull_request["user"], + "pull_request": pull_request, + "repository": repository, + } ) else: issue = github_app.get_one_issue(team.name, repo.name, issue_id) logging.debug("get_one_issue %r", issue) tasks.on_issue_opened( - {"action": "opened", "issue": issue, "repository": repository} + { + "action": "opened", + "sender": issue["user"], + "issue": issue, + "repository": repository, + } ) return send_chat_failed_tip( From 0464edc657e81d03a791ef66a3a9c9a75c4ea457 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Thu, 1 Feb 2024 14:12:36 +0800 Subject: [PATCH 6/6] feat: sync issue and pull request --- server/tasks/lark/chat.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/tasks/lark/chat.py b/server/tasks/lark/chat.py index afa98e28..4ab6eb43 100644 --- a/server/tasks/lark/chat.py +++ b/server/tasks/lark/chat.py @@ -341,7 +341,7 @@ def sync_issue( if is_pr: pull_request = github_app.get_one_pull_request(team.name, repo.name, issue_id) logging.debug("get_one_pull_requrst %r", pull_request) - tasks.on_pull_request_opened( + return tasks.on_pull_request_opened( { "action": "opened", "sender": pull_request["user"], @@ -352,7 +352,7 @@ def sync_issue( else: issue = github_app.get_one_issue(team.name, repo.name, issue_id) logging.debug("get_one_issue %r", issue) - tasks.on_issue_opened( + return tasks.on_issue_opened( { "action": "opened", "sender": issue["user"],