Add docs on trigger ci (#13513)

Co-authored-by: sglang-bot <sglangbot@gmail.com>
This commit is contained in:
Lianmin Zheng
2025-11-18 05:23:05 -08:00
committed by GitHub
co-authored by sglang-bot
parent f6cfe9f197
commit 63807079b9
3 changed files with 38 additions and 29 deletions
@@ -22,8 +22,6 @@ jobs:
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@v4
# We checkout the current context to get the script,
# but the script will fetch permissions from main as requested.
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v5 uses: actions/setup-python@v5
@@ -32,7 +30,7 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: | run: |
pip install requests PyGithub pip install PyGithub
- name: Handle Slash Command - name: Handle Slash Command
env: env:
+11 -9
View File
@@ -68,19 +68,21 @@ You can follow the pull request merge process described in [MAINTAINER.md](https
You will need to work with the Merge Oncall, Codeowner, and other reviewers to get their approvals. You will need to work with the Merge Oncall, Codeowner, and other reviewers to get their approvals.
Then your PR can be merged. Then your PR can be merged.
## How to trigger CI ## How to Trigger CI Tests
To trigger CI, the pull request must have the "run-ci" label. We have a lot of open PRs but limited CI machines, so only top and trusted contributors have permission to trigger CI tests.
- The "run-ci" label is not added automatically to new pull requests. Users with permission are listed here:
- Only collaborators with triage or higher permission can add the "run-ci" label. https://github.com/sgl-project/sglang/blob/main/.github/CI_PERMISSIONS.json
- If you have triage/write/maintain/admin access, you can manually add the label by clicking "Labels" on the right side of the pull request.
- If you do not have triage or higher permission, please request a review and ask a collaborator to add the label for you.
After the "run-ci" label is added, the PR author can trigger CI by: 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:
1. Pushing new commits, or - `/tag-run-ci-label`: Tag the "run-ci" label. Every future commits will trigger CI.
2. Clicking "Re-run" / retrigger on the workflow page. - `/rerun-failed-ci`: Rerun the failed/flaky tests of the last commit.
If you have permission, the [Slash Command Handler](https://github.com/sgl-project/sglang/actions/workflows/slash_command_handler.yml) will execute your command and react with a 👍 on your comment. It may take up to several minutes to react. Here is a usage [example](https://github.com/sgl-project/sglang/pull/13498#issuecomment-3547552157).
If you don’t have permission, please ask maintainers to trigger CI for you.
## Code style guidance ## Code style guidance
- Avoid code duplication. If the same code snippet (more than five lines) appears multiple times, extract it into a shared function. - Avoid code duplication. If the same code snippet (more than five lines) appears multiple times, extract it into a shared function.
+26 -17
View File
@@ -2,11 +2,10 @@ import json
import os import os
import sys import sys
import requests from github import Auth, Github
from github import Github
# Configuration # Configuration
PERMISSIONS_FILE_URL = "https://raw.githubusercontent.com/sgl-project/sglang/main/.github/CI_PERMISSIONS.json" PERMISSIONS_FILE_PATH = ".github/CI_PERMISSIONS.json"
def get_env_var(name): def get_env_var(name):
@@ -19,15 +18,18 @@ def get_env_var(name):
def load_permissions(user_login): def load_permissions(user_login):
""" """
Downloads the permissions JSON from the main branch and returns Reads the permissions JSON from the local file system and returns
the permissions dict for the specific user. the permissions dict for the specific user.
""" """
try: try:
print(f"Fetching permissions from {PERMISSIONS_FILE_URL}...") print(f"Loading permissions from {PERMISSIONS_FILE_PATH}...")
response = requests.get(PERMISSIONS_FILE_URL) if not os.path.exists(PERMISSIONS_FILE_PATH):
response.raise_for_status() print(f"Error: Permissions file not found at {PERMISSIONS_FILE_PATH}")
return None
with open(PERMISSIONS_FILE_PATH, "r") as f:
data = json.load(f)
data = response.json()
user_perms = data.get(user_login) user_perms = data.get(user_login)
if not user_perms: if not user_perms:
@@ -79,8 +81,13 @@ def handle_rerun_failed_ci(gh_repo, pr, comment, user_perms):
# We only care about completed runs that failed # We only care about completed runs that failed
if run.status == "completed" and run.conclusion == "failure": if run.status == "completed" and run.conclusion == "failure":
print(f"Rerunning workflow: {run.name} (ID: {run.id})") print(f"Rerunning workflow: {run.name} (ID: {run.id})")
run.rerun_failed() try:
rerun_count += 1 # PyGithub uses rerun_failed_jobs() or rerun() depending on version/intent
# The traceback suggested rerun_failed_jobs
run.rerun_failed_jobs()
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") comment.create_reaction("+1")
@@ -98,19 +105,21 @@ def main():
comment_body = get_env_var("COMMENT_BODY").strip() comment_body = get_env_var("COMMENT_BODY").strip()
user_login = get_env_var("USER_LOGIN") user_login = get_env_var("USER_LOGIN")
# 2. Initialize GitHub API # 2. Load Permissions (Local Check)
g = Github(token)
repo = g.get_repo(repo_name)
pr = repo.get_pull(pr_number)
comment = repo.get_issue(pr_number).get_comment(comment_id)
# 3. Load Permissions (Remote Check)
user_perms = load_permissions(user_login) user_perms = load_permissions(user_login)
if not user_perms: if not user_perms:
print(f"User {user_login} does not have any configured permissions. Exiting.") print(f"User {user_login} does not have any configured permissions. Exiting.")
return return
# 3. Initialize GitHub API with Auth
auth = Auth.Token(token)
g = Github(auth=auth)
repo = g.get_repo(repo_name)
pr = repo.get_pull(pr_number)
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 # 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()