[CI] Accept whitespace around /ci commands and reply instead of going silent (#60925)

Signed-off-by: khluu <khluu000@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kevin H. Luu
2026-10-09 15:43:37 -07:00
committed by GitHub
co-authored by Claude Opus 5.5
parent ed7ae705a1
commit 783ac12071
3 changed files with 82 additions and 19 deletions
+13 -16
View File
@@ -18,22 +18,8 @@ jobs:
if: >-
github.repository_owner == 'vllm-project' &&
github.event.issue.pull_request &&
(github.event.comment.body == '/ci run' ||
github.event.comment.body == '/ci run all' ||
github.event.comment.body == '/ci run nightly' ||
github.event.comment.body == '/ci run --allow-stale' ||
github.event.comment.body == '/ci run all --allow-stale' ||
github.event.comment.body == '/ci run nightly --allow-stale' ||
github.event.comment.body == '/ci retry' ||
github.event.comment.body == '/ci cancel' ||
github.event.comment.body == '/amd-ci run' ||
github.event.comment.body == '/amd-ci run all' ||
github.event.comment.body == '/amd-ci run nightly' ||
github.event.comment.body == '/amd-ci run --allow-stale' ||
github.event.comment.body == '/amd-ci run all --allow-stale' ||
github.event.comment.body == '/amd-ci run nightly --allow-stale' ||
github.event.comment.body == '/amd-ci retry' ||
github.event.comment.body == '/amd-ci cancel')
(startsWith(github.event.comment.body, '/ci') ||
startsWith(github.event.comment.body, '/amd-ci'))
runs-on: [self-hosted, linux, x64, vllm-runners]
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
@@ -54,3 +40,14 @@ jobs:
BUILDKITE_PIPELINE: ci
CI_TRUSTED_USERS: ${{ vars.CI_TRUSTED_USERS }}
GH_TOKEN: ${{ github.token }}
- name: Report failure on the PR
if: failure()
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
await github.rest.issues.createComment({
...context.repo,
issue_number: context.issue.number,
body: `❌ @${context.payload.comment.user.login}, your CI command failed with an unexpected error, so CI may not have started. See the [workflow run](${runUrl}) for details.`,
});
+33 -1
View File
@@ -58,6 +58,7 @@ AMD_CI_COMMANDS = frozenset(
RETRY_COMMANDS = frozenset({COMMAND_RETRY_FAILED, COMMAND_RETRY_AMD_FAILED})
CANCEL_COMMANDS = frozenset({COMMAND_CANCEL_CI, COMMAND_CANCEL_AMD_CI})
ALL_CI_COMMANDS = UPSTREAM_CI_COMMANDS | AMD_CI_COMMANDS
CI_COMMAND_PREFIXES = frozenset({"/ci", "/amd-ci"})
CI_AUTHORIZED_COMMENT_MARKER = "<!-- vllm-ci-authorized -->"
READY_LABELS = {"ready", "ready-run-all-tests"}
TRUSTED_PERMISSIONS = {"admin", "maintain", "write"}
@@ -461,11 +462,17 @@ class BuildkiteClient:
def parse_command(body: str) -> str | None:
body = body.strip()
if body in ALL_CI_COMMANDS:
return body
return None
def is_ci_command_attempt(body: str) -> bool:
words = body.split(maxsplit=1)
return bool(words) and words[0].casefold() in CI_COMMAND_PREFIXES
def pipeline_for_command(
command: str,
*,
@@ -1086,6 +1093,28 @@ def handle_cancel_ci(
)
def reply_unrecognized_command(
event: Mapping[str, Any],
github: GitHubClient,
) -> None:
if "pull_request" not in event["issue"]:
return
issue_number = event["issue"]["number"]
comment_id = event["comment"]["id"]
actor = event["comment"]["user"]["login"]
if is_already_handled(github, issue_number, comment_id):
print(f"Comment {comment_id} was already handled.")
return
add_reaction_safely(github, comment_id, "-1")
commands = ", ".join(f"`{command}`" for command in sorted(ALL_CI_COMMANDS))
github.add_comment(
issue_number,
f"❌ @{actor}, that is not a recognized CI command, so no CI was "
"started. Post a new comment containing only one of: "
f"{commands}.\n\n{command_comment_marker(comment_id)}",
)
def run(
event: Mapping[str, Any],
github: GitHubClient,
@@ -1217,8 +1246,11 @@ def main() -> None:
)
return
command = parse_command(event["comment"]["body"])
body = event["comment"]["body"]
command = parse_command(body)
if not command:
if is_ci_command_attempt(body):
reply_unrecognized_command(event, github)
return
pipeline = pipeline_for_command(
@@ -32,10 +32,12 @@ from run_ci_command import (
has_trusted_approval,
is_active_build,
is_build_for_pr,
is_ci_command_attempt,
notify_authorized,
parse_command,
parse_trusted_users,
pipeline_for_command,
reply_unrecognized_command,
resolve_workflow_run_pr,
run,
select_latest_build,
@@ -340,14 +342,46 @@ class RunCiCommandTest(unittest.TestCase):
self.assertIsNone(parse_command("/ci run please"))
self.assertIsNone(parse_command("/ci run all please"))
self.assertIsNone(parse_command("/ci cancel please"))
self.assertIsNone(parse_command(" /ci run"))
self.assertIsNone(parse_command("/amd-ci run please"))
self.assertIsNone(parse_command("/amd-ci retry "))
self.assertIsNone(parse_command("/AMD-CI run"))
self.assertIsNone(parse_command("/amdci run"))
self.assertIsNone(parse_command("/ci run --allow-stale all"))
self.assertIsNone(parse_command("/amd-ci run --allow-stale please"))
def test_surrounding_whitespace_is_ignored(self) -> None:
self.assertEqual(parse_command("/ci run\r\n"), COMMAND_RUN_CI)
self.assertEqual(parse_command(" /ci run "), COMMAND_RUN_CI)
self.assertEqual(parse_command("/amd-ci retry\n"), COMMAND_RETRY_AMD_FAILED)
def test_ci_command_attempts_are_detected(self) -> None:
for body in ("/ci", "/ci rn", "/CI run", "/amd-ci run please", " /ci\nrun"):
with self.subTest(body=body):
self.assertTrue(is_ci_command_attempt(body))
for body in ("", "LGTM", "/cifoo", "/amdci run", "please /ci run"):
with self.subTest(body=body):
self.assertFalse(is_ci_command_attempt(body))
def test_unrecognized_command_gets_feedback(self) -> None:
github = FakeGitHub()
reply_unrecognized_command(make_event("/ci rn", actor="author"), github)
self.assertEqual(github.reactions, ["-1"])
self.assertEqual(len(github.comments), 1)
self.assertIn(
"@author, that is not a recognized CI command", github.comments[0]
)
self.assertIn(f"`{COMMAND_RUN_CI}`", github.comments[0])
self.assertIn("<!-- vllm-ci-command:99 -->", github.comments[0])
def test_unrecognized_command_feedback_is_not_repeated(self) -> None:
github = FakeGitHub(comments=["❌ earlier\n\n<!-- vllm-ci-command:99 -->"])
reply_unrecognized_command(make_event("/ci rn"), github)
self.assertEqual(len(github.comments), 1)
self.assertEqual(github.reactions, [])
def test_commands_select_only_their_configured_pipeline(self) -> None:
cases = (
(COMMAND_RUN_CI, "ci"),