From 4b61f300c04ddfed4d2188b06b273085518a1960 Mon Sep 17 00:00:00 2001 From: "Kevin H. Luu" Date: Wed, 14 Oct 2026 15:26:15 -0700 Subject: [PATCH] [CI] Fix /ci run reporting a failed merge on fork PRs (#61684) Signed-off-by: khluu --- .github/workflows/scripts/run_ci_command.py | 16 +++++++++++++--- .../workflows/scripts/test_run_ci_command.py | 18 ++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/.github/workflows/scripts/run_ci_command.py b/.github/workflows/scripts/run_ci_command.py index b6ef1c3ae8..142249476d 100644 --- a/.github/workflows/scripts/run_ci_command.py +++ b/.github/workflows/scripts/run_ci_command.py @@ -861,14 +861,24 @@ def merge_base_into_pr( for _ in range(BRANCH_UPDATE_POLL_ATTEMPTS): time.sleep(BRANCH_UPDATE_POLL_SECONDS) current_pr = github.get_pr(pr["number"]) - if current_pr["head"]["sha"] != pr["head"]["sha"]: - break + if current_pr["head"]["sha"] == pr["head"]["sha"]: + continue + try: + behind = github.get_commits_behind_base( + base_ref, current_pr["head"]["sha"] + ) + except ApiError as error: + # A fork's new head is briefly unknown to the base repository. + if error.status == 404: + continue + raise + break else: raise merge_failed("the merge commit did not appear in time") if ( current_pr["state"] != "open" or current_pr["base"]["ref"] != base_ref - or github.get_commits_behind_base(base_ref, current_pr["head"]["sha"]) + or behind ): raise merge_failed("the PR changed during the merge") except ApiError as error: diff --git a/.github/workflows/scripts/test_run_ci_command.py b/.github/workflows/scripts/test_run_ci_command.py index 2061ff895e..220af20e8b 100644 --- a/.github/workflows/scripts/test_run_ci_command.py +++ b/.github/workflows/scripts/test_run_ci_command.py @@ -677,6 +677,24 @@ class RunCiCommandTest(unittest.TestCase): self.assertIn("CI already ran on this commit", github.comments[0]) self.assertIn("`/ci retry`", github.comments[0]) + def test_run_waits_for_fork_merge_commit_to_reach_base_repo(self) -> None: + github = FakeGitHub(behind=5) + updater = FakeBranchUpdater(github) + buildkite = FakeBuildkite([[], []]) + + with ( + patch("run_ci_command.time.sleep"), + patch.object( + github, + "get_commits_behind_base", + side_effect=[5, ApiError(404, "Not Found"), 0], + ), + ): + run(make_event(COMMAND_RUN_CI), github, buildkite, "", updater) + + self.assertEqual(buildkite.created_builds[0]["commit"], "merge-commit-sha") + self.assertTrue(github.comments[0].startswith("✅ ")) + def test_run_reports_failed_merge_without_building(self) -> None: github = FakeGitHub(behind=5) updater = FakeBranchUpdater(github, error=ApiError(422, "merge conflict"))