diff --git a/ci_scripts/mark-pr-ready.py b/ci_scripts/mark-pr-ready.py index 2fbee7f32682..8d44747379e6 100755 --- a/ci_scripts/mark-pr-ready.py +++ b/ci_scripts/mark-pr-ready.py @@ -37,13 +37,14 @@ from dataclasses import dataclass import requests -from github import Auth, Github +from github import Auth, Github, GithubException from github.PullRequest import PullRequest from github.Repository import Repository from github.WorkflowRun import WorkflowRun REPOSITORY = "riseproject-dev/python-wheels" PASSING_CONCLUSIONS = {"success", "skipped"} +MERGE_REJECTED_STATUSES = {405, 409, 422} def convert_to_draft(token: str, pr: PullRequest) -> None: @@ -127,9 +128,22 @@ def sync_pull_request( if merge: actions.append("squash merge") if not dry_run: - result = pr.merge(merge_method="squash", sha=pr.head.sha) - if not result.merged: - actions[-1] = f"merge rejected: {result.message}" + try: + result = pr.merge(merge_method="squash", sha=pr.head.sha) + except GithubException as exc: + # GitHub answers 405 when the PR cannot be merged (e.g. merge + # conflicts), 409 when its head moved since we looked, and + # 422 for other validation failures. These affect only this + # PR, so report them and carry on with the rest. + if exc.status not in MERGE_REJECTED_STATUSES: + raise + message = ( + exc.data.get("message") if isinstance(exc.data, dict) else None + ) + actions[-1] = f"merge rejected: {message or exc.status}" + else: + if not result.merged: + actions[-1] = f"merge rejected: {result.message}" elif not pr.draft: actions.append("convert to draft") if not dry_run: