[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(