[CI] Answer unrecognized slash commands instead of skipping silently (#38736)
This commit is contained in:
@@ -14,6 +14,10 @@ jobs:
|
|||||||
slash_command:
|
slash_command:
|
||||||
# Only run if it is a PR and the comment contains a recognized command
|
# Only run if it is a PR and the comment contains a recognized command
|
||||||
# Use contains() since startsWith() can't handle leading whitespace/newlines
|
# Use contains() since startsWith() can't handle leading whitespace/newlines
|
||||||
|
#
|
||||||
|
# The trailing startsWith() namespace clauses admit *unrecognized* commands
|
||||||
|
# so the script can answer them; they are startsWith() because
|
||||||
|
# contains('/run-') would fire on any comment quoting `scripts/run-tests.sh`.
|
||||||
if: >
|
if: >
|
||||||
github.event.issue.pull_request &&
|
github.event.issue.pull_request &&
|
||||||
(contains(github.event.comment.body, '/tag-run-ci-label') ||
|
(contains(github.event.comment.body, '/tag-run-ci-label') ||
|
||||||
@@ -24,7 +28,10 @@ jobs:
|
|||||||
contains(github.event.comment.body, '/rerun-full-ci') ||
|
contains(github.event.comment.body, '/rerun-full-ci') ||
|
||||||
contains(github.event.comment.body, '/rerun-extra-ci') ||
|
contains(github.event.comment.body, '/rerun-extra-ci') ||
|
||||||
contains(github.event.comment.body, '/rerun-group') ||
|
contains(github.event.comment.body, '/rerun-group') ||
|
||||||
contains(github.event.comment.body, '/rerun-test'))
|
contains(github.event.comment.body, '/rerun-test') ||
|
||||||
|
startsWith(github.event.comment.body, '/tag-') ||
|
||||||
|
startsWith(github.event.comment.body, '/rerun-') ||
|
||||||
|
startsWith(github.event.comment.body, '/run-'))
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@@ -141,6 +141,8 @@ Selective reruns do not build or install a PR-local `sglang-kernel` wheel. If a
|
|||||||
|
|
||||||
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/14253#issuecomment-3599509302).
|
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/14253#issuecomment-3599509302).
|
||||||
|
|
||||||
|
If a command isn't recognized, the handler reacts 😕 instead, and replies with the closest matching command when there is one. A comment with no reaction at all means the handler never saw it — check the command is spelled as listed above.
|
||||||
|
|
||||||
To avoid spamming a PR with too many `/rerun-failed-ci` comments, you can also trigger the command by editing an existing comment and adding any suffix (e.g., `/rerun-failed-ci try again`).
|
To avoid spamming a PR with too many `/rerun-failed-ci` comments, you can also trigger the command by editing an existing comment and adding any suffix (e.g., `/rerun-failed-ci try again`).
|
||||||
|
|
||||||
If you don’t have permission and you’re not the PR author, please ask maintainers to trigger CI for you.
|
If you don’t have permission and you’re not the PR author, please ask maintainers to trigger CI for you.
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import difflib
|
||||||
import glob
|
import glob
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
@@ -1615,6 +1616,72 @@ def handle_rerun_group(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Namespaces this handler owns. Anything else reaching the script is a comment
|
||||||
|
# that merely quoted a path, and is left alone.
|
||||||
|
OWNED_COMMAND_PREFIXES = ("/tag-", "/rerun-", "/run-")
|
||||||
|
|
||||||
|
# Suggestion targets. Documented spellings only, so a typo is pointed at the
|
||||||
|
# canonical name rather than at an undocumented alias.
|
||||||
|
KNOWN_COMMANDS = (
|
||||||
|
"/tag-run-ci-label",
|
||||||
|
"/tag-and-rerun-ci",
|
||||||
|
"/rerun-failed-ci",
|
||||||
|
"/rerun-group",
|
||||||
|
"/rerun-test",
|
||||||
|
"/run-full-ci",
|
||||||
|
"/run-extra-ci",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Removed commands, kept because they were documented long enough that muscle
|
||||||
|
# memory still sends them and difflib would suggest something unrelated.
|
||||||
|
RETIRED_COMMANDS = {
|
||||||
|
"/rerun-stage": (
|
||||||
|
"`/rerun-stage` was removed. Use `/rerun-test <test-spec>` for specific "
|
||||||
|
"tests, or `/rerun-failed-ci` for everything that didn't pass."
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def handle_unknown_command(pr, comment, first_line):
|
||||||
|
"""
|
||||||
|
Answer a comment addressed to this handler that matched no command.
|
||||||
|
|
||||||
|
A silent skip is indistinguishable from the bot being down, so always react;
|
||||||
|
comment only when there is something concrete to say, to avoid turning every
|
||||||
|
stray `/run-...` into PR noise.
|
||||||
|
"""
|
||||||
|
tokens = first_line.split()
|
||||||
|
command = tokens[0] if tokens else first_line
|
||||||
|
if not command.startswith(OWNED_COMMAND_PREFIXES):
|
||||||
|
print(f"Not addressed to this handler: {first_line[:60]!r}")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"Unrecognized command: {command}")
|
||||||
|
try:
|
||||||
|
comment.create_reaction("confused")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Failed to add reaction: {e}")
|
||||||
|
|
||||||
|
hint = RETIRED_COMMANDS.get(command)
|
||||||
|
if hint is None:
|
||||||
|
close = difflib.get_close_matches(command, KNOWN_COMMANDS, n=1, cutoff=0.6)
|
||||||
|
hint = f"Did you mean `{close[0]}`?" if close else None
|
||||||
|
|
||||||
|
if hint is None:
|
||||||
|
print("No close match; reaction only.")
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
pr.create_issue_comment(
|
||||||
|
f"⛔ `{command}` isn't a recognized CI command. {hint}\n\n"
|
||||||
|
"See the [command reference]"
|
||||||
|
"(https://docs.sglang.io/docs/developer_guide/contribution_guide"
|
||||||
|
"#how-to-trigger-ci-tests)."
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Failed to post hint comment: {e}")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
# 1. Load Environment Variables
|
# 1. Load Environment Variables
|
||||||
token = get_env_var("GITHUB_TOKEN")
|
token = get_env_var("GITHUB_TOKEN")
|
||||||
@@ -1740,7 +1807,7 @@ def main():
|
|||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print(f"Unknown or ignored command: {first_line}")
|
handle_unknown_command(pr, comment, first_line)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Reference in New Issue
Block a user