[CI] Build the Rust extension modules once per run instead of in every CUDA job (#33384)
This commit is contained in:
@@ -208,8 +208,31 @@ jobs:
|
||||
skip_pr_test_health_check: ${{ inputs.skip_pr_test_health_check == true }}
|
||||
secrets: inherit
|
||||
|
||||
# =============================================== Rust extensions ====================================================
|
||||
|
||||
# Unlike sgl-kernel, not gated on source changes: the cache key is the source
|
||||
# hash, so the job always runs but only compiles on a miss.
|
||||
rust-ext-build:
|
||||
needs: [check-changes, call-gate]
|
||||
# Ungated on the event, unlike the jobs above: a cache entry is visible to
|
||||
# every PR only if it was written from the default branch's ref, so every
|
||||
# main-ref run - schedule, dispatch, workflow_call - has to seed it.
|
||||
#
|
||||
# !cancelled() so a skipped call-gate does not take this job with it, since a
|
||||
# docs-only PR still installs sglang in every stage.
|
||||
if: |
|
||||
!cancelled() &&
|
||||
needs.check-changes.result == 'success' &&
|
||||
(needs.call-gate.result == 'success' || needs.call-gate.result == 'skipped')
|
||||
uses: ./.github/workflows/_pr-test-rust-ext-build.yml
|
||||
with:
|
||||
runs_on: x64-kernel-build-node
|
||||
git_ref: ${{ inputs.git_ref || '' }}
|
||||
skip_pr_test_health_check: ${{ inputs.skip_pr_test_health_check == true }}
|
||||
secrets: inherit
|
||||
|
||||
call-sgl-kernel-tests:
|
||||
needs: [check-changes, call-gate, sgl-kernel-build-wheels]
|
||||
needs: [check-changes, call-gate, sgl-kernel-build-wheels, rust-ext-build]
|
||||
if: |
|
||||
github.event_name != 'schedule' &&
|
||||
inputs.test_parallel_dispatch != true &&
|
||||
@@ -221,12 +244,13 @@ jobs:
|
||||
sgl_kernel: ${{ needs.check-changes.outputs.sgl_kernel }}
|
||||
git_ref: ${{ inputs.git_ref || '' }}
|
||||
skip_pr_test_health_check: ${{ inputs.skip_pr_test_health_check == true }}
|
||||
rust_ext_artifact: ${{ needs.rust-ext-build.outputs.artifact_name }}
|
||||
secrets: inherit
|
||||
|
||||
# =============================================== jit-kernel ====================================================
|
||||
|
||||
call-jit-kernel-tests:
|
||||
needs: [check-changes, call-gate, sgl-kernel-build-wheels]
|
||||
needs: [check-changes, call-gate, sgl-kernel-build-wheels, rust-ext-build]
|
||||
# Run on scheduled/parallel-dispatch runs (same pattern as the base-* stages) so the
|
||||
# jit_kernel suite is exercised on main 3x daily, not only on PRs that touch kernels/**.
|
||||
# check-changes already forces jit_kernel='true' on scheduled runs (run_all_tests).
|
||||
@@ -246,13 +270,14 @@ jobs:
|
||||
git_ref: ${{ inputs.git_ref || '' }}
|
||||
test_parallel_dispatch: ${{ inputs.test_parallel_dispatch == true && 'true' || 'false' }}
|
||||
skip_pr_test_health_check: ${{ inputs.skip_pr_test_health_check == true }}
|
||||
rust_ext_artifact: ${{ needs.rust-ext-build.outputs.artifact_name }}
|
||||
secrets: inherit
|
||||
|
||||
# =============================================== primary ====================================================
|
||||
|
||||
# Runs on 5090 (32GB, SM120)
|
||||
base-a-test-1-gpu-small:
|
||||
needs: [check-changes, call-gate, sgl-kernel-build-wheels]
|
||||
needs: [check-changes, call-gate, sgl-kernel-build-wheels, rust-ext-build]
|
||||
if: ${{ !failure() && !cancelled() }}
|
||||
uses: ./.github/workflows/_pr-test-stage.yml
|
||||
with:
|
||||
@@ -262,10 +287,11 @@ jobs:
|
||||
caller_inputs: ${{ toJson(inputs) }}
|
||||
partitions: ${{ needs.check-changes.outputs.partitions }}
|
||||
run_timeout_minutes: '10'
|
||||
rust_ext_artifact: ${{ needs.rust-ext-build.outputs.artifact_name }}
|
||||
secrets: inherit
|
||||
|
||||
base-a-test-cpu:
|
||||
needs: [check-changes, call-gate]
|
||||
needs: [check-changes, call-gate, rust-ext-build]
|
||||
if: |
|
||||
always() &&
|
||||
needs.check-changes.result == 'success' &&
|
||||
@@ -303,13 +329,29 @@ jobs:
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v5
|
||||
|
||||
# Needed by setuptools-rust to build the bundled native gRPC extension
|
||||
# (rust/sglang-grpc) when installing the main `sglang` wheel from source.
|
||||
# This stage compiled the workspace too - 7+ minutes per partition on
|
||||
# billable hosted minutes. rust-ext-build's modules need an older glibc than
|
||||
# this runner has, which is the safe direction, and both pin Python 3.10.
|
||||
- name: Download prebuilt Rust extensions
|
||||
id: rust_ext
|
||||
if: ${{ needs.rust-ext-build.outputs.artifact_name != '' }}
|
||||
continue-on-error: true
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: ${{ needs.rust-ext-build.outputs.artifact_name }}
|
||||
path: python/sglang/srt/
|
||||
|
||||
# Both only serve the fallback where this stage compiles the extensions
|
||||
# itself, so they follow the download's outcome, not the job output: an
|
||||
# expired artifact still needs cargo and a warm target dir here. Otherwise
|
||||
# rust-cache restores ~1 GB per partition for nothing, on an over-quota cache.
|
||||
- name: Install protoc + Rust toolchain
|
||||
if: ${{ steps.rust_ext.outcome != 'success' }}
|
||||
timeout-minutes: 10
|
||||
run: bash scripts/ci/utils/install_rust_protoc.sh
|
||||
|
||||
- name: Rust cache (rust/ workspace)
|
||||
if: ${{ steps.rust_ext.outcome != 'success' }}
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: rust
|
||||
@@ -321,6 +363,7 @@ jobs:
|
||||
timeout-minutes: 20
|
||||
env:
|
||||
UV_SYSTEM_PYTHON: "1"
|
||||
SGLANG_BUILD_RUST_EXTS: ${{ steps.rust_ext.outcome == 'success' && 'none' || '' }}
|
||||
run: |
|
||||
uv pip install -e "python[dev]" --index-strategy unsafe-best-match --prerelease allow
|
||||
|
||||
@@ -357,7 +400,7 @@ jobs:
|
||||
|
||||
# Runs on 5090 (32GB, SM120)
|
||||
base-b-test-1-gpu-small:
|
||||
needs: [check-changes, call-gate, wait-for-base-a, sgl-kernel-build-wheels]
|
||||
needs: [check-changes, call-gate, wait-for-base-a, sgl-kernel-build-wheels, rust-ext-build]
|
||||
if: ${{ !failure() && !cancelled() }}
|
||||
uses: ./.github/workflows/_pr-test-stage.yml
|
||||
with:
|
||||
@@ -367,11 +410,12 @@ jobs:
|
||||
caller_inputs: ${{ toJson(inputs) }}
|
||||
partitions: ${{ needs.check-changes.outputs.partitions }}
|
||||
run_timeout_minutes: '30'
|
||||
rust_ext_artifact: ${{ needs.rust-ext-build.outputs.artifact_name }}
|
||||
secrets: inherit
|
||||
|
||||
# Runs on H100 (80GB, SM90) - tests that don't pass on 5090 (FA3, FP8, high VRAM, etc.)
|
||||
base-b-test-1-gpu-large:
|
||||
needs: [check-changes, call-gate, wait-for-base-a, sgl-kernel-build-wheels]
|
||||
needs: [check-changes, call-gate, wait-for-base-a, sgl-kernel-build-wheels, rust-ext-build]
|
||||
if: ${{ !failure() && !cancelled() }}
|
||||
uses: ./.github/workflows/_pr-test-stage.yml
|
||||
with:
|
||||
@@ -382,10 +426,11 @@ jobs:
|
||||
partitions: ${{ needs.check-changes.outputs.partitions }}
|
||||
run_timeout_minutes: '30'
|
||||
timeout_per_file: '1800'
|
||||
rust_ext_artifact: ${{ needs.rust-ext-build.outputs.artifact_name }}
|
||||
secrets: inherit
|
||||
|
||||
base-b-test-2-gpu-large:
|
||||
needs: [check-changes, call-gate, wait-for-base-a, sgl-kernel-build-wheels]
|
||||
needs: [check-changes, call-gate, wait-for-base-a, sgl-kernel-build-wheels, rust-ext-build]
|
||||
if: ${{ !failure() && !cancelled() }}
|
||||
uses: ./.github/workflows/_pr-test-stage.yml
|
||||
with:
|
||||
@@ -395,10 +440,11 @@ jobs:
|
||||
caller_inputs: ${{ toJson(inputs) }}
|
||||
partitions: ${{ needs.check-changes.outputs.partitions }}
|
||||
run_timeout_minutes: '30'
|
||||
rust_ext_artifact: ${{ needs.rust-ext-build.outputs.artifact_name }}
|
||||
secrets: inherit
|
||||
|
||||
base-b-test-4-gpu-b200:
|
||||
needs: [check-changes, call-gate, wait-for-base-a, sgl-kernel-build-wheels]
|
||||
needs: [check-changes, call-gate, wait-for-base-a, sgl-kernel-build-wheels, rust-ext-build]
|
||||
if: ${{ !failure() && !cancelled() }}
|
||||
uses: ./.github/workflows/_pr-test-stage.yml
|
||||
with:
|
||||
@@ -408,10 +454,11 @@ jobs:
|
||||
caller_inputs: ${{ toJson(inputs) }}
|
||||
partitions: ${{ needs.check-changes.outputs.partitions }}
|
||||
run_timeout_minutes: '40'
|
||||
rust_ext_artifact: ${{ needs.rust-ext-build.outputs.artifact_name }}
|
||||
secrets: inherit
|
||||
|
||||
call-multimodal-gen-tests:
|
||||
needs: [check-changes, call-gate, sgl-kernel-build-wheels]
|
||||
needs: [check-changes, call-gate, sgl-kernel-build-wheels, rust-ext-build]
|
||||
if: |
|
||||
always() &&
|
||||
!cancelled() &&
|
||||
@@ -428,10 +475,11 @@ jobs:
|
||||
test_parallel_dispatch: ${{ inputs.test_parallel_dispatch == true && 'true' || 'false' }}
|
||||
caller_needs_failure: ${{ (needs.call-gate.result == 'failure' || needs.sgl-kernel-build-wheels.result == 'failure' || needs.check-changes.result == 'failure') && 'true' || 'false' }}
|
||||
skip_pr_test_health_check: ${{ inputs.skip_pr_test_health_check == true && 'true' || 'false' }}
|
||||
rust_ext_artifact: ${{ needs.rust-ext-build.outputs.artifact_name }}
|
||||
secrets: inherit
|
||||
|
||||
base-c-test-4-gpu-h100:
|
||||
needs: [check-changes, call-gate, wait-for-base-b, sgl-kernel-build-wheels]
|
||||
needs: [check-changes, call-gate, wait-for-base-b, sgl-kernel-build-wheels, rust-ext-build]
|
||||
if: ${{ !failure() && !cancelled() }}
|
||||
uses: ./.github/workflows/_pr-test-stage.yml
|
||||
with:
|
||||
@@ -441,10 +489,11 @@ jobs:
|
||||
caller_inputs: ${{ toJson(inputs) }}
|
||||
partitions: ${{ needs.check-changes.outputs.partitions }}
|
||||
run_timeout_minutes: '30'
|
||||
rust_ext_artifact: ${{ needs.rust-ext-build.outputs.artifact_name }}
|
||||
secrets: inherit
|
||||
|
||||
base-c-test-8-gpu-h200:
|
||||
needs: [check-changes, call-gate, wait-for-base-b, sgl-kernel-build-wheels]
|
||||
needs: [check-changes, call-gate, wait-for-base-b, sgl-kernel-build-wheels, rust-ext-build]
|
||||
if: ${{ !failure() && !cancelled() }}
|
||||
uses: ./.github/workflows/_pr-test-stage.yml
|
||||
with:
|
||||
@@ -461,10 +510,11 @@ jobs:
|
||||
# Server CUDA Graph warmup is combined into this step (warmup_server_models unset).
|
||||
warmup_deep_gemm_models: 'deepseek-ai/DeepSeek-V3-0324:8 deepseek-ai/DeepSeek-V3.2:8 zai-org/GLM-5-FP8:8 XiaomiMiMo/MiMo-V2-Flash:4 XiaomiMiMo/MiMo-V2.5:8'
|
||||
warmup_timeout_minutes: '60'
|
||||
rust_ext_artifact: ${{ needs.rust-ext-build.outputs.artifact_name }}
|
||||
secrets: inherit
|
||||
|
||||
base-c-test-8-gpu-h20:
|
||||
needs: [check-changes, call-gate, wait-for-base-b, sgl-kernel-build-wheels]
|
||||
needs: [check-changes, call-gate, wait-for-base-b, sgl-kernel-build-wheels, rust-ext-build]
|
||||
if: ${{ !failure() && !cancelled() }}
|
||||
uses: ./.github/workflows/_pr-test-stage.yml
|
||||
with:
|
||||
@@ -474,10 +524,11 @@ jobs:
|
||||
caller_inputs: ${{ toJson(inputs) }}
|
||||
partitions: ${{ needs.check-changes.outputs.partitions }}
|
||||
run_timeout_minutes: '30'
|
||||
rust_ext_artifact: ${{ needs.rust-ext-build.outputs.artifact_name }}
|
||||
secrets: inherit
|
||||
|
||||
base-c-test-deepep-4-gpu-h100:
|
||||
needs: [check-changes, call-gate, wait-for-base-b, sgl-kernel-build-wheels]
|
||||
needs: [check-changes, call-gate, wait-for-base-b, sgl-kernel-build-wheels, rust-ext-build]
|
||||
if: ${{ !failure() && !cancelled() }}
|
||||
uses: ./.github/workflows/_pr-test-stage.yml
|
||||
with:
|
||||
@@ -489,10 +540,11 @@ jobs:
|
||||
run_timeout_minutes: '30'
|
||||
warmup_deep_gemm_models: 'lmsys/sglang-ci-dsv3-test:4'
|
||||
warmup_server_models: 'lmsys/sglang-ci-dsv3-test:4'
|
||||
rust_ext_artifact: ${{ needs.rust-ext-build.outputs.artifact_name }}
|
||||
secrets: inherit
|
||||
|
||||
base-c-test-deepep-4-gpu-b200:
|
||||
needs: [check-changes, call-gate, wait-for-base-b, sgl-kernel-build-wheels]
|
||||
needs: [check-changes, call-gate, wait-for-base-b, sgl-kernel-build-wheels, rust-ext-build]
|
||||
if: ${{ !failure() && !cancelled() }}
|
||||
uses: ./.github/workflows/_pr-test-stage.yml
|
||||
with:
|
||||
@@ -503,10 +555,11 @@ jobs:
|
||||
partitions: ${{ needs.check-changes.outputs.partitions }}
|
||||
run_timeout_minutes: '30'
|
||||
timeout_per_file: '1800'
|
||||
rust_ext_artifact: ${{ needs.rust-ext-build.outputs.artifact_name }}
|
||||
secrets: inherit
|
||||
|
||||
base-c-test-deepep-8-gpu-h200:
|
||||
needs: [check-changes, call-gate, wait-for-base-b, sgl-kernel-build-wheels]
|
||||
needs: [check-changes, call-gate, wait-for-base-b, sgl-kernel-build-wheels, rust-ext-build]
|
||||
if: ${{ !failure() && !cancelled() }}
|
||||
uses: ./.github/workflows/_pr-test-stage.yml
|
||||
with:
|
||||
@@ -517,10 +570,11 @@ jobs:
|
||||
partitions: ${{ needs.check-changes.outputs.partitions }}
|
||||
run_timeout_minutes: '30'
|
||||
timeout_per_file: '1800'
|
||||
rust_ext_artifact: ${{ needs.rust-ext-build.outputs.artifact_name }}
|
||||
secrets: inherit
|
||||
|
||||
base-c-test-4-gpu-b200:
|
||||
needs: [check-changes, call-gate, wait-for-base-b, sgl-kernel-build-wheels]
|
||||
needs: [check-changes, call-gate, wait-for-base-b, sgl-kernel-build-wheels, rust-ext-build]
|
||||
if: ${{ !failure() && !cancelled() }}
|
||||
uses: ./.github/workflows/_pr-test-stage.yml
|
||||
with:
|
||||
@@ -531,10 +585,11 @@ jobs:
|
||||
partitions: ${{ needs.check-changes.outputs.partitions }}
|
||||
run_timeout_minutes: '30'
|
||||
timeout_per_file: '1800'
|
||||
rust_ext_artifact: ${{ needs.rust-ext-build.outputs.artifact_name }}
|
||||
secrets: inherit
|
||||
|
||||
base-c-test-4-gpu-gb300:
|
||||
needs: [check-changes, call-gate, wait-for-base-b, sgl-kernel-build-wheels]
|
||||
needs: [check-changes, call-gate, wait-for-base-b, sgl-kernel-build-wheels, rust-ext-build]
|
||||
if: ${{ !failure() && !cancelled() }}
|
||||
uses: ./.github/workflows/_pr-test-stage.yml
|
||||
with:
|
||||
@@ -545,8 +600,13 @@ jobs:
|
||||
partitions: ${{ needs.check-changes.outputs.partitions }}
|
||||
run_timeout_minutes: '30'
|
||||
timeout_per_file: '1800'
|
||||
# aarch64 has no prebuild, so this stage compiles during install - which also
|
||||
# makes it the only stage still covering that path. Keep it that way.
|
||||
rust_ext_artifact: ''
|
||||
secrets: inherit
|
||||
|
||||
# List every build and test job: `skipped` passes here, so an omission turns that
|
||||
# job's failure into a green run with no tests.
|
||||
pr-test-finish:
|
||||
needs:
|
||||
[
|
||||
@@ -557,6 +617,8 @@ jobs:
|
||||
sgl-kernel-build-wheels-arm,
|
||||
call-sgl-kernel-tests,
|
||||
|
||||
rust-ext-build,
|
||||
|
||||
wait-for-base-a,
|
||||
wait-for-base-b,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user