94057c3d3e
PR Test (NPU) / check-changes (push) Has been cancelled
PR Test (NPU) / pr-gate (push) Has been cancelled
PR Test (NPU) / set-image-config (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-4-npu-a3 (push) Has been cancelled
PR Test (NPU) / stage-b-test-16-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-1-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-2-npu-a3 (push) Has been cancelled
PR Test (Arm64) / pr-gate (push) Has been cancelled
PR Test (Arm64) / check-changes (push) Has been cancelled
PR Test (Arm64) / build-test (push) Has been cancelled
PR Test (sgl-router) / gate (push) Has been cancelled
PR Test (sgl-router) / tier-1 — lint (push) Has been cancelled
PR Test (sgl-router) / tier-2 — build + test (push) Has been cancelled
PR Test (sgl-router) / tier-3 — docker (placeholder) (push) Has been cancelled
PR Test (sgl-router) / tier-3 — k8s integration (push) Has been cancelled
PR Test (sgl-router) / tier-3 — e2e (push) Has been cancelled
PR Test (sgl-router) / finish (push) Has been cancelled
PR Test (NPU) / single-node-poc (map[name:qwen3_6_27b_w8a8_1p_in64k_out1k_50ms runner:linux-aarch64-a3-2 test_case:test/registered/ascend/performance/qwen3_6_27b/test_npu_qwen3_6_27b_w8a8_1p_in64k_out1k_50ms.py test_type:perf]) (push) Has been cancelled
PR Test (NPU) / pr-test-npu-finish (push) Has been cancelled
PR Test (Xeon) / pr-gate (push) Has been cancelled
PR Test (Xeon) / check-changes (push) Has been cancelled
PR Test (Xeon) / build-test (, xeon-gnr, base-b-test-cpu) (push) Has been cancelled
PR Test (XPU) / check-changes (push) Has been cancelled
PR Test (XPU) / pr-gate (push) Has been cancelled
PR Test (XPU) / stage-a-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / wait-for-stage-a (push) Has been cancelled
PR Test (XPU) / stage-b-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / finish (push) Has been cancelled
CI Model Inventory / build-inventory (push) Has been cancelled
Lint / lint (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Compilation Check (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Manual Policy (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Request Processing (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Summary (push) Has been cancelled
PR Test (SMG) / build-wheel (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on windows (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (x86_64 - auto) (push) Has been cancelled
PR Test (SMG) / python-unit-tests (push) Has been cancelled
PR Test (SMG) / unit-tests (push) Has been cancelled
PR Test (SMG) / benchmarks (push) Has been cancelled
PR Test (SMG) / chat-completions (push) Has been cancelled
PR Test (SMG) / chat-completions-4gpu (push) Has been cancelled
PR Test (SMG) / e2e (push) Has been cancelled
PR Test (SMG) / docker-build-test (push) Has been cancelled
PR Test (SMG) / k8s-integration (push) Has been cancelled
PR Test (SMG) / finish (push) Has been cancelled
PR Test (SMG) / summarize-benchmarks (push) Has been cancelled
Release SGLang Model Gateway Docker Image / publish (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Build SDist (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Upload to PyPI (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (aarch64, 12.9, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (x86_64, 12.9, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu129 (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (aarch64, 13.0, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (x86_64, 13.0, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu130 (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 700) (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 720) (push) Has been cancelled
Release SGLang Kernels / release-rocm700 (push) Has been cancelled
Release SGLang Kernels / release-rocm720 (push) Has been cancelled
Release SGLang Kernels / build-musa43 (43, 3.10) (push) Has been cancelled
Release SGLang Kernels / release-musa43 (push) Has been cancelled
435 lines
18 KiB
YAML
435 lines
18 KiB
YAML
name: PR Test (sgl-router)
|
|
|
|
# Trigger contract — modeled on `pr-test.yml`:
|
|
#
|
|
# * No `paths:` filter at the trigger level. The workflow ALWAYS
|
|
# fires on every PR synchronize / push, so the run record always
|
|
# appears as a check on the PR (no more "workflow silently didn't
|
|
# fire" mystery debugging). Path-based skip decisions are made
|
|
# inside the `sgl-router-gate` job below, where we can log the
|
|
# reason. Same for the `run-ci` label gate — moved off the
|
|
# workflow trigger and into the gate job so its outcome is
|
|
# observable.
|
|
#
|
|
# * `push` on `main` keeps firing so post-merge runs still record
|
|
# against the default branch.
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
branches: [main]
|
|
types: [opened, synchronize, reopened, labeled]
|
|
workflow_dispatch:
|
|
|
|
concurrency:
|
|
group: sgl-router-${{ github.event_name }}-${{ github.head_ref || github.ref_name || 'default' }}
|
|
cancel-in-progress: true
|
|
|
|
env:
|
|
SGLANG_IS_IN_CI: true
|
|
|
|
jobs:
|
|
# Stage 0 — decide whether to run the heavy tiers. Always runs
|
|
# (cheap, ubuntu-latest), and emits a single `should_run` output
|
|
# consumed by every tier below. Reasons it might evict downstream
|
|
# work:
|
|
# * `pull_request` event without the `run-ci` label (budget gate)
|
|
# * No files matching the sgl-router paths changed in this PR
|
|
# Either outcome is logged on the gate job's page, so operators can
|
|
# see *why* the tiers were skipped instead of guessing.
|
|
sgl-router-gate:
|
|
name: gate
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
should_run: ${{ steps.decide.outputs.should_run }}
|
|
paths_changed: ${{ steps.paths.outputs.sgl_router }}
|
|
has_run_ci_label: ${{ steps.label.outputs.has_run_ci }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
# `dorny/paths-filter` computes the diff against the PR base
|
|
# (for pull_request) or the push's `before` SHA (for push) and
|
|
# exposes `sgl_router=true|false` on whether any tracked path
|
|
# changed. Replaces the old workflow-level `paths:` filter so
|
|
# the gate is observable.
|
|
- name: Detect sgl-router path changes
|
|
id: paths
|
|
uses: dorny/paths-filter@v3
|
|
with:
|
|
filters: |
|
|
sgl_router:
|
|
- 'experimental/sgl-router/**'
|
|
- '.github/workflows/pr-test-sgl-router.yml'
|
|
- 'scripts/ci/cuda/ci_install_dependency.sh'
|
|
# `run-ci` label gate. Cheap workflow runs (e.g. docs-only PRs
|
|
# that happen to touch the sgl-router dir) still need the
|
|
# opt-in label before consuming the H100 / kind tiers below.
|
|
# `push` events on main and `workflow_dispatch` skip this gate.
|
|
- name: Check run-ci label
|
|
id: label
|
|
run: |
|
|
if [[ "${{ github.event_name }}" != "pull_request" ]]; then
|
|
echo "has_run_ci=true" >> "$GITHUB_OUTPUT"
|
|
echo "Non-PR event (${{ github.event_name }}); label gate bypassed."
|
|
exit 0
|
|
fi
|
|
if [[ "${{ contains(github.event.pull_request.labels.*.name, 'run-ci') }}" == "true" ]]; then
|
|
echo "has_run_ci=true" >> "$GITHUB_OUTPUT"
|
|
echo "PR has run-ci label; downstream tiers will run."
|
|
else
|
|
echo "has_run_ci=false" >> "$GITHUB_OUTPUT"
|
|
echo "::warning::PR is missing the 'run-ci' label; skipping sgl-router tiers. Apply the label to opt in."
|
|
fi
|
|
- name: Decide
|
|
id: decide
|
|
run: |
|
|
paths='${{ steps.paths.outputs.sgl_router }}'
|
|
label='${{ steps.label.outputs.has_run_ci }}'
|
|
if [[ "$paths" == "true" && "$label" == "true" ]]; then
|
|
echo "should_run=true" >> "$GITHUB_OUTPUT"
|
|
echo "Both path filter and run-ci label match; running tiers."
|
|
else
|
|
echo "should_run=false" >> "$GITHUB_OUTPUT"
|
|
echo "Skipping tiers (paths_changed=$paths, has_run_ci=$label)."
|
|
fi
|
|
|
|
sgl-router-lint:
|
|
name: tier-1 — lint
|
|
needs: sgl-router-gate
|
|
if: needs.sgl-router-gate.outputs.should_run == 'true'
|
|
runs-on: ubuntu-latest
|
|
env:
|
|
# Scoped per-job (not workflow-wide) to avoid SMG's documented breakage
|
|
# of self-hosted-runner pip installs that compile Rust extensions.
|
|
RUSTC_WRAPPER: sccache
|
|
SCCACHE_GHA_ENABLED: "true"
|
|
# Supply-chain guard: deny.toml allowlists the dynamo git source but
|
|
# cannot pin a SHA. Bumps to this constant must be a deliberate PR.
|
|
DYNAMO_TOKENIZERS_EXPECTED_REV: "1efdd4dcb901caeae636131321094090d252c8d6"
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Verify dynamo-* SHA pin
|
|
run: |
|
|
set -euo pipefail
|
|
revs=$(grep -E '^dynamo-[a-z]+[[:space:]]*=.*\brev[[:space:]]*=' experimental/sgl-router/Cargo.toml \
|
|
| sed -E 's/.*rev[[:space:]]*=[[:space:]]*"([^"]+)".*/\1/')
|
|
if [ -z "${revs:-}" ]; then
|
|
echo "::error::no dynamo-* git deps with rev= found in experimental/sgl-router/Cargo.toml"
|
|
exit 1
|
|
fi
|
|
count=0
|
|
while IFS= read -r r; do
|
|
count=$((count + 1))
|
|
if [ "$r" != "$DYNAMO_TOKENIZERS_EXPECTED_REV" ]; then
|
|
echo "::error::dynamo-* SHA pin mismatch in experimental/sgl-router/Cargo.toml"
|
|
echo " expected: $DYNAMO_TOKENIZERS_EXPECTED_REV"
|
|
echo " actual: $r"
|
|
echo "All revs found:"
|
|
echo "$revs" | sed 's/^/ /'
|
|
exit 1
|
|
fi
|
|
done <<< "$revs"
|
|
echo "dynamo-* SHA pin OK: $count entries all at $DYNAMO_TOKENIZERS_EXPECTED_REV"
|
|
|
|
# sccache install is best-effort: the GitHub release CDN intermittently
|
|
# returns 5xx and the action's built-in retry is shallow. If it fails,
|
|
# we unset RUSTC_WRAPPER below and proceed without compile caching —
|
|
# rust-cache still covers the bulk of warm-cache wins.
|
|
- name: Configure sccache
|
|
id: sccache
|
|
continue-on-error: true
|
|
uses: mozilla-actions/sccache-action@v0.0.9
|
|
with:
|
|
version: "v0.12.0"
|
|
disable_annotations: true
|
|
|
|
- name: Disable sccache if install failed
|
|
if: steps.sccache.outcome != 'success'
|
|
run: |
|
|
echo "::warning::sccache install failed (${{ steps.sccache.outcome }}); proceeding without compile caching"
|
|
echo "RUSTC_WRAPPER=" >> "$GITHUB_ENV"
|
|
|
|
- name: Rust cache
|
|
uses: Swatinem/rust-cache@v2
|
|
with:
|
|
workspaces: experimental/sgl-router
|
|
shared-key: "sgl-router-cache"
|
|
cache-all-crates: true
|
|
cache-on-failure: true
|
|
save-if: ${{ github.ref == 'refs/heads/main' }}
|
|
|
|
- name: cargo check
|
|
working-directory: experimental/sgl-router
|
|
run: cargo check --all-targets
|
|
|
|
- name: cargo clippy
|
|
working-directory: experimental/sgl-router
|
|
run: cargo clippy --all-targets -- -D warnings
|
|
|
|
- name: cargo fmt
|
|
working-directory: experimental/sgl-router
|
|
run: |
|
|
rustup toolchain install nightly --profile minimal --component rustfmt
|
|
cargo +nightly fmt -- --check
|
|
|
|
# cargo-deny 0.19.6+ required for CVSS 4.0 parsing.
|
|
- name: Install cargo-deny
|
|
run: cargo install --locked cargo-deny@0.19.6
|
|
|
|
- name: cargo deny check
|
|
working-directory: experimental/sgl-router
|
|
run: cargo deny check licenses bans sources advisories
|
|
|
|
- name: Show sccache stats
|
|
if: always() && steps.sccache.outcome == 'success'
|
|
run: sccache --show-stats
|
|
|
|
sgl-router-build-and-test:
|
|
name: tier-2 — build + test
|
|
needs: [sgl-router-gate, sgl-router-lint]
|
|
if: needs.sgl-router-gate.outputs.should_run == 'true'
|
|
runs-on: ubuntu-latest
|
|
env:
|
|
RUSTC_WRAPPER: sccache
|
|
SCCACHE_GHA_ENABLED: "true"
|
|
timeout-minutes: 30
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Install OS deps (libssl, pkg-config)
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y libssl-dev pkg-config
|
|
|
|
# sccache install is best-effort: the GitHub release CDN intermittently
|
|
# returns 5xx and the action's built-in retry is shallow. If it fails,
|
|
# we unset RUSTC_WRAPPER below and proceed without compile caching —
|
|
# rust-cache still covers the bulk of warm-cache wins.
|
|
- name: Configure sccache
|
|
id: sccache
|
|
continue-on-error: true
|
|
uses: mozilla-actions/sccache-action@v0.0.9
|
|
with:
|
|
version: "v0.12.0"
|
|
disable_annotations: true
|
|
|
|
- name: Disable sccache if install failed
|
|
if: steps.sccache.outcome != 'success'
|
|
run: |
|
|
echo "::warning::sccache install failed (${{ steps.sccache.outcome }}); proceeding without compile caching"
|
|
echo "RUSTC_WRAPPER=" >> "$GITHUB_ENV"
|
|
|
|
- name: Rust cache
|
|
uses: Swatinem/rust-cache@v2
|
|
with:
|
|
workspaces: experimental/sgl-router
|
|
shared-key: "sgl-router-cache"
|
|
cache-all-crates: true
|
|
cache-on-failure: true
|
|
save-if: ${{ github.ref == 'refs/heads/main' }}
|
|
|
|
- name: cargo build (record wall time)
|
|
working-directory: experimental/sgl-router
|
|
run: |
|
|
START=$(date +%s)
|
|
cargo build --release --all-targets
|
|
END=$(date +%s)
|
|
BUILD_SECONDS=$((END - START))
|
|
echo "tier_2_build_duration_seconds=${BUILD_SECONDS}" >> "$GITHUB_ENV"
|
|
echo "::notice title=Tier-2 build duration::${BUILD_SECONDS}s"
|
|
|
|
- name: cargo test
|
|
working-directory: experimental/sgl-router
|
|
# Skip the tokenizer parity_matrix test here: ubuntu-latest has
|
|
# no HuggingFace cache, so the matrix would hard-fail (see the
|
|
# test docstring). The e2e job runs it after pytest populates
|
|
# the Qwen3-0.6B tokenizer.json. Filter is matched against the
|
|
# full test path `tokenizer::parity::parity_matrix`; substring
|
|
# `parity_matrix` is unique to that test.
|
|
run: cargo test --release -- --skip parity_matrix
|
|
|
|
# Regenerate the cross-impl block-hash parity fixture and fail if it
|
|
# differs from the committed file. The Python script replicates
|
|
# SGLang's `radix_cache.hash_page` algorithm verbatim (no
|
|
# `import sglang`); a diff here means EITHER the Rust port's algorithm
|
|
# drifted from the script, OR the script drifted from SGLang's actual
|
|
# code — in both cases the operator must investigate and re-commit
|
|
# the fixture in the same PR as the algorithm change.
|
|
#
|
|
# `set -euo pipefail` makes a Python-side failure (syntax error,
|
|
# missing import) cause this step to fail instead of falling
|
|
# through to a no-diff "pass" when no fixture was actually
|
|
# regenerated.
|
|
- name: kv_events hash parity fixture (drift check)
|
|
working-directory: experimental/sgl-router
|
|
run: |
|
|
set -euo pipefail
|
|
python3 tests/scripts/generate_kv_events_hash_parity.py
|
|
if ! git diff --exit-code -- tests/fixtures/kv_events_hash_parity.json; then
|
|
echo "::error::kv_events hash parity fixture drifted." \
|
|
"Re-run experimental/sgl-router/tests/scripts/generate_kv_events_hash_parity.py" \
|
|
"and commit the updated tests/fixtures/kv_events_hash_parity.json."
|
|
exit 1
|
|
fi
|
|
|
|
- name: Show sccache stats
|
|
if: always() && steps.sccache.outcome == 'success'
|
|
run: sccache --show-stats
|
|
|
|
- name: Summary
|
|
if: always()
|
|
run: |
|
|
echo "## Tier-2 results" >> "$GITHUB_STEP_SUMMARY"
|
|
echo "- Build duration: \`${tier_2_build_duration_seconds:-(not recorded)}\` s" >> "$GITHUB_STEP_SUMMARY"
|
|
|
|
sgl-router-docker-build-test:
|
|
name: tier-3 — docker (placeholder)
|
|
needs: [sgl-router-gate, sgl-router-build-and-test]
|
|
if: needs.sgl-router-gate.outputs.should_run == 'true'
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 15
|
|
steps:
|
|
- name: Placeholder
|
|
run: |
|
|
echo "docker-build-test not implemented yet."
|
|
exit 0
|
|
|
|
# tier-3 k8s integration is decoupled from tier-3 e2e: each runs on a
|
|
# different runner type (ubuntu kind cluster vs H100), each manages its
|
|
# own test scope (k8s_integration/ vs everything-else-in-e2e), and
|
|
# each is allowed to fail without blocking the other. They both still
|
|
# gate on tier-2's build+test passing — a Rust compile failure blocks
|
|
# the GPU/cluster runners from spinning up.
|
|
sgl-router-k8s-integration:
|
|
name: tier-3 — k8s integration
|
|
needs: [sgl-router-gate, sgl-router-build-and-test]
|
|
if: needs.sgl-router-gate.outputs.should_run == 'true'
|
|
runs-on: ubuntu-22.04
|
|
timeout-minutes: 30
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- name: Setup Docker buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
- name: Install kind
|
|
run: |
|
|
curl -Lo /tmp/kind https://kind.sigs.k8s.io/dl/v0.24.0/kind-linux-amd64
|
|
chmod +x /tmp/kind && sudo mv /tmp/kind /usr/local/bin/kind
|
|
- name: Install kubectl
|
|
run: |
|
|
curl -Lo /tmp/kubectl https://dl.k8s.io/release/v1.31.0/bin/linux/amd64/kubectl
|
|
chmod +x /tmp/kubectl && sudo mv /tmp/kubectl /usr/local/bin/kubectl
|
|
- name: Build router image
|
|
run: docker build -t sgl-router:e2e -f experimental/sgl-router/tests/e2e/k8s_integration/Dockerfile.router .
|
|
- name: Build fake_worker image
|
|
run: |
|
|
docker build -t sgl-router-fake-worker:e2e \
|
|
-f experimental/sgl-router/tests/e2e/k8s_integration/Dockerfile.fake_worker \
|
|
experimental/sgl-router/tests/e2e/k8s_integration/
|
|
- name: Bootstrap kind + deploy
|
|
run: bash experimental/sgl-router/tests/e2e/k8s_integration/setup.sh
|
|
- name: Set up Python
|
|
run: |
|
|
python3 -m venv /tmp/e2e-venv
|
|
/tmp/e2e-venv/bin/pip install -r experimental/sgl-router/tests/e2e/k8s_integration/requirements.txt
|
|
- name: Run E2E
|
|
run: /tmp/e2e-venv/bin/pytest experimental/sgl-router/tests/e2e/k8s_integration/ -v --tb=short
|
|
- name: Dump cluster + router diagnostics on failure
|
|
if: failure()
|
|
run: |
|
|
set +e
|
|
kubectl -n sgl-router-test get pods -o wide
|
|
kubectl -n sgl-router-test describe pod -l app=sgl-router
|
|
kubectl -n sgl-router-test describe pod -l app=sglang
|
|
kubectl -n sgl-router-test logs deploy/sgl-router --tail=300
|
|
kubectl -n sgl-router-test logs deploy/sgl-router --tail=300 --previous
|
|
kubectl -n sgl-router-test get events --sort-by=.lastTimestamp
|
|
kubectl -n sgl-router-test get endpointslices -o wide
|
|
kubectl -n sgl-router-test get svc
|
|
true
|
|
|
|
sgl-router-e2e:
|
|
name: tier-3 — e2e
|
|
needs: [sgl-router-gate, sgl-router-build-and-test]
|
|
if: needs.sgl-router-gate.outputs.should_run == 'true'
|
|
runs-on: 2-gpu-h100
|
|
timeout-minutes: 45
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- name: Install Rust toolchain
|
|
run: bash scripts/ci/utils/install_rust_protoc.sh
|
|
- name: Rust cache
|
|
uses: Swatinem/rust-cache@v2
|
|
with:
|
|
workspaces: experimental/sgl-router
|
|
shared-key: "sgl-router-cache"
|
|
- name: cargo build (release)
|
|
working-directory: experimental/sgl-router
|
|
run: |
|
|
source "$HOME/.cargo/env"
|
|
cargo build --release
|
|
|
|
# Install SGLang from the local checkout in editable mode (no PyPI
|
|
# version pin) — mirrors `pr-test-rust.yml` so the router e2e runs
|
|
# against whatever SGLang version is on the branch. Replaces the
|
|
# previous `pip install sglang[srt]==X.Y.Z` pin, which forced the
|
|
# e2e to test against a stale wheel and would silently miss any
|
|
# new ServerArgs field (e.g. `disaggregation_mode` /
|
|
# `disaggregation_bootstrap_port`) added in the branch.
|
|
- name: Install SGLang dependencies
|
|
run: |
|
|
bash scripts/ci/cuda/ci_install_dependency.sh
|
|
|
|
- name: Install e2e test dependencies
|
|
run: |
|
|
python3 -m pip install -r experimental/sgl-router/tests/e2e/requirements.txt
|
|
|
|
# IMPORTANT: --ignore=tests/e2e/k8s_integration. The k8s integration
|
|
# suite is owned by the `sgl-router-k8s-integration` job which has
|
|
# kind + kubectl installed and a real cluster running. The e2e GPU
|
|
# runner has neither, so pytest's recursive collection of
|
|
# tests/e2e/ would ERROR every k8s test at setup. Both tiers must
|
|
# be allowed to fail independently — k8s flakes (cluster boot,
|
|
# image pull) must not surface as e2e failures on H100, and e2e
|
|
# flakes (model load, HF auth) must not surface as k8s failures.
|
|
- name: Run e2e
|
|
working-directory: experimental/sgl-router
|
|
env:
|
|
HF_TOKEN: ${{ secrets.HF_TOKEN }}
|
|
run: |
|
|
python3 -m pytest tests/e2e/ -v -s --tb=short \
|
|
--ignore=tests/e2e/k8s_integration
|
|
|
|
- name: Tokenizer parity matrix (uses HF cache populated by e2e)
|
|
working-directory: experimental/sgl-router
|
|
env:
|
|
HF_TOKEN: ${{ secrets.HF_TOKEN }}
|
|
run: |
|
|
source "$HOME/.cargo/env"
|
|
cargo test --release --test component tokenizer::parity
|
|
|
|
sgl-router-finish:
|
|
name: finish
|
|
needs:
|
|
- sgl-router-gate
|
|
- sgl-router-lint
|
|
- sgl-router-build-and-test
|
|
- sgl-router-docker-build-test
|
|
- sgl-router-k8s-integration
|
|
- sgl-router-e2e
|
|
# `always()` lets `finish` run after upstream `skipped` outcomes
|
|
# (when the gate decided to skip). The downstream-skipped path is
|
|
# an explicit success — the workflow was correctly bypassed for a
|
|
# PR that didn't need full CI. The downstream-failure /
|
|
# downstream-cancelled path is a real fail. We also accept the
|
|
# gate's `skipped` (impossible today, kept for symmetry) and
|
|
# require the gate itself to have succeeded.
|
|
if: |
|
|
always() &&
|
|
needs.sgl-router-gate.result == 'success' &&
|
|
!contains(needs.*.result, 'failure') &&
|
|
!contains(needs.*.result, 'cancelled')
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: All required checks completed
|
|
run: echo "OK"
|