[CI] Add /run-full-ci and /run-extra-ci slash commands (#38734)
This commit is contained in:
@@ -32,6 +32,8 @@ PRECISION_BASELINE_TEST = "registered/debug_utils/test_nightly_precision_regress
|
||||
PRECISION_BASELINE_REFRESH_FLAG = "--refresh-precision-baseline"
|
||||
CHANGED_TESTS_FLAG = "--changed"
|
||||
CHANGED_TESTS_SHORT_FLAG = "-c"
|
||||
# Workflow `name:` field, which is what the runs API reports (not the filename).
|
||||
EXTRA_WORKFLOW_NAME = "PR Test Extra"
|
||||
|
||||
|
||||
MAINTENANCE_ISSUE_NUMBER = 21065
|
||||
@@ -495,6 +497,94 @@ def handle_rerun_failed_ci(gh_repo, pr, comment, user_perms, react_on_success=Tr
|
||||
return False
|
||||
|
||||
|
||||
def _run_extra_ci(gh_repo, pr):
|
||||
"""
|
||||
Make `PR Test Extra` run for the current head SHA.
|
||||
|
||||
Assumes `run-ci` + `run-ci-extra` are already on the PR. pr-test-extra.yml
|
||||
gates on them through call-gate -> pr-gate.yml, which live-fetches the
|
||||
label set at run time, so re-running a run that was red at the gate picks
|
||||
up labels added seconds earlier.
|
||||
|
||||
Deliberately rerun-only, with no workflow_dispatch fallback: the extra
|
||||
workflow's dispatch inputs carry no `pr_head_sha`, so a fork PR could only
|
||||
be dispatched against `main` — testing the wrong tree. A pull_request run
|
||||
exists at essentially every head SHA anyway, so the missing-run case is
|
||||
reported rather than papered over.
|
||||
|
||||
Returns (acted, message).
|
||||
"""
|
||||
extra_runs = [
|
||||
run
|
||||
for run in gh_repo.get_workflow_runs(head_sha=pr.head.sha)
|
||||
if run.name == EXTRA_WORKFLOW_NAME
|
||||
]
|
||||
if not extra_runs:
|
||||
return (
|
||||
False,
|
||||
f"No `{EXTRA_WORKFLOW_NAME}` run exists for this commit, so there is "
|
||||
"nothing to re-run. Push a commit to create one.",
|
||||
)
|
||||
|
||||
# Same newest-wins rule handle_rerun_failed_ci uses: older runs at this SHA
|
||||
# are superseded and re-running them fights the live run for runners.
|
||||
run = _latest_run_per_workflow(extra_runs)[0]
|
||||
|
||||
if run.status != "completed":
|
||||
return (
|
||||
True,
|
||||
f"⏳ [`{EXTRA_WORKFLOW_NAME}`]({run.html_url}) is already "
|
||||
f"{run.status} for this commit; left it alone.",
|
||||
)
|
||||
|
||||
try:
|
||||
if run.conclusion == "success":
|
||||
# Nothing failed, so there are no jobs for rerun_failed_jobs() to
|
||||
# target — the ask is an explicit re-run of green work.
|
||||
print(f" Full rerun of successful run {run.id}")
|
||||
run.rerun()
|
||||
else:
|
||||
try:
|
||||
print(f" rerun_failed_jobs on {run.id} ({run.conclusion})")
|
||||
run.rerun_failed_jobs()
|
||||
except Exception as e:
|
||||
print(f" rerun_failed_jobs rejected ({e}) - full rerun")
|
||||
run.rerun()
|
||||
except Exception as e:
|
||||
return False, f"Failed to re-run [`{EXTRA_WORKFLOW_NAME}`]({run.html_url}): {e}"
|
||||
|
||||
return True, f"🚀 Re-running [`{EXTRA_WORKFLOW_NAME}`]({run.html_url})."
|
||||
|
||||
|
||||
def handle_run_extra_ci(gh_repo, pr, comment, user_perms):
|
||||
"""
|
||||
Handles /run-extra-ci: label the PR for extra CI and re-run only
|
||||
`PR Test Extra`. Baseline CI runs are left untouched.
|
||||
|
||||
Gated on the same two permissions as the steps it performs — the label add
|
||||
(can_tag_run_ci_label) and the re-run (can_rerun_failed_ci) — rather than a
|
||||
new key, so every user who can already drive CI can drive extra CI.
|
||||
Returns True if action was taken, False otherwise.
|
||||
"""
|
||||
if not user_perms.get("can_rerun_failed_ci", False):
|
||||
print("Permission denied: can_rerun_failed_ci is false.")
|
||||
return False
|
||||
|
||||
tagged = handle_tag_run_ci(
|
||||
gh_repo, pr, comment, user_perms, react_on_success=False, tag_extra=True
|
||||
)
|
||||
if not tagged:
|
||||
return False
|
||||
|
||||
print("Waiting 5 seconds for labels to propagate...")
|
||||
time.sleep(5)
|
||||
|
||||
acted, message = _run_extra_ci(gh_repo, pr)
|
||||
pr.create_issue_comment(message if acted else f"⛔ {message}")
|
||||
comment.create_reaction("+1" if acted else "confused")
|
||||
return acted
|
||||
|
||||
|
||||
MULTIMODAL_TEST_DIR = "python/sglang/multimodal_gen/test"
|
||||
|
||||
MULTIMODAL_PATH_TO_RUNNER = {
|
||||
@@ -1575,15 +1665,28 @@ def main():
|
||||
tokens = first_line.split()
|
||||
tag_extra = len(tokens) > 1 and "extra" in tokens[1:]
|
||||
|
||||
# /run-full-ci is the short, spelled-out form of `/tag-and-rerun-ci extra`
|
||||
# and shares its branch below. /rerun-* spellings are accepted silently as
|
||||
# aliases: they sit one keystroke from the documented name and from the
|
||||
# neighbouring /rerun-* commands, and failing them closed would just look
|
||||
# like the bot ignoring the comment.
|
||||
is_full_ci = first_line.startswith(("/run-full-ci", "/rerun-full-ci"))
|
||||
is_extra_ci = first_line.startswith(("/run-extra-ci", "/rerun-extra-ci"))
|
||||
if is_full_ci:
|
||||
tag_extra = True
|
||||
|
||||
if first_line.startswith("/tag-run-ci-label"):
|
||||
handle_tag_run_ci(repo, pr, comment, user_perms, tag_extra=tag_extra)
|
||||
|
||||
elif is_extra_ci:
|
||||
handle_run_extra_ci(repo, pr, comment, user_perms)
|
||||
|
||||
elif first_line.startswith("/rerun-failed-ci"):
|
||||
handle_rerun_failed_ci(repo, pr, comment, user_perms)
|
||||
|
||||
elif first_line.startswith("/tag-and-rerun-ci"):
|
||||
elif first_line.startswith("/tag-and-rerun-ci") or is_full_ci:
|
||||
# Perform both actions, but suppress individual reactions
|
||||
print(f"Processing combined command: /tag-and-rerun-ci (tag_extra={tag_extra})")
|
||||
print(f"Processing combined command: {first_line} (tag_extra={tag_extra})")
|
||||
|
||||
tagged = handle_tag_run_ci(
|
||||
repo, pr, comment, user_perms, react_on_success=False, tag_extra=tag_extra
|
||||
|
||||
Reference in New Issue
Block a user