From 9b97794be6a0e127e8d7e093eb24c1328c3e6413 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 23 Oct 2026 14:25:13 +0000 Subject: [PATCH] mark-pr-ready: keep going when a PR cannot be merged pr.merge() raises on merge conflicts (405), a moved head (409) or other validation failures (422), which aborted the whole run and left every remaining PR unprocessed. Report the rejection and continue. Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01WLrKmVNbTh8QfP71a78k8b --- ci_scripts/mark-pr-ready.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) 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: