Add /tag-and-rerun-ci (#13521)
This commit is contained in:
@@ -16,7 +16,8 @@ jobs:
|
|||||||
if: >
|
if: >
|
||||||
github.event.issue.pull_request &&
|
github.event.issue.pull_request &&
|
||||||
(startsWith(github.event.comment.body, '/tag-run-ci-label') ||
|
(startsWith(github.event.comment.body, '/tag-run-ci-label') ||
|
||||||
startsWith(github.event.comment.body, '/rerun-failed-ci'))
|
startsWith(github.event.comment.body, '/rerun-failed-ci') ||
|
||||||
|
startsWith(github.event.comment.body, '/tag-and-rerun-ci'))
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@@ -75,8 +75,9 @@ Users with permission are listed in the [CI_PERMISSIONS.json](https://github.com
|
|||||||
|
|
||||||
For CI to run on a pull request, it must have the "run-ci" label. Authorized users can add the label or rerun failed tests by commenting on the PR with one of these commands:
|
For CI to run on a pull request, it must have the "run-ci" label. Authorized users can add the label or rerun failed tests by commenting on the PR with one of these commands:
|
||||||
|
|
||||||
- `/tag-run-ci-label`: Tag the "run-ci" label. Every future commits will trigger CI.
|
- `/tag-run-ci-label`: Adds the "run-ci" label. Every future commit will trigger CI.
|
||||||
- `/rerun-failed-ci`: Rerun the failed/flaky tests of the last commit.
|
- `/rerun-failed-ci`: Reruns the failed or flaky tests from the most recent commit.
|
||||||
|
- `/tag-and-rerun-ci`: A single command that performs both `/tag-run-ci-label` and `/rerun-failed-ci`.
|
||||||
|
|
||||||
If you have permission, the [Slash Command Handler](https://github.com/sgl-project/sglang/actions/workflows/slash_command_handler.yml) will run your command and react with a 👍 to your comment. It may take up to a few minutes for the reaction to appear. Here’s a usage [example](https://github.com/sgl-project/sglang/pull/13498#issuecomment-3547552157).
|
If you have permission, the [Slash Command Handler](https://github.com/sgl-project/sglang/actions/workflows/slash_command_handler.yml) will run your command and react with a 👍 to your comment. It may take up to a few minutes for the reaction to appear. Here’s a usage [example](https://github.com/sgl-project/sglang/pull/13498#issuecomment-3547552157).
|
||||||
|
|
||||||
|
|||||||
@@ -43,31 +43,38 @@ def load_permissions(user_login):
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
def handle_tag_run_ci(gh_repo, pr, comment, user_perms):
|
def handle_tag_run_ci(gh_repo, pr, comment, user_perms, react_on_success=True):
|
||||||
"""
|
"""
|
||||||
Handles the /tag-run-ci-label command.
|
Handles the /tag-run-ci-label command.
|
||||||
|
Returns True if action was taken, False otherwise.
|
||||||
"""
|
"""
|
||||||
if not user_perms.get("can_tag_run_ci_label", False):
|
if not user_perms.get("can_tag_run_ci_label", False):
|
||||||
print("Permission denied: can_tag_run_ci_label is false.")
|
print("Permission denied: can_tag_run_ci_label is false.")
|
||||||
return
|
return False
|
||||||
|
|
||||||
print("Permission granted. Adding 'run-ci' label.")
|
print("Permission granted. Adding 'run-ci' label.")
|
||||||
pr.add_to_labels("run-ci")
|
pr.add_to_labels("run-ci")
|
||||||
|
|
||||||
# React to the comment with +1
|
if react_on_success:
|
||||||
comment.create_reaction("+1")
|
comment.create_reaction("+1")
|
||||||
print("Label added and comment reacted.")
|
print("Label added and comment reacted.")
|
||||||
|
else:
|
||||||
|
print("Label added (reaction suppressed).")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def handle_rerun_failed_ci(gh_repo, pr, comment, user_perms):
|
def handle_rerun_failed_ci(gh_repo, pr, comment, user_perms, react_on_success=True):
|
||||||
"""
|
"""
|
||||||
Handles the /rerun-failed-ci command.
|
Handles the /rerun-failed-ci command.
|
||||||
|
Reruns workflows with 'failure' or 'skipped' conclusions.
|
||||||
|
Returns True if action was taken, False otherwise.
|
||||||
"""
|
"""
|
||||||
if not user_perms.get("can_rerun_failed_ci", False):
|
if not user_perms.get("can_rerun_failed_ci", False):
|
||||||
print("Permission denied: can_rerun_failed_ci is false.")
|
print("Permission denied: can_rerun_failed_ci is false.")
|
||||||
return
|
return False
|
||||||
|
|
||||||
print("Permission granted. Triggering rerun of failed workflows.")
|
print("Permission granted. Triggering rerun of failed or skipped workflows.")
|
||||||
|
|
||||||
# Get the SHA of the latest commit in the PR
|
# Get the SHA of the latest commit in the PR
|
||||||
head_sha = pr.head.sha
|
head_sha = pr.head.sha
|
||||||
@@ -78,22 +85,35 @@ def handle_rerun_failed_ci(gh_repo, pr, comment, user_perms):
|
|||||||
|
|
||||||
rerun_count = 0
|
rerun_count = 0
|
||||||
for run in runs:
|
for run in runs:
|
||||||
# We only care about completed runs that failed
|
if run.status != "completed":
|
||||||
if run.status == "completed" and run.conclusion == "failure":
|
continue
|
||||||
print(f"Rerunning workflow: {run.name} (ID: {run.id})")
|
|
||||||
|
if run.conclusion == "failure":
|
||||||
|
print(f"Rerunning failed workflow: {run.name} (ID: {run.id})")
|
||||||
try:
|
try:
|
||||||
# PyGithub uses rerun_failed_jobs() or rerun() depending on version/intent
|
# Use rerun_failed_jobs for efficiency on failures
|
||||||
# The traceback suggested rerun_failed_jobs
|
|
||||||
run.rerun_failed_jobs()
|
run.rerun_failed_jobs()
|
||||||
rerun_count += 1
|
rerun_count += 1
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Failed to rerun workflow {run.id}: {e}")
|
print(f"Failed to rerun workflow {run.id}: {e}")
|
||||||
|
|
||||||
|
elif run.conclusion == "skipped":
|
||||||
|
print(f"Rerunning skipped workflow: {run.name} (ID: {run.id})")
|
||||||
|
try:
|
||||||
|
# Skipped workflows don't have 'failed jobs', so we use full rerun()
|
||||||
|
run.rerun()
|
||||||
|
rerun_count += 1
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Failed to rerun workflow {run.id}: {e}")
|
||||||
|
|
||||||
if rerun_count > 0:
|
if rerun_count > 0:
|
||||||
comment.create_reaction("+1")
|
print(f"Triggered rerun for {rerun_count} workflows.")
|
||||||
print(f"Triggered rerun for {rerun_count} failed workflows.")
|
if react_on_success:
|
||||||
|
comment.create_reaction("+1")
|
||||||
|
return True
|
||||||
else:
|
else:
|
||||||
print("No failed workflows found to rerun.")
|
print("No failed or skipped workflows found to rerun.")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@@ -121,7 +141,6 @@ def main():
|
|||||||
comment = repo.get_issue(pr_number).get_comment(comment_id)
|
comment = repo.get_issue(pr_number).get_comment(comment_id)
|
||||||
|
|
||||||
# 4. Parse Command and Execute
|
# 4. Parse Command and Execute
|
||||||
# split lines to handle cases where there might be text after the command
|
|
||||||
first_line = comment_body.split("\n")[0].strip()
|
first_line = comment_body.split("\n")[0].strip()
|
||||||
|
|
||||||
if first_line.startswith("/tag-run-ci-label"):
|
if first_line.startswith("/tag-run-ci-label"):
|
||||||
@@ -130,6 +149,24 @@ def main():
|
|||||||
elif first_line.startswith("/rerun-failed-ci"):
|
elif first_line.startswith("/rerun-failed-ci"):
|
||||||
handle_rerun_failed_ci(repo, pr, comment, user_perms)
|
handle_rerun_failed_ci(repo, pr, comment, user_perms)
|
||||||
|
|
||||||
|
elif first_line.startswith("/tag-and-rerun-ci"):
|
||||||
|
# Perform both actions, but suppress individual reactions
|
||||||
|
print("Processing combined command: /tag-and-rerun-ci")
|
||||||
|
|
||||||
|
tagged = handle_tag_run_ci(
|
||||||
|
repo, pr, comment, user_perms, react_on_success=False
|
||||||
|
)
|
||||||
|
rerun = handle_rerun_failed_ci(
|
||||||
|
repo, pr, comment, user_perms, react_on_success=False
|
||||||
|
)
|
||||||
|
|
||||||
|
# If at least one action was successful, add the reaction here
|
||||||
|
if tagged or rerun:
|
||||||
|
comment.create_reaction("+1")
|
||||||
|
print("Combined command processed successfully; reaction added.")
|
||||||
|
else:
|
||||||
|
print("Combined command finished, but no actions were taken.")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print(f"Unknown or ignored command: {first_line}")
|
print(f"Unknown or ignored command: {first_line}")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user