[CI] Use PR head label for Buildkite branch to avoid main collision (#54895)

Signed-off-by: khluu <khluu000@gmail.com>

Kevin H. Luu committed Sep 1, 2026 at 23:09 UTC 3976eada8bf6cc9c84963d2350703df835733c89
2 files changed +61 -30
.github/workflows/scripts/run_ci_command.py
+9 -5
@@ -606,7 +606,10 @@ def create_build_payload(
606 }
607 return {
608 "commit": pr["head"]["sha"],
609 - "branch": pr["head"]["ref"],
609 + # Use the head label (owner:branch) rather than the bare ref so a PR
610 + # whose fork branch is named e.g. "main" does not collide with the
611 + # upstream branch of the same name.
612 + "branch": pr["head"].get("label") or pr["head"]["ref"],
613 "message": f"PR #{pr['number']} {command} by @{actor}",
614 "pull_request_id": pr["number"],
615 "pull_request_base_branch": pr["base"]["ref"],
@@ -969,12 +972,13 @@ def handle_cancel_ci(
972 ) -> str:
973 ci_name = ci_name_for_command(command)
974 branch = pr["head"]["ref"]
975 + # Builds are created under the head label (owner:branch); also match the
976 + # bare ref so builds created before that change can still be cancelled.
977 branches = [branch]
978 + head_label = pr["head"].get("label")
979 + if head_label and head_label not in branches:
980 + branches.insert(0, str(head_label))
981 states = CANCELABLE_BUILD_STATES
974 - if command in AMD_CI_COMMANDS:
975 - head_label = pr["head"].get("label")
976 - if head_label and head_label not in branches:
977 - branches.append(str(head_label))
982
983 builds_by_number: dict[int, dict[str, Any]] = {}
984 for candidate_branch in branches:
.github/workflows/scripts/test_run_ci_command.py
+52 -25
@@ -45,6 +45,7 @@ def make_pr(**overrides: Any) -> dict[str, Any]:
45 "base": {"ref": "main"},
46 "draft": False,
47 "head": {
48 + "label": "contributor:feature",
49 "ref": "feature",
50 "repo": {"clone_url": "https://github.com/contributor/vllm.git"},
51 "sha": "0123456789abcdef",
@@ -479,7 +480,7 @@ class RunCiCommandTest(unittest.TestCase):
480 payload,
481 {
482 "commit": "0123456789abcdef",
482 - "branch": "feature",
483 + "branch": "contributor:feature",
484 "message": "PR #42 /ci run by @reviewer",
485 "pull_request_id": 42,
486 "pull_request_base_branch": "main",
@@ -498,6 +499,23 @@ class RunCiCommandTest(unittest.TestCase):
499 },
500 )
501
502 + def test_build_payload_uses_head_label_to_avoid_branch_collision(self) -> None:
503 + pr = make_pr()
504 + pr["head"]["ref"] = "main"
505 + pr["head"]["label"] = "contributor:main"
506 +
507 + payload = create_build_payload(actor="reviewer", comment_id=99, pr=pr)
508 +
509 + self.assertEqual(payload["branch"], "contributor:main")
510 +
511 + def test_build_payload_falls_back_to_ref_without_label(self) -> None:
512 + pr = make_pr()
513 + del pr["head"]["label"]
514 +
515 + payload = create_build_payload(actor="reviewer", comment_id=99, pr=pr)
516 +
517 + self.assertEqual(payload["branch"], "feature")
518 +
519 def test_write_reviewer_runs_ci_without_delegation(self) -> None:
520 github = FakeGitHub()
521 buildkite = FakeBuildkite([[], []])
@@ -1039,56 +1057,65 @@ class RunCiCommandTest(unittest.TestCase):
1057 github = FakeGitHub()
1058 buildkite = FakeBuildkite(
1059 [
1060 + # Builds created under the head label (owner:branch).
1061 [
1062 {
1044 - "branch": "feature",
1063 + "branch": "contributor:feature",
1064 "number": 123,
1065 "pull_request": {"id": 42},
1066 "state": "running",
1067 "web_url": "https://buildkite.example/builds/123",
1068 },
1069 {
1051 - "branch": "feature",
1070 + "branch": "contributor:feature",
1071 "number": 124,
1072 "meta_data": {"github-pr-number": "42"},
1073 "state": "failing",
1074 "web_url": "https://buildkite.example/builds/124",
1075 },
1076 {
1058 - "branch": "feature",
1077 + "branch": "contributor:feature",
1078 "number": 125,
1079 "pull_request": {"id": 43},
1080 "state": "running",
1081 "web_url": "https://buildkite.example/builds/125",
1082 },
1083 {
1065 - "branch": "other-branch",
1066 - "number": 126,
1084 + "branch": "contributor:feature",
1085 + "number": 127,
1086 "pull_request": {"id": 42},
1068 - "state": "running",
1069 - "web_url": "https://buildkite.example/builds/126",
1087 + "state": "passed",
1088 + "web_url": "https://buildkite.example/builds/127",
1089 },
1090 + ],
1091 + # Legacy builds created under the bare ref before the label change.
1092 + [
1093 {
1094 "branch": "feature",
1073 - "number": 127,
1095 + "number": 126,
1096 "pull_request": {"id": 42},
1075 - "state": "passed",
1076 - "web_url": "https://buildkite.example/builds/127",
1097 + "state": "running",
1098 + "web_url": "https://buildkite.example/builds/126",
1099 },
1078 - ]
1100 + ],
1101 ]
1102 )
1103
1104 run(make_event(COMMAND_CANCEL_CI), github, buildkite)
1105
1084 - self.assertEqual(buildkite.cancel_calls, [123, 124])
1085 - self.assertIn("Requested cancellation of 2 CI builds", github.comments[0])
1106 + self.assertEqual(buildkite.cancel_calls, [123, 124, 126])
1107 + self.assertEqual(
1108 + [request["branch"] for request in buildkite.list_requests],
1109 + ["contributor:feature", "feature"],
1110 + )
1111 + self.assertIn("Requested cancellation of 3 CI builds", github.comments[0])
1112 self.assertIn("#123", github.comments[0])
1113 self.assertIn("#124", github.comments[0])
1114 + self.assertIn("#126", github.comments[0])
1115
1116 def test_ci_cancel_is_a_noop_without_active_builds(self) -> None:
1117 github = FakeGitHub()
1091 - buildkite = FakeBuildkite([[]])
1118 + buildkite = FakeBuildkite([[], []])
1119
1120 run(make_event(COMMAND_CANCEL_CI), github, buildkite)
1121
@@ -1103,20 +1130,20 @@ class RunCiCommandTest(unittest.TestCase):
1130 [
1131 [
1132 {
1106 - "branch": "feature",
1107 - "number": 321,
1133 + "branch": "contributor:feature",
1134 + "number": 322,
1135 "pull_request": {"id": 42},
1109 - "state": "running",
1110 - "web_url": "https://buildkite.example/amd-ci/builds/321",
1136 + "state": "failing",
1137 + "web_url": "https://buildkite.example/amd-ci/builds/322",
1138 }
1139 ],
1140 [
1141 {
1115 - "branch": "contributor:feature",
1116 - "number": 322,
1142 + "branch": "feature",
1143 + "number": 321,
1144 "pull_request": {"id": 42},
1118 - "state": "failing",
1119 - "web_url": "https://buildkite.example/amd-ci/builds/322",
1145 + "state": "running",
1146 + "web_url": "https://buildkite.example/amd-ci/builds/321",
1147 }
1148 ],
1149 ]
@@ -1124,10 +1151,10 @@ class RunCiCommandTest(unittest.TestCase):
1151
1152 run(make_event(COMMAND_CANCEL_AMD_CI), github, buildkite)
1153
1127 - self.assertEqual(buildkite.cancel_calls, [321, 322])
1154 + self.assertEqual(buildkite.cancel_calls, [322, 321])
1155 self.assertEqual(
1156 [request["branch"] for request in buildkite.list_requests],
1130 - ["feature", "contributor:feature"],
1157 + ["contributor:feature", "feature"],
1158 )
1159 self.assertTrue(
1160 all(