Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 137 additions & 0 deletions .github/workflows/_run-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
name: CI Job

# Reusable workflow ported from radixark/miles (.github/workflows/_run-ci.yml).
#
# CPU-only path: GitHub-hosted ubuntu-latest. Trimmed from miles main:
# * GPU `run:` job removed entirely — miles-D has no self-hosted GPU
# runners. To re-add: copy the `run:` job block back from miles main,
# reintroduce `runs_on / container_image / skip_dependency_install /
# cpu_runner` inputs, and add a matching `if: !inputs.cpu_runner` gate.
# * Megatron-LM checkout/install removed: miles-D source has zero
# `from megatron` imports (verified via grep).
# * PR-body magic for `ci-megatron-pr:` removed for the same reason.
# * sglang checkout/install preserved (miles-D imports
# sglang.multimodal_gen.runtime.* and sglang.srt.*).

on:
workflow_call:
inputs:
execute_command:
type: string
required: true

# TODO: run gpu
jobs:
run-cpu:
runs-on: ubuntu-latest
timeout-minutes: 60
env:
PYTHONPATH: ${{ github.workspace }}
steps:
- name: Free disk space
shell: bash
run: |
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc
df -h

- name: Checkout miles-diffusion
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
# 3.10 matches miles-D's setup.py / pyproject (python_requires=">=3.10").
python-version: '3.10'

- name: Install uv
uses: astral-sh/setup-uv@v5

- name: Install system dependencies
shell: bash
run: |
sudo apt-get update
sudo apt-get install -y protobuf-compiler
protoc --version

# TODO: sglang-diffusion-rollout-test to be switched back to sgl main
- name: Resolve dependency refs
id: resolve-refs
shell: bash
env:
PR_BODY: ${{ github.event.pull_request.body || '' }}
INPUT_SGLANG_PR: ${{ github.event.inputs.ci_sglang_pr || '' }}
INPUT_SGLANG_REPO: ${{ github.event.inputs.ci_sglang_repo || '' }}
run: |
SGLANG_PR="${INPUT_SGLANG_PR}"
SGLANG_REPO="${INPUT_SGLANG_REPO}"
if [ -n "$PR_BODY" ]; then
PR_SGLANG_PR=$(echo "$PR_BODY" | grep -m1 -oP '^ci-sglang-pr:\s+\K\S+' || true)
[ -z "$SGLANG_PR" ] && [ -n "$PR_SGLANG_PR" ] && SGLANG_PR="$PR_SGLANG_PR"
PR_SGLANG_REPO=$(echo "$PR_BODY" | grep -m1 -oP '^ci-sglang-repo:\s+\K\S+' || true)
[ -z "$SGLANG_REPO" ] && [ -n "$PR_SGLANG_REPO" ] && SGLANG_REPO="$PR_SGLANG_REPO"
fi
[ -z "$SGLANG_PR" ] && SGLANG_PR="sglang-diffusion-rollout-test"
# TODO: default repo Rockdu/sglang to be switched back to sgl-project/sglang
[ -z "$SGLANG_REPO" ] && SGLANG_REPO="Rockdu/sglang"
resolve_fetch_ref() {
local ref="$1"
if [[ "$ref" =~ ^#([0-9]+)$ ]]; then
echo "refs/pull/${BASH_REMATCH[1]}/head"
else
echo "$ref"
fi
}
SGLANG_FETCH=$(resolve_fetch_ref "$SGLANG_PR")
echo "ci_sglang_pr=$SGLANG_FETCH" >> $GITHUB_OUTPUT
echo "sglang_repo=$SGLANG_REPO" >> $GITHUB_OUTPUT
echo "Resolved: sglang repo=$SGLANG_REPO ref=$SGLANG_PR -> fetch=$SGLANG_FETCH"

# TODO: default sglang repo (Rockdu/sglang) to be switched back to sgl main
- name: Checkout temporary sglang
uses: actions/checkout@v4
with:
repository: ${{ steps.resolve-refs.outputs.sglang_repo }}
ref: ${{ steps.resolve-refs.outputs.ci_sglang_pr }}
path: sglang

# - name: Checkout sglang
# uses: actions/checkout@v4
# with:
# repository: sgl-project/sglang
# ref: ${{ steps.resolve-refs.outputs.ci_sglang_pr }}
# path: sglang

- name: Install dependencies
shell: bash
env:
UV_SYSTEM_PYTHON: "1"
run: |
uv pip install -e sglang/python --no-deps
uv pip install -r requirements.txt
uv pip install -e . --no-deps
# sglang is installed --no-deps above, but miles-D's import chain
# loads many sglang modules. Install sglang's pure-python runtime
# deps upfront; skip GPU-only ones (cuda-python, flashinfer,
# flash-attn-4, sglang-kernel, torchao, torchcodec,
# torch_memory_saver, quack-kernels, nvidia-cutlass-dsl,
# apache-tvm-ffi, kernels, decord2, av). torch itself comes via
# accelerate (in requirements.txt).
uv pip install \
IPython aiohttp anthropic build compressed-tensors einops fastapi \
gguf interegular jsonschema llguidance mistral_common modelscope \
msgspec ninja nvidia-ml-py openai openai-harmony orjson outlines \
partial_json_parser prometheus-client psutil py-spy pydantic \
python-multipart pyzmq scipy sentencepiece setproctitle soundfile \
tiktoken timm torchvision uvicorn uvloop watchfiles xgrammar
# sglang's memory_pool_host.py unconditionally imports sgl_kernel
# on non-NPU/XPU/MPS hardware. sgl_kernel is GPU-only — install a
# local stub so imports succeed at module load.
uv pip install tests/ci/cpu_stubs

- name: Resolve suite plan
shell: bash
run: ${{ inputs.execute_command }} --list-only

- name: Run tests
shell: bash
run: ${{ inputs.execute_command }}
110 changes: 110 additions & 0 deletions .github/workflows/bot-slash-lint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
name: Slash Command Handler

on:
issue_comment:
types: [created, edited]

permissions:
contents: write # Required to push commits back to PR branch
actions: write # Required to rerun workflows
issues: write # Required for comment reactions in some contexts

jobs:
slash_lint_codebase:
# Only run if it is a PR comment with a recognized command
if: >
github.event_name == 'issue_comment' &&
github.event.issue.pull_request &&
(
contains(github.event.comment.body, '/tag-run-lint') ||
contains(github.event.comment.body, '/run-lint')
)
runs-on: ubuntu-latest
steps:
- name: React to command comment (ack)
if: always()
uses: actions/github-script@v7
with:
script: |
const commentId = context.payload.comment.id;
// Add an eyes reaction to acknowledge the command
await github.request('POST /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions', {
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: commentId,
content: 'eyes'
});

- name: Check out Git repository
uses: actions/checkout@v4
with:
repository: ${{ github.repository }}
ref: refs/pull/${{ github.event.issue.number }}/head
token: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.10'

- name: Run pre-commit hooks
continue-on-error: true
uses: pre-commit/action@v3.0.1

- name: Get PR branch name
id: get_branch
run: |
BRANCH_NAME=$(gh pr view ${{ github.event.issue.number }} --json headRefName --jq '.headRefName')
echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Check if there are any changes
id: verify_diff
run: |
git diff --quiet . || echo "changed=true" >> $GITHUB_OUTPUT

- name: Commit files
if: steps.verify_diff.outputs.changed == 'true'
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add .
git commit -m "[CI-Lint] Fix code style issues with pre-commit ${{ github.sha }}" -a
git push origin HEAD:refs/heads/${{ steps.get_branch.outputs.branch_name }}

cleanup_reaction:
# Always run after the main job completes (success, failure, or cancelled)
if: always()
needs: slash_lint_codebase
runs-on: ubuntu-latest
steps:
- name: Remove initial ack reaction
uses: actions/github-script@v7
with:
script: |
const commentId = context.payload.comment.id;
// List reactions on the comment
const reactions = await github.rest.reactions.listForIssueComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: commentId
}).then(r => r.data);
// Find the 'eyes' reaction added by this workflow bot
const target = reactions.find(r => r.content === 'eyes' && r.user && r.user.login === 'github-actions[bot]');
if (target) {
try {
await github.rest.reactions.deleteForIssueComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: commentId,
reaction_id: target.id
});
core.info(`Successfully deleted eyes reaction (${target.id})`);
} catch (err) {
// Non-fatal: reaction may already be gone or inaccessible
core.info(`Could not delete eyes reaction (${target.id}): ${err.message || err.status || 'unknown error'}`);
}
} else {
core.info('No eyes reaction from github-actions[bot] found to remove.');
}
69 changes: 69 additions & 0 deletions .github/workflows/pr-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: PR Test

# Ported from radixark/miles (.github/workflows/pr-test.yml).
#
# Differences vs miles main:
# * All GPU stages (stage-b-2-gpu-h200, stage-c-8-gpu-h100,
# stage-c-4-gpu-h200, stage-c-2-gpu-h200) removed — miles-D has no
# self-hosted GPU runner fleet yet. To re-enable, copy the job blocks
# back from miles main and provision matching runners.
# * `resolve-ci-image` job removed — only relevant for GPU stages that
# pull a `radixark/miles:<tag>` container.
# * `ci_megatron_pr` workflow_dispatch input removed — miles-D source has
# zero `from megatron` imports.

on:
pull_request:
types: [synchronize, labeled, opened, reopened]
workflow_dispatch:
inputs:
ci_sglang_pr:
description: 'SGLang branch/commit (default: sglang-miles)'
required: false
type: string
default: 'sglang-miles-diffusion'
ci_sglang_repo:
description: 'SGLang repository owner/name (default: Rockdu/sglang)'
required: false
type: string
default: 'Rockdu/sglang'

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

# PR labels are passed through to run_suite.py as raw `run-ci-<X>` strings via
# `--labels`. run_suite.py strips the `run-ci-` prefix internally and ignores
# any label that does not start with `run-ci-` (see tests/ci/run_suite.py
# `strip_run_ci_prefix`). For `workflow_dispatch`, no PR labels exist, so the
# `--labels` list collapses to empty; `--match-all-labels` is then added
# unconditionally to bypass the labels predicate inside run_suite.py and run
# every enabled test in the suite.

jobs:
# Stage A: CPU-only fast tests (always runs on PR)
stage-a-cpu:
if: (github.event_name == 'workflow_dispatch') || (github.event.pull_request)
uses: ./.github/workflows/_run-ci.yml
with:
execute_command: >-
python tests/ci/run_suite.py --hw cpu --suite stage-a-cpu
--labels ${{ join(github.event.pull_request.labels.*.name, ' ') }}
${{ (github.event_name == 'workflow_dispatch' || contains(github.event.pull_request.labels.*.name, 'run-ci-image') || contains(github.event.pull_request.labels.*.name, 'run-ci-all')) && '--match-all-labels' || '' }}
secrets: inherit

# Stage B: CPU-only slower bucket (currently empty; reserved for future
# CPU tests that don't fit stage-a-cpu's fast budget). Always runs on PR.
# Empty result exits 0 in run_suite.py.
stage-b-cpu:
if: (github.event_name == 'workflow_dispatch') || (github.event.pull_request)
uses: ./.github/workflows/_run-ci.yml
with:
execute_command: >-
python tests/ci/run_suite.py --hw cpu --suite stage-b-cpu
--labels ${{ join(github.event.pull_request.labels.*.name, ' ') }}
${{ (github.event_name == 'workflow_dispatch' || contains(github.event.pull_request.labels.*.name, 'run-ci-image') || contains(github.event.pull_request.labels.*.name, 'run-ci-all')) && '--match-all-labels' || '' }}
secrets: inherit
41 changes: 41 additions & 0 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: pre-commit

on:
push:
branches: [main]
pull_request:
types: [opened, synchronize, reopened, ready_for_review]

permissions:
contents: read

jobs:
run-pre-commit:
name: Run pre-commit
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'

- name: Install pre-commit
run: pip install --upgrade pip pre-commit

- name: Cache pre-commit environments
uses: actions/cache@v4
with:
path: ~/.cache/pre-commit
key: pre-commit-${{ runner.os }}-${{ hashFiles('.pre-commit-config.yaml') }}
restore-keys: |
pre-commit-${{ runner.os }}-

- name: Run pre-commit on all files
run: pre-commit run --all-files --show-diff-on-failure --color=always

Loading
Loading