From c4848fdbd2f2d5b7d9a0e358ea8a379ced9898af Mon Sep 17 00:00:00 2001 From: uy_sun Date: Sat, 30 Nov 2024 09:43:41 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E4=BC=98=E5=8C=96=20handler=20?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/github/models/git.py | 16 +++ src/plugins/github/models/github.py | 98 ++++++++-------- src/plugins/github/models/issue.py | 5 +- src/plugins/github/plugins/config/__init__.py | 31 +++--- .../github/plugins/publish/__init__.py | 32 ++---- src/plugins/github/plugins/publish/utils.py | 14 ++- src/plugins/github/plugins/remove/__init__.py | 40 ++----- src/plugins/github/plugins/remove/utils.py | 14 ++- .../github/plugins/resolve/__init__.py | 4 +- .../config/process/test_config_auto_merge.py | 19 +--- .../github/publish/process/test_auto_merge.py | 105 +++--------------- .../publish/process/test_publish_check.py | 1 - .../remove/process/test_remove_auto_merge.py | 101 ++--------------- 13 files changed, 138 insertions(+), 342 deletions(-) diff --git a/src/plugins/github/models/git.py b/src/plugins/github/models/git.py index 22cb8a5d..dd2815bb 100644 --- a/src/plugins/github/models/git.py +++ b/src/plugins/github/models/git.py @@ -7,6 +7,17 @@ class GitHandler(BaseModel): """Git 操作""" + def checkout_branch(self, branch_name: str): + """检出分支""" + + run_shell_command(["git", "checkout", branch_name]) + + def checkout_remote_branch(self, branch_name: str): + """检出远程分支""" + + run_shell_command(["git", "fetch", "origin", branch_name]) + run_shell_command(["git", "checkout", branch_name]) + def commit_and_push(self, message: str, branch_name: str, author: str): """提交并推送""" @@ -36,3 +47,8 @@ def delete_origin_branch(self, branch_name: str): """删除远程分支""" run_shell_command(["git", "push", "origin", "--delete", branch_name]) + + def switch_branch(self, branch_name: str): + """切换分支""" + + run_shell_command(["git", "switch", "-C", branch_name]) diff --git a/src/plugins/github/models/github.py b/src/plugins/github/models/github.py index 39c49d87..04a96371 100644 --- a/src/plugins/github/models/github.py +++ b/src/plugins/github/models/github.py @@ -36,6 +36,7 @@ async def update_issue_content(self, body: str, issue_number: int): async def create_dispatch_event( self, event_type: str, client_payload: dict, repo: RepoInfo | None = None ): + """创建触发事件""" if repo is None: repo = self.repo_info @@ -100,6 +101,20 @@ async def get_pull_requests_by_label(self, label: str) -> list[PullRequestSimple pull for pull in pulls if label in [label.name for label in pull.labels] ] + async def get_pull_request_by_branch(self, branch_name: str) -> PullRequestSimple: + """根据分支的名称获取对应拉取请求""" + pulls = ( + await self.bot.rest.pulls.async_list( + **self.repo_info.model_dump(), + head=f"{self.repo_info.owner}:{branch_name}", + ) + ).parsed_data + + if not pulls: + raise ValueError(f"找不到分支 {branch_name} 对应的拉取请求") + + return pulls[0] + async def get_pull_request(self, pull_number: int): """获取拉取请求""" return ( @@ -109,16 +124,14 @@ async def get_pull_request(self, pull_number: int): ).parsed_data async def draft_pull_request(self, branch_name: str): - """ - 将拉取请求转换为草稿 - """ - pulls = ( - await self.bot.rest.pulls.async_list( - **self.repo_info.model_dump(), - head=f"{self.repo_info.owner}:{branch_name}", - ) - ).parsed_data - if pulls and (pull := pulls[0]) and not pull.draft: + """将拉取请求转换为草稿""" + try: + pull = await self.get_pull_request_by_branch(branch_name) + except ValueError: + logger.info("未找到对应的拉取请求,无需转换") + return + + if not pull.draft: await self.bot.async_graphql( query="""mutation convertPullRequestToDraft($pullRequestId: ID!) { convertPullRequestToDraft(input: {pullRequestId: $pullRequestId}) { @@ -128,6 +141,8 @@ async def draft_pull_request(self, branch_name: str): variables={"pullRequestId": pull.node_id}, ) logger.info("没通过检查,已将之前的拉取请求转换为草稿") + else: + logger.info("拉取请求已为草稿状态,无需转换") async def merge_pull_request( self, @@ -142,44 +157,22 @@ async def merge_pull_request( ) logger.info(f"拉取请求 #{pull_number} 已合并") - async def get_pull_request_by_branch(self, branch_name: str) -> PullRequestSimple: - """根据分支的名称获取对应的拉取请求实例""" - return ( - await self.bot.rest.pulls.async_list( - **self.repo_info.model_dump(), - head=f"{self.repo_info.owner}:{branch_name}", - ) - ).parsed_data[0] - async def update_pull_request_status(self, title: str, branch_name: str): """拉取请求若为草稿状态则标记为可评审,若标题不符则修改标题""" pull = await self.get_pull_request_by_branch(branch_name) if pull.title != title: - await self.bot.rest.pulls.async_update( - **self.repo_info.model_dump(), pull_number=pull.number, title=title - ) - logger.info(f"拉取请求标题已修改为 {title}") + await self.update_pull_request_title(title, pull.number) if pull.draft: - await self.bot.async_graphql( - query="""mutation markPullRequestReadyForReview($pullRequestId: ID!) { - markPullRequestReadyForReview(input: {pullRequestId: $pullRequestId}) { - clientMutationId - } - }""", - variables={"pullRequestId": pull.node_id}, - ) - logger.info("拉取请求已标记为可评审") + await self.ready_pull_request(pull.node_id) async def create_pull_request( self, base_branch: str, title: str, branch_name: str, - label: str | list[str], body: str = "", ) -> int: - """创建拉取请求并分配标签,若存在请求会导致 raise RequestFailed""" - + """创建拉取请求并分配标签,若当前分支已存在对应拉去请求,会报错 RequestFailed""" resp = await self.bot.rest.pulls.async_create( **self.repo_info.model_dump(), title=title, @@ -189,16 +182,21 @@ async def create_pull_request( ) pull = resp.parsed_data - # 自动给拉取请求添加标签 + logger.info("拉取请求创建完毕") + return pull.number + + async def add_labels(self, issue_number: int, labels: str | list[str]): + """添加标签""" + labels = [labels] if isinstance(labels, str) else labels + await self.bot.rest.issues.async_add_labels( **self.repo_info.model_dump(), - issue_number=pull.number, - labels=[label] if isinstance(label, str) else label, + issue_number=issue_number, + labels=labels, ) - logger.info("拉取请求创建完毕") - return pull.number + logger.info(f"标签 {labels} 已添加") - async def ready_pull_request(self, node_id: int): + async def ready_pull_request(self, node_id: str): """将拉取请求标记为可评审""" await self.bot.async_graphql( query="""mutation markPullRequestReadyForReview($pullRequestId: ID!) { @@ -210,20 +208,12 @@ async def ready_pull_request(self, node_id: int): ) logger.info("拉取请求已标记为可评审") - async def update_pull_request_title(self, title: str, branch_name: int): + async def update_pull_request_title(self, title: str, pull_number: int) -> None: """修改拉取请求标题""" - pull = ( - await self.bot.rest.pulls.async_list( - **self.repo_info.model_dump(), - head=f"{self.repo_info.owner}:{branch_name}", - ) - ).parsed_data[0] - - if pull.title != title: - await self.bot.rest.pulls.async_update( - **self.repo_info.model_dump(), pull_number=pull.number, title=title - ) - logger.info(f"拉取请求标题已修改为 {title}") + await self.bot.rest.pulls.async_update( + **self.repo_info.model_dump(), pull_number=pull_number, title=title + ) + logger.info(f"拉取请求标题已修改为 {title}") async def get_user_name(self, account_id: int): """根据用户 ID 获取用户名""" diff --git a/src/plugins/github/models/issue.py b/src/plugins/github/models/issue.py index fa6e933c..aae5ad84 100644 --- a/src/plugins/github/models/issue.py +++ b/src/plugins/github/models/issue.py @@ -77,15 +77,12 @@ async def create_pull_request( base_branch: str, title: str, branch_name: str, - label: str | list[str], body: str = "", ): if not body: body = f"resolve #{self.issue_number}" - return await super().create_pull_request( - base_branch, title, branch_name, label, body - ) + return await super().create_pull_request(base_branch, title, branch_name, body) async def should_skip_test(self) -> bool: """判断评论是否包含跳过的标记""" diff --git a/src/plugins/github/plugins/config/__init__.py b/src/plugins/github/plugins/config/__init__.py index 351d5857..52400621 100644 --- a/src/plugins/github/plugins/config/__init__.py +++ b/src/plugins/github/plugins/config/__init__.py @@ -12,16 +12,15 @@ from src.plugins.github.constants import CONFIG_LABEL, TITLE_MAX_LENGTH from src.plugins.github.depends import ( - RepoInfo, bypass_git, + get_github_handler, get_installation_id, get_issue_handler, - get_repo_info, get_type_by_labels_name, - install_pre_commit_hooks, is_bot_triggered_workflow, ) from src.plugins.github.models import IssueHandler +from src.plugins.github.models.github import GithubHandler from src.plugins.github.plugins.publish.render import render_comment from src.plugins.github.plugins.publish.utils import ( ensure_issue_plugin_test_button, @@ -29,7 +28,6 @@ ) from src.plugins.github.plugins.remove.depends import check_labels from src.plugins.github.typing import IssuesEvent -from src.plugins.github.utils import run_shell_command from src.providers.validation.models import PublishType from .constants import BRANCH_NAME_PREFIX, COMMIT_MESSAGE_PREFIX, RESULTS_BRANCH @@ -80,8 +78,7 @@ async def handle_remove_check( await ensure_issue_plugin_test_button_in_progress(handler) # 需要先切换到结果分支 - run_shell_command(["git", "fetch", "origin", RESULTS_BRANCH]) - run_shell_command(["git", "checkout", RESULTS_BRANCH]) + handler.checkout_remote_branch(RESULTS_BRANCH) # 检查是否满足发布要求 # 仅在通过检查的情况下创建拉取请求 @@ -103,16 +100,19 @@ async def handle_remove_check( commit_message = f"{COMMIT_MESSAGE_PREFIX} {result.type.value.lower()} {result.name} (#{handler.issue_number})" # 创建新分支 - run_shell_command(["git", "switch", "-C", branch_name]) + handler.switch_branch(branch_name) # 更新文件 update_file(result) handler.commit_and_push(commit_message, branch_name, handler.author) # 创建拉取请求 try: - await handler.create_pull_request( + pull_number = await handler.create_pull_request( RESULTS_BRANCH, title, branch_name, + ) + await handler.add_labels( + pull_number, [result.type.value, CONFIG_LABEL], ) except RequestFailed: @@ -146,21 +146,18 @@ async def review_submitted_rule( auto_merge_matcher = on_type(PullRequestReviewSubmitted, rule=review_submitted_rule) -@auto_merge_matcher.handle( - parameterless=[Depends(bypass_git), Depends(install_pre_commit_hooks)] -) +@auto_merge_matcher.handle(parameterless=[Depends(bypass_git)]) async def handle_auto_merge( bot: GitHubBot, event: PullRequestReviewSubmitted, installation_id: int = Depends(get_installation_id), - repo_info: RepoInfo = Depends(get_repo_info), + handler: GithubHandler = Depends(get_github_handler), ) -> None: async with bot.as_installation(installation_id): + pull_number = event.payload.pull_request.number + # 如果有冲突的话,不会触发 Github Actions # 所以直接合并即可 - await bot.rest.pulls.async_merge( - **repo_info.model_dump(), - pull_number=event.payload.pull_request.number, - merge_method="rebase", - ) + await handler.merge_pull_request(pull_number, "rebase") + logger.info(f"已自动合并 #{event.payload.pull_request.number}") diff --git a/src/plugins/github/plugins/publish/__init__.py b/src/plugins/github/plugins/publish/__init__.py index 9f38896f..ce6b4723 100644 --- a/src/plugins/github/plugins/publish/__init__.py +++ b/src/plugins/github/plugins/publish/__init__.py @@ -28,11 +28,10 @@ get_labels_name, get_related_issue_handler, get_related_issue_number, - get_repo_info, install_pre_commit_hooks, is_bot_triggered_workflow, ) -from src.plugins.github.models import GithubHandler, IssueHandler, RepoInfo +from src.plugins.github.models import GithubHandler, IssueHandler from src.providers.validation.models import PublishType, ValidationDict from .depends import ( @@ -44,7 +43,6 @@ ensure_issue_plugin_test_button, ensure_issue_plugin_test_button_in_progress, process_pull_request, - resolve_conflict_pull_requests, trigger_registry_update, ) from .validation import ( @@ -126,7 +124,6 @@ async def handle_publish_plugin_check( # 确保插件重测按钮存在 await ensure_issue_plugin_test_button(handler) - state["handler"] = handler state["validation"] = result @@ -149,7 +146,6 @@ async def handle_adapter_publish_check( # 仅在通过检查的情况下创建拉取请求 result = await validate_adapter_info_from_issue(handler.issue) - state["handler"] = handler state["validation"] = result @@ -264,30 +260,16 @@ async def review_submitted_rule( ) -@auto_merge_matcher.handle( - parameterless=[Depends(bypass_git), Depends(install_pre_commit_hooks)] -) +@auto_merge_matcher.handle(parameterless=[Depends(bypass_git)]) async def handle_auto_merge( bot: GitHubBot, event: PullRequestReviewSubmitted, installation_id: int = Depends(get_installation_id), - repo_info: RepoInfo = Depends(get_repo_info), handler: GithubHandler = Depends(get_github_handler), ) -> None: async with bot.as_installation(installation_id): - pull_request = ( - await bot.rest.pulls.async_get( - **repo_info.model_dump(), pull_number=event.payload.pull_request.number - ) - ).parsed_data - - if not pull_request.mergeable: - # 尝试处理冲突 - await resolve_conflict_pull_requests(handler, [pull_request]) - - await bot.rest.pulls.async_merge( - **repo_info.model_dump(), - pull_number=event.payload.pull_request.number, - merge_method="rebase", - ) - logger.info(f"已自动合并 #{event.payload.pull_request.number}") + pull_number = event.payload.pull_request.number + + await handler.merge_pull_request(pull_number, "rebase") + + logger.info(f"已自动合并 #{pull_number}") diff --git a/src/plugins/github/plugins/publish/utils.py b/src/plugins/github/plugins/publish/utils.py index 96d20a9e..12bbecd0 100644 --- a/src/plugins/github/plugins/publish/utils.py +++ b/src/plugins/github/plugins/publish/utils.py @@ -9,7 +9,6 @@ from src.plugins.github.models import GithubHandler, IssueHandler from src.plugins.github.typing import PullRequestList from src.plugins.github.utils import commit_message as _commit_message -from src.plugins.github.utils import run_shell_command from src.providers.models import RegistryUpdatePayload, to_store from src.providers.utils import dump_json5, load_json_from_file from src.providers.validation import PublishType, ValidationDict @@ -114,9 +113,9 @@ async def resolve_conflict_pull_requests( continue # 每次切换前都要确保回到主分支 - run_shell_command(["git", "checkout", plugin_config.input_config.base]) + handler.checkout_branch(plugin_config.input_config.base) # 切换到对应分支 - run_shell_command(["git", "switch", "-C", pull.head.ref]) + handler.switch_branch(pull.head.ref) # 更新文件 update_file(result) @@ -205,15 +204,18 @@ async def process_pull_request( if result.valid: commit_message = f"{COMMIT_MESSAGE_PREFIX} {result.type.value.lower()} {result.name} (#{handler.issue_number})" - run_shell_command(["git", "switch", "-C", branch_name]) + handler.switch_branch(branch_name) # 更新文件 update_file(result) handler.commit_and_push(commit_message, branch_name, handler.author) # 创建拉取请求 try: - await handler.create_pull_request( - plugin_config.input_config.base, title, branch_name, result.type.value + pull_number = await handler.create_pull_request( + plugin_config.input_config.base, + title, + branch_name, ) + await handler.add_labels(pull_number, result.type.value) except RequestFailed: # 如果之前已经创建了拉取请求,则将其转换为草稿 logger.info("该分支的拉取请求已创建,请前往查看") diff --git a/src/plugins/github/plugins/remove/__init__.py b/src/plugins/github/plugins/remove/__init__.py index 971a879c..47397066 100644 --- a/src/plugins/github/plugins/remove/__init__.py +++ b/src/plugins/github/plugins/remove/__init__.py @@ -13,13 +13,11 @@ from src.plugins.github import plugin_config from src.plugins.github.constants import TITLE_MAX_LENGTH from src.plugins.github.depends import ( - RepoInfo, bypass_git, get_github_handler, get_installation_id, get_issue_handler, get_related_issue_number, - get_repo_info, get_type_by_labels_name, install_pre_commit_hooks, is_bot_triggered_workflow, @@ -32,7 +30,7 @@ from .constants import BRANCH_NAME_PREFIX, REMOVE_LABEL from .depends import check_labels from .render import render_comment, render_error -from .utils import process_pull_reqeusts, resolve_conflict_pull_requests +from .utils import process_pull_reqeusts from .validation import validate_author_info @@ -113,13 +111,13 @@ async def handle_remove_check( pull_number = ( await store_handler.get_pull_request_by_branch(branch_name) ).number + # 评论议题 - await handler.comment_issue( - await render_comment( - result, - pr_url=f"{plugin_config.input_config.store_repository}#{pull_number}", - ) + comment = await render_comment( + result, + f"{plugin_config.input_config.store_repository}#{pull_number}", ) + await handler.comment_issue(comment) async def review_submitted_rule( @@ -142,30 +140,16 @@ async def review_submitted_rule( auto_merge_matcher = on_type(PullRequestReviewSubmitted, rule=review_submitted_rule) -@auto_merge_matcher.handle( - parameterless=[Depends(bypass_git), Depends(install_pre_commit_hooks)] -) +@auto_merge_matcher.handle(parameterless=[Depends(bypass_git)]) async def handle_auto_merge( bot: GitHubBot, event: PullRequestReviewSubmitted, installation_id: int = Depends(get_installation_id), - repo_info: RepoInfo = Depends(get_repo_info), handler: GithubHandler = Depends(get_github_handler), ) -> None: async with bot.as_installation(installation_id): - pull_request = ( - await bot.rest.pulls.async_get( - **repo_info.model_dump(), pull_number=event.payload.pull_request.number - ) - ).parsed_data - - if not pull_request.mergeable: - # 尝试处理冲突 - await resolve_conflict_pull_requests(handler, [pull_request]) - - await bot.rest.pulls.async_merge( - **repo_info.model_dump(), - pull_number=event.payload.pull_request.number, - merge_method="rebase", - ) - logger.info(f"已自动合并 #{event.payload.pull_request.number}") + pull_number = event.payload.pull_request.number + + await handler.merge_pull_request(pull_number, "rebase") + + logger.info(f"已自动合并 #{pull_number}") diff --git a/src/plugins/github/plugins/remove/utils.py b/src/plugins/github/plugins/remove/utils.py index 252d296e..7c65b7e8 100644 --- a/src/plugins/github/plugins/remove/utils.py +++ b/src/plugins/github/plugins/remove/utils.py @@ -9,7 +9,7 @@ ) from src.plugins.github.models import GithubHandler, IssueHandler from src.plugins.github.typing import PullRequestList -from src.plugins.github.utils import commit_message, run_shell_command +from src.plugins.github.utils import commit_message from src.providers.utils import dump_json5 from src.providers.validation.models import PublishType @@ -51,7 +51,7 @@ async def process_pull_reqeusts( message = commit_message(COMMIT_MESSAGE_PREFIX, result.name, handler.issue_number) # 切换分支 - run_shell_command(["git", "switch", "-C", branch_name]) + handler.switch_branch(branch_name) # 更新文件并提交更改 update_file(result) store_handler.commit_and_push(message, branch_name, author=handler.author) @@ -59,13 +59,15 @@ async def process_pull_reqeusts( logger.info("开始创建拉取请求") try: - await store_handler.create_pull_request( + pull_number = await store_handler.create_pull_request( plugin_config.input_config.base, title, branch_name, - [REMOVE_LABEL, result.publish_type.value], body=f"resolve {handler.repo_info}#{handler.issue_number}", ) + await store_handler.add_labels( + pull_number, [REMOVE_LABEL, result.publish_type.value] + ) except RequestFailed: # 如果之前已经创建了拉取请求,则将其转换为草稿 logger.info("该分支的拉取请求已创建,请前往查看") @@ -104,9 +106,9 @@ async def resolve_conflict_pull_requests( continue # 每次切换前都要确保回到主分支 - run_shell_command(["git", "checkout", plugin_config.input_config.base]) + handler.checkout_branch(plugin_config.input_config.base) # 切换到对应分支 - run_shell_command(["git", "switch", "-C", pull.head.ref]) + handler.switch_branch(pull.head.ref) # 更新文件 update_file(result) diff --git a/src/plugins/github/plugins/resolve/__init__.py b/src/plugins/github/plugins/resolve/__init__.py index 02ac9b89..1e80ef11 100644 --- a/src/plugins/github/plugins/resolve/__init__.py +++ b/src/plugins/github/plugins/resolve/__init__.py @@ -15,10 +15,10 @@ is_remove_by_pull_request_labels, ) from src.plugins.github.models import GithubHandler, IssueHandler -from src.plugins.github.plugins.publish import ( +from src.plugins.github.plugins.publish.utils import ( resolve_conflict_pull_requests as resolve_conflict_publish_pull_requests, ) -from src.plugins.github.plugins.remove import ( +from src.plugins.github.plugins.remove.utils import ( resolve_conflict_pull_requests as resolve_conflict_remove_pull_requests, ) from src.providers.validation.models import PublishType diff --git a/tests/github/config/process/test_config_auto_merge.py b/tests/github/config/process/test_config_auto_merge.py index 52999a22..30a2063c 100644 --- a/tests/github/config/process/test_config_auto_merge.py +++ b/tests/github/config/process/test_config_auto_merge.py @@ -43,8 +43,6 @@ async def test_config_auto_merge( event = get_mock_event(PullRequestReviewSubmitted) event.payload.pull_request.labels = get_issue_labels(["Config", "Plugin"]) - ctx.receive_event(bot, event) - ctx.should_pass_rule(auto_merge_matcher) ctx.should_call_api( "rest.apps.async_get_repo_installation", {"owner": "he0119", "repo": "action-test"}, @@ -61,6 +59,9 @@ async def test_config_auto_merge( True, ) + ctx.receive_event(bot, event) + ctx.should_pass_rule(auto_merge_matcher) + # 测试 git 命令 mock_subprocess_run.assert_has_calls( [ @@ -68,13 +69,8 @@ async def test_config_auto_merge( ["git", "config", "--global", "safe.directory", "*"], check=True, capture_output=True, - ), - mocker.call( - ["pre-commit", "install", "--install-hooks"], - check=True, - capture_output=True, - ), - ], # type: ignore + ), # type: ignore + ], any_order=True, ) @@ -87,20 +83,17 @@ async def test_auto_merge_not_remove(app: App, mocker: MockerFixture) -> None: from src.plugins.github.plugins.config import auto_merge_matcher mock_subprocess_run = mocker.patch("subprocess.run") - mock_resolve_conflict_pull_requests = mocker.patch( - "src.plugins.github.plugins.remove.resolve_conflict_pull_requests" - ) async with app.test_matcher() as ctx: adapter, bot = get_github_bot(ctx) event = get_mock_event(PullRequestReviewSubmitted) event.payload.pull_request.labels = [] + ctx.receive_event(bot, event) ctx.should_not_pass_rule(auto_merge_matcher) # 测试 git 命令 mock_subprocess_run.assert_not_called() - mock_resolve_conflict_pull_requests.assert_not_called() async def test_auto_merge_not_member(app: App, mocker: MockerFixture) -> None: diff --git a/tests/github/publish/process/test_auto_merge.py b/tests/github/publish/process/test_auto_merge.py index 3d6f5e3e..e7051a5b 100644 --- a/tests/github/publish/process/test_auto_merge.py +++ b/tests/github/publish/process/test_auto_merge.py @@ -11,75 +11,12 @@ async def test_auto_merge(app: App, mocker: MockerFixture, mock_installation) -> 可直接合并的情况 """ - mock_subprocess_run = mocker.patch("subprocess.run") - - mock_pull = mocker.MagicMock() - mock_pull.mergeable = True - mock_pull_resp = mocker.MagicMock() - mock_pull_resp.parsed_data = mock_pull - - async with app.test_matcher() as ctx: - adapter, bot = get_github_bot(ctx) - event = get_mock_event(PullRequestReviewSubmitted) - - ctx.should_call_api( - "rest.apps.async_get_repo_installation", - {"owner": "he0119", "repo": "action-test"}, - mock_installation, - ) - ctx.should_call_api( - "rest.pulls.async_get", - {"owner": "he0119", "repo": "action-test", "pull_number": 100}, - mock_pull_resp, - ) - ctx.should_call_api( - "rest.pulls.async_merge", - { - "owner": "he0119", - "repo": "action-test", - "pull_number": 100, - "merge_method": "rebase", - }, - True, - ) - - ctx.receive_event(bot, event) - - # 测试 git 命令 - mock_subprocess_run.assert_has_calls( - [ - mocker.call( - ["git", "config", "--global", "safe.directory", "*"], - check=True, - capture_output=True, - ), - mocker.call( - ["pre-commit", "install", "--install-hooks"], - check=True, - capture_output=True, - ), - ], # type: ignore - any_order=True, - ) - - -async def test_auto_merge_need_rebase( - app: App, mocker: MockerFixture, mock_installation -) -> None: - """测试审查后自动合并 - - 需要 rebase 的情况 - """ - from src.plugins.github.models import GithubHandler, RepoInfo + from src.plugins.github.plugins.publish import auto_merge_matcher mock_subprocess_run = mocker.patch("subprocess.run") - mock_resolve_conflict_pull_requests = mocker.patch( - "src.plugins.github.plugins.publish.resolve_conflict_pull_requests" - ) mock_pull = mocker.MagicMock() - mock_pull.mergeable = False - mock_pull.head.ref = "publish/issue1" + mock_pull.mergeable = True mock_pull_resp = mocker.MagicMock() mock_pull_resp.parsed_data = mock_pull @@ -92,12 +29,6 @@ async def test_auto_merge_need_rebase( {"owner": "he0119", "repo": "action-test"}, mock_installation, ) - ctx.should_call_api( - "rest.pulls.async_get", - {"owner": "he0119", "repo": "action-test", "pull_number": 100}, - mock_pull_resp, - ) - ctx.should_call_api( "rest.pulls.async_merge", { @@ -110,6 +41,7 @@ async def test_auto_merge_need_rebase( ) ctx.receive_event(bot, event) + ctx.should_pass_rule(auto_merge_matcher) # 测试 git 命令 mock_subprocess_run.assert_has_calls( @@ -119,18 +51,9 @@ async def test_auto_merge_need_rebase( check=True, capture_output=True, ), # type: ignore - mocker.call( - ["pre-commit", "install", "--install-hooks"], - check=True, - capture_output=True, - ), # type: ignore ], any_order=True, ) - mock_resolve_conflict_pull_requests.assert_called_once_with( - GithubHandler(bot=bot, repo_info=RepoInfo(owner="he0119", repo="action-test")), - [mock_pull], - ) async def test_auto_merge_not_publish(app: App, mocker: MockerFixture) -> None: @@ -138,10 +61,9 @@ async def test_auto_merge_not_publish(app: App, mocker: MockerFixture) -> None: 和发布无关 """ + from src.plugins.github.plugins.publish import auto_merge_matcher + mock_subprocess_run = mocker.patch("subprocess.run") - mock_resolve_conflict_pull_requests = mocker.patch( - "src.plugins.github.plugins.publish.resolve_conflict_pull_requests" - ) async with app.test_matcher() as ctx: adapter, bot = get_github_bot(ctx) @@ -149,10 +71,10 @@ async def test_auto_merge_not_publish(app: App, mocker: MockerFixture) -> None: event.payload.pull_request.labels = [] ctx.receive_event(bot, event) + ctx.should_not_pass_rule(auto_merge_matcher) # 测试 git 命令 mock_subprocess_run.assert_not_called() - mock_resolve_conflict_pull_requests.assert_not_called() async def test_auto_merge_not_member(app: App, mocker: MockerFixture) -> None: @@ -160,20 +82,20 @@ async def test_auto_merge_not_member(app: App, mocker: MockerFixture) -> None: 审核者不是仓库成员 """ + from src.plugins.github.plugins.publish import auto_merge_matcher + mock_subprocess_run = mocker.patch("subprocess.run") - mock_resolve_conflict_pull_requests = mocker.patch( - "src.plugins.github.plugins.publish.resolve_conflict_pull_requests" - ) async with app.test_matcher() as ctx: adapter, bot = get_github_bot(ctx) event = get_mock_event(PullRequestReviewSubmitted) event.payload.review.author_association = "CONTRIBUTOR" + ctx.receive_event(bot, event) + ctx.should_not_pass_rule(auto_merge_matcher) # 测试 git 命令 mock_subprocess_run.assert_not_called() - mock_resolve_conflict_pull_requests.assert_not_called() async def test_auto_merge_not_approve(app: App, mocker: MockerFixture) -> None: @@ -181,10 +103,9 @@ async def test_auto_merge_not_approve(app: App, mocker: MockerFixture) -> None: 审核未通过 """ + from src.plugins.github.plugins.publish import auto_merge_matcher + mock_subprocess_run = mocker.patch("subprocess.run") - mock_resolve_conflict_pull_requests = mocker.patch( - "src.plugins.github.plugins.publish.resolve_conflict_pull_requests" - ) async with app.test_matcher() as ctx: adapter, bot = get_github_bot(ctx) @@ -192,7 +113,7 @@ async def test_auto_merge_not_approve(app: App, mocker: MockerFixture) -> None: event.payload.review.state = "commented" ctx.receive_event(bot, event) + ctx.should_not_pass_rule(auto_merge_matcher) # 测试 git 命令 mock_subprocess_run.assert_not_called() - mock_resolve_conflict_pull_requests.assert_not_called() diff --git a/tests/github/publish/process/test_publish_check.py b/tests/github/publish/process/test_publish_check.py index 8a55da2a..3c8f3445 100644 --- a/tests/github/publish/process/test_publish_check.py +++ b/tests/github/publish/process/test_publish_check.py @@ -711,7 +711,6 @@ async def test_edit_title_too_long( }, True, ) - ctx.should_call_api( "rest.issues.async_list_comments", {"owner": "he0119", "repo": "action-test", "issue_number": 80}, diff --git a/tests/github/remove/process/test_remove_auto_merge.py b/tests/github/remove/process/test_remove_auto_merge.py index 41516326..ebb614c5 100644 --- a/tests/github/remove/process/test_remove_auto_merge.py +++ b/tests/github/remove/process/test_remove_auto_merge.py @@ -34,6 +34,7 @@ async def test_remove_auto_merge( 可直接合并的情况 """ + from src.plugins.github.plugins.remove import auto_merge_matcher mock_subprocess_run = mocker.patch("subprocess.run") @@ -47,17 +48,11 @@ async def test_remove_auto_merge( event = get_mock_event(PullRequestReviewSubmitted) event.payload.pull_request.labels = get_issue_labels(["Remove", "Plugin"]) - ctx.receive_event(bot, event) ctx.should_call_api( "rest.apps.async_get_repo_installation", {"owner": "he0119", "repo": "action-test"}, mock_installation, ) - ctx.should_call_api( - "rest.pulls.async_get", - {"owner": "he0119", "repo": "action-test", "pull_number": 100}, - mock_pull_resp, - ) ctx.should_call_api( "rest.pulls.async_merge", { @@ -69,75 +64,9 @@ async def test_remove_auto_merge( True, ) - # 测试 git 命令 - mock_subprocess_run.assert_has_calls( - [ - mocker.call( - ["git", "config", "--global", "safe.directory", "*"], - check=True, - capture_output=True, - ), - mocker.call( - ["pre-commit", "install", "--install-hooks"], - check=True, - capture_output=True, - ), - ], # type: ignore - any_order=True, - ) - - -async def test_auto_merge_need_rebase( - app: App, mocker: MockerFixture, mock_installation -) -> None: - """测试审查后自动合并 - - 需要 rebase 的情况 - """ - from src.plugins.github.models import GithubHandler, RepoInfo - from src.plugins.github.plugins.remove import auto_merge_matcher - - mock_subprocess_run = mocker.patch("subprocess.run") - mock_resolve_conflict_pull_requests = mocker.patch( - "src.plugins.github.plugins.remove.resolve_conflict_pull_requests" - ) - - mock_pull = mocker.MagicMock() - mock_pull.mergeable = False - mock_pull.head.ref = "remove/issue1" - mock_pull_resp = mocker.MagicMock() - mock_pull_resp.parsed_data = mock_pull - - async with app.test_matcher() as ctx: - adapter, bot = get_github_bot(ctx) - event = get_mock_event(PullRequestReviewSubmitted) - event.payload.pull_request.labels = get_issue_labels(["Remove", "Plugin"]) - ctx.receive_event(bot, event) ctx.should_pass_rule(auto_merge_matcher) - ctx.should_call_api( - "rest.apps.async_get_repo_installation", - {"owner": "he0119", "repo": "action-test"}, - mock_installation, - ) - ctx.should_call_api( - "rest.pulls.async_get", - {"owner": "he0119", "repo": "action-test", "pull_number": 100}, - mock_pull_resp, - ) - - ctx.should_call_api( - "rest.pulls.async_merge", - { - "owner": "he0119", - "repo": "action-test", - "pull_number": 100, - "merge_method": "rebase", - }, - True, - ) - # 测试 git 命令 mock_subprocess_run.assert_has_calls( [ @@ -145,19 +74,10 @@ async def test_auto_merge_need_rebase( ["git", "config", "--global", "safe.directory", "*"], check=True, capture_output=True, - ), - mocker.call( - ["pre-commit", "install", "--install-hooks"], - check=True, - capture_output=True, ), # type: ignore ], any_order=True, ) - mock_resolve_conflict_pull_requests.assert_called_once_with( - GithubHandler(bot=bot, repo_info=RepoInfo(owner="he0119", repo="action-test")), - [mock_pull], - ) async def test_auto_merge_not_remove(app: App, mocker: MockerFixture) -> None: @@ -168,20 +88,17 @@ async def test_auto_merge_not_remove(app: App, mocker: MockerFixture) -> None: from src.plugins.github.plugins.remove import auto_merge_matcher mock_subprocess_run = mocker.patch("subprocess.run") - mock_resolve_conflict_pull_requests = mocker.patch( - "src.plugins.github.plugins.remove.resolve_conflict_pull_requests" - ) async with app.test_matcher() as ctx: adapter, bot = get_github_bot(ctx) event = get_mock_event(PullRequestReviewSubmitted) event.payload.pull_request.labels = [] + ctx.receive_event(bot, event) ctx.should_not_pass_rule(auto_merge_matcher) # 测试 git 命令 mock_subprocess_run.assert_not_called() - mock_resolve_conflict_pull_requests.assert_not_called() async def test_auto_merge_not_member(app: App, mocker: MockerFixture) -> None: @@ -189,10 +106,9 @@ async def test_auto_merge_not_member(app: App, mocker: MockerFixture) -> None: 审核者不是仓库成员 """ + from src.plugins.github.plugins.remove import auto_merge_matcher + mock_subprocess_run = mocker.patch("subprocess.run") - mock_resolve_conflict_pull_requests = mocker.patch( - "src.plugins.github.plugins.remove.resolve_conflict_pull_requests" - ) async with app.test_matcher() as ctx: adapter, bot = get_github_bot(ctx) @@ -201,10 +117,10 @@ async def test_auto_merge_not_member(app: App, mocker: MockerFixture) -> None: event.payload.pull_request.labels = get_issue_labels(["Remove", "Plugin"]) ctx.receive_event(bot, event) + ctx.should_not_pass_rule(auto_merge_matcher) # 测试 git 命令 mock_subprocess_run.assert_not_called() - mock_resolve_conflict_pull_requests.assert_not_called() async def test_auto_merge_not_approve(app: App, mocker: MockerFixture) -> None: @@ -212,11 +128,9 @@ async def test_auto_merge_not_approve(app: App, mocker: MockerFixture) -> None: 审核未通过 """ + from src.plugins.github.plugins.remove import auto_merge_matcher mock_subprocess_run = mocker.patch("subprocess.run") - mock_resolve_conflict_pull_requests = mocker.patch( - "src.plugins.github.plugins.remove.resolve_conflict_pull_requests" - ) async with app.test_matcher() as ctx: adapter, bot = get_github_bot(ctx) @@ -225,8 +139,7 @@ async def test_auto_merge_not_approve(app: App, mocker: MockerFixture) -> None: event.payload.review.state = "commented" ctx.receive_event(bot, event) + ctx.should_not_pass_rule(auto_merge_matcher) # 测试 git 命令 - mock_subprocess_run.assert_not_called() - mock_resolve_conflict_pull_requests.assert_not_called()