diff --git a/.github/actions/download-rust-ext/action.yml b/.github/actions/download-rust-ext/action.yml new file mode 100644 index 000000000..0980a4f10 --- /dev/null +++ b/.github/actions/download-rust-ext/action.yml @@ -0,0 +1,70 @@ +name: 'Download prebuilt Rust extensions' +description: > + Put rust-ext-build's PyO3 extension modules in the checkout and set + SGLANG_BUILD_RUST_EXTS=none for the job, so install skips the cargo build. + Sets nothing when neither source has them, leaving install to compile. + +inputs: + artifact_name: + description: "rust-ext-build's artifact in this run; empty uses only the cache." + required: false + default: '' + cache_key_prefix: + description: 'Must match what _pr-test-rust-ext-build.yml saves under.' + required: false + default: rust-ext-x86_64 + +outputs: + hit: + description: "'true' when the modules are in place, for callers that install a Rust toolchain only to build them." + value: ${{ steps.decide.outputs.hit }} + +runs: + using: composite + steps: + # continue-on-error: the artifact expires in a day, so a re-run falls through + # to the cache below. + - name: Download prebuilt Rust extensions + id: artifact + if: inputs.artifact_name != '' + continue-on-error: true + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.artifact_name }} + path: python/sglang/srt/ + + # Gated with the restore below, not run unconditionally: a job whose artifact + # arrived never reads the cache, so it should not pay an apt-get for it. The + # self-hosted images ship without zstd, and the entries were saved with it. + - name: Ensure zstd so the cache entry is readable + if: steps.artifact.outcome != 'success' + shell: bash + run: bash scripts/ci/utils/ensure_zstd.sh + + # Second, not first: the cache is evictable and this repo sits at its 10 GB + # limit. A run reads its own branch's entries plus the default branch's, so + # seed-rust-ext-cache.yml and the branch's own rust-ext-build both land here. + - name: Restore prebuilt Rust extensions from cache + id: cache + if: steps.artifact.outcome != 'success' + uses: actions/cache/restore@v4 + with: + path: python/sglang/srt/*/_core*.so + key: ${{ inputs.cache_key_prefix }}-${{ hashFiles('rust/**', 'python/setup.py') }} + + # Job-wide, but only setup.py reads it, and only while building. + # Whether the modules suit this interpreter is not decided here: + # require_prebuilt_rust_exts checks them against the local EXT_SUFFIX and + # clears this back to a source build on a mismatch. + - name: Decide whether to skip the cargo build + id: decide + shell: bash + run: | + set -uo pipefail + if [ "${{ steps.artifact.outcome }}" = "success" ] \ + || [ "${{ steps.cache.outputs.cache-hit }}" = "true" ]; then + echo "hit=true" >> "$GITHUB_OUTPUT" + echo "SGLANG_BUILD_RUST_EXTS=none" >> "$GITHUB_ENV" + else + echo "hit=false" >> "$GITHUB_OUTPUT" + fi diff --git a/.github/workflows/_pr-test-rust-ext-build.yml b/.github/workflows/_pr-test-rust-ext-build.yml index b60e0c4cb..125d39fb1 100644 --- a/.github/workflows/_pr-test-rust-ext-build.yml +++ b/.github/workflows/_pr-test-rust-ext-build.yml @@ -88,6 +88,11 @@ jobs: - uses: ./.github/actions/check-maintenance + # A no-op on the hosted default, which ships zstd; here for whatever + # restore_runs_on is pointed at, since a reader without it sees no entry. + - name: Ensure zstd so the saved entry is readable + run: bash scripts/ci/utils/ensure_zstd.sh + # setup.py counts because it selects which crates get built. pyproject.toml # is left out - it churns on bumps that cannot affect these modules. - name: Restore built modules @@ -182,21 +187,10 @@ jobs: MAX_GLIBC: ${{ inputs.max_glibc }} run: bash scripts/ci/utils/stage_rust_ext_modules.sh - # actions/cache identifies an entry by key *and* a version derived from the - # compression tool, so a runner without zstd saves what the hosted restore job - # cannot find - a silent miss every run. Warn, not fail: a cold build still works. + # Without it the entry saved below lands under a version no reader with zstd + # can find. This runner's image ships without it. - name: Ensure zstd so the restore job can read what this job saves - run: | - set -uo pipefail - if ! command -v zstd >/dev/null 2>&1; then - if [ "$(id -u)" = "0" ]; then SUDO="" - elif command -v sudo >/dev/null 2>&1; then SUDO="sudo" - else SUDO=""; fi - ${SUDO} apt-get update || true - ${SUDO} apt-get install -y --no-install-recommends zstd || true - fi - command -v zstd >/dev/null 2>&1 \ - || echo "::warning::zstd unavailable on ${RUNNER_NAME:-this runner}; the cache entry saved below will not be readable by the restore job" + run: bash scripts/ci/utils/ensure_zstd.sh # After the verify step, so a rejected build cannot poison this key for every # later run. diff --git a/.github/workflows/_pr-test-stage-cpu.yml b/.github/workflows/_pr-test-stage-cpu.yml index 4834984d2..0972a2cc6 100644 --- a/.github/workflows/_pr-test-stage-cpu.yml +++ b/.github/workflows/_pr-test-stage-cpu.yml @@ -29,7 +29,7 @@ on: type: string required: true rust_ext_artifact: - description: 'Artifact of prebuilt Rust extension modules, from rust-ext-build. Empty, or a download that fails, means this stage compiles them during install.' + description: 'Artifact of prebuilt Rust extension modules, from rust-ext-build. Empty, or a download that fails, falls back to the cache; a miss there compiles during install.' type: string default: '' @@ -85,26 +85,22 @@ jobs: # 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 + - uses: ./.github/actions/download-rust-ext id: rust_ext - if: ${{ inputs.rust_ext_artifact != '' }} - continue-on-error: true - uses: actions/download-artifact@v4 with: - name: ${{ inputs.rust_ext_artifact }} - path: python/sglang/srt/ + artifact_name: ${{ inputs.rust_ext_artifact }} # 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. + # itself, so they follow whether the modules arrived, not the producer job's + # output. 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' }} + if: ${{ steps.rust_ext.outputs.hit != 'true' }} timeout-minutes: 10 run: bash scripts/ci/utils/install_rust_protoc.sh - name: Rust cache (rust/ workspace) - if: ${{ steps.rust_ext.outcome != 'success' }} + if: ${{ steps.rust_ext.outputs.hit != 'true' }} uses: Swatinem/rust-cache@v2 with: workspaces: rust @@ -116,7 +112,6 @@ 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 diff --git a/.github/workflows/_pr-test-stage.yml b/.github/workflows/_pr-test-stage.yml index f0861b30c..15057160e 100644 --- a/.github/workflows/_pr-test-stage.yml +++ b/.github/workflows/_pr-test-stage.yml @@ -55,9 +55,13 @@ on: type: string default: '' rust_ext_artifact: - description: 'Artifact of prebuilt Rust extension modules, from rust-ext-build. Empty, or a download that fails, means this stage compiles them during install.' + description: 'Artifact of prebuilt Rust extension modules, from rust-ext-build. Empty, or a download that fails, falls back to the cache; a miss there compiles during install.' type: string default: '' + skip_prebuilt_rust_ext: + description: 'Take neither the artifact nor the cache, and compile during install. For a stage no prebuild targets: the cache key is arch-blind, so an aarch64 stage would be handed x86_64 modules.' + type: boolean + default: false # Mirror pr-test.yml top-level env. Reusable workflows do NOT inherit caller's # workflow-level env across the workflow_call boundary, so anything pr-test.yml @@ -124,23 +128,15 @@ jobs: merge-multiple: true pattern: wheel-python3.10-cuda* - # continue-on-error: the artifact expires in a day, so a later re-run just - # compiles during install. download-artifact creates srt/server/, which - # exists only as build output. - - name: Download prebuilt Rust extensions - id: rust_ext - if: ${{ inputs.rust_ext_artifact != '' }} - continue-on-error: true - uses: actions/download-artifact@v4 + - uses: ./.github/actions/download-rust-ext + if: ${{ !inputs.skip_prebuilt_rust_ext }} with: - name: ${{ inputs.rust_ext_artifact }} - path: python/sglang/srt/ + artifact_name: ${{ inputs.rust_ext_artifact }} - name: Install dependencies timeout-minutes: ${{ fromJson(steps.rc.outputs.install_timeout) }} env: GRACE_BLACKWELL: ${{ steps.rc.outputs.grace_blackwell || '0' }} - SGLANG_BUILD_RUST_EXTS: ${{ steps.rust_ext.outcome == 'success' && 'none' || '' }} run: | CUSTOM_BUILD_SGL_KERNEL=${{ fromJson(inputs.check_changes).sgl_kernel }} bash ${{ steps.rc.outputs.install }} diff --git a/.github/workflows/pr-test-jit-kernel.yml b/.github/workflows/pr-test-jit-kernel.yml index 5d8c59316..18ddd537d 100644 --- a/.github/workflows/pr-test-jit-kernel.yml +++ b/.github/workflows/pr-test-jit-kernel.yml @@ -10,7 +10,7 @@ on: required: true type: string rust_ext_artifact: - description: 'Artifact of prebuilt Rust extension modules, from rust-ext-build. Empty, or a download that fails, means this job compiles them during install.' + description: 'Artifact of prebuilt Rust extension modules, from rust-ext-build. Empty, or a download that fails, falls back to the cache; a miss there compiles during install.' type: string default: '' runner_config: @@ -71,19 +71,12 @@ jobs: merge-multiple: true pattern: wheel-python3.10-cuda13.0 - - name: Download prebuilt Rust extensions - id: rust_ext - if: ${{ inputs.rust_ext_artifact != '' }} - continue-on-error: true - uses: actions/download-artifact@v4 + - uses: ./.github/actions/download-rust-ext with: - name: ${{ inputs.rust_ext_artifact }} - path: python/sglang/srt/ + artifact_name: ${{ inputs.rust_ext_artifact }} - name: Install dependencies timeout-minutes: 20 - env: - SGLANG_BUILD_RUST_EXTS: ${{ steps.rust_ext.outcome == 'success' && 'none' || '' }} run: | CUSTOM_BUILD_SGL_KERNEL=${{ inputs.sgl_kernel }} bash scripts/ci/cuda/ci_install_dependency.sh diffusion @@ -120,19 +113,12 @@ jobs: merge-multiple: true pattern: wheel-python3.10-cuda13.0 - - name: Download prebuilt Rust extensions - id: rust_ext - if: ${{ inputs.rust_ext_artifact != '' }} - continue-on-error: true - uses: actions/download-artifact@v4 + - uses: ./.github/actions/download-rust-ext with: - name: ${{ inputs.rust_ext_artifact }} - path: python/sglang/srt/ + artifact_name: ${{ inputs.rust_ext_artifact }} - name: Install dependencies timeout-minutes: 20 - env: - SGLANG_BUILD_RUST_EXTS: ${{ steps.rust_ext.outcome == 'success' && 'none' || '' }} run: | CUSTOM_BUILD_SGL_KERNEL=${{ inputs.sgl_kernel }} bash scripts/ci/cuda/ci_install_dependency.sh diffusion @@ -171,19 +157,12 @@ jobs: merge-multiple: true pattern: wheel-python3.10-cuda13.0 - - name: Download prebuilt Rust extensions - id: rust_ext - if: ${{ inputs.rust_ext_artifact != '' }} - continue-on-error: true - uses: actions/download-artifact@v4 + - uses: ./.github/actions/download-rust-ext with: - name: ${{ inputs.rust_ext_artifact }} - path: python/sglang/srt/ + artifact_name: ${{ inputs.rust_ext_artifact }} - name: Install dependencies timeout-minutes: 20 - env: - SGLANG_BUILD_RUST_EXTS: ${{ steps.rust_ext.outcome == 'success' && 'none' || '' }} run: | CUSTOM_BUILD_SGL_KERNEL=${{ inputs.sgl_kernel }} bash scripts/ci/cuda/ci_install_dependency.sh diffusion @@ -222,19 +201,12 @@ jobs: merge-multiple: true pattern: wheel-python3.10-cuda13.0 - - name: Download prebuilt Rust extensions - id: rust_ext - if: ${{ inputs.rust_ext_artifact != '' }} - continue-on-error: true - uses: actions/download-artifact@v4 + - uses: ./.github/actions/download-rust-ext with: - name: ${{ inputs.rust_ext_artifact }} - path: python/sglang/srt/ + artifact_name: ${{ inputs.rust_ext_artifact }} - name: Install dependencies timeout-minutes: 20 - env: - SGLANG_BUILD_RUST_EXTS: ${{ steps.rust_ext.outcome == 'success' && 'none' || '' }} run: | CUSTOM_BUILD_SGL_KERNEL=${{ inputs.sgl_kernel }} bash scripts/ci/cuda/ci_install_dependency.sh diffusion diff --git a/.github/workflows/pr-test-multimodal-gen.yml b/.github/workflows/pr-test-multimodal-gen.yml index eea4b4ba3..5c3a7f897 100644 --- a/.github/workflows/pr-test-multimodal-gen.yml +++ b/.github/workflows/pr-test-multimodal-gen.yml @@ -10,7 +10,7 @@ on: required: true type: string rust_ext_artifact: - description: 'Artifact of prebuilt Rust extension modules, from rust-ext-build. Empty, or a download that fails, means this job compiles them during install.' + description: 'Artifact of prebuilt Rust extension modules, from rust-ext-build. Empty, or a download that fails, falls back to the cache; a miss there compiles during install.' type: string default: '' runner_config: @@ -106,19 +106,12 @@ jobs: merge-multiple: true pattern: wheel-python3.10-cuda* - - name: Download prebuilt Rust extensions - id: rust_ext - if: ${{ inputs.rust_ext_artifact != '' }} - continue-on-error: true - uses: actions/download-artifact@v4 + - uses: ./.github/actions/download-rust-ext with: - name: ${{ inputs.rust_ext_artifact }} - path: python/sglang/srt/ + artifact_name: ${{ inputs.rust_ext_artifact }} - name: Install dependencies timeout-minutes: 20 - env: - SGLANG_BUILD_RUST_EXTS: ${{ steps.rust_ext.outcome == 'success' && 'none' || '' }} run: | CUSTOM_BUILD_SGL_KERNEL=${{inputs.sgl_kernel}} bash scripts/ci/cuda/ci_install_dependency.sh diffusion - name: Run diffusion server tests @@ -183,19 +176,12 @@ jobs: merge-multiple: true pattern: wheel-python3.10-cuda* - - name: Download prebuilt Rust extensions - id: rust_ext - if: ${{ inputs.rust_ext_artifact != '' }} - continue-on-error: true - uses: actions/download-artifact@v4 + - uses: ./.github/actions/download-rust-ext with: - name: ${{ inputs.rust_ext_artifact }} - path: python/sglang/srt/ + artifact_name: ${{ inputs.rust_ext_artifact }} - name: Install dependencies timeout-minutes: 20 - env: - SGLANG_BUILD_RUST_EXTS: ${{ steps.rust_ext.outcome == 'success' && 'none' || '' }} run: | CUSTOM_BUILD_SGL_KERNEL=${{inputs.sgl_kernel}} bash scripts/ci/cuda/ci_install_dependency.sh diffusion @@ -257,19 +243,12 @@ jobs: merge-multiple: true pattern: wheel-python3.10-cuda* - - name: Download prebuilt Rust extensions - id: rust_ext - if: ${{ inputs.rust_ext_artifact != '' }} - continue-on-error: true - uses: actions/download-artifact@v4 + - uses: ./.github/actions/download-rust-ext with: - name: ${{ inputs.rust_ext_artifact }} - path: python/sglang/srt/ + artifact_name: ${{ inputs.rust_ext_artifact }} - name: Install dependencies timeout-minutes: 20 - env: - SGLANG_BUILD_RUST_EXTS: ${{ steps.rust_ext.outcome == 'success' && 'none' || '' }} run: | CUSTOM_BUILD_SGL_KERNEL=${{inputs.sgl_kernel}} bash scripts/ci/cuda/ci_install_dependency.sh diffusion @@ -330,19 +309,12 @@ jobs: merge-multiple: true pattern: wheel-python3.10-cuda* - - name: Download prebuilt Rust extensions - id: rust_ext - if: ${{ inputs.rust_ext_artifact != '' }} - continue-on-error: true - uses: actions/download-artifact@v4 + - uses: ./.github/actions/download-rust-ext with: - name: ${{ inputs.rust_ext_artifact }} - path: python/sglang/srt/ + artifact_name: ${{ inputs.rust_ext_artifact }} - name: Install dependencies timeout-minutes: 20 - env: - SGLANG_BUILD_RUST_EXTS: ${{ steps.rust_ext.outcome == 'success' && 'none' || '' }} run: | CUSTOM_BUILD_SGL_KERNEL=${{inputs.sgl_kernel}} bash scripts/ci/cuda/ci_install_dependency.sh diffusion @@ -410,19 +382,12 @@ jobs: merge-multiple: true pattern: wheel-python3.10-cuda* - - name: Download prebuilt Rust extensions - id: rust_ext - if: ${{ inputs.rust_ext_artifact != '' }} - continue-on-error: true - uses: actions/download-artifact@v4 + - uses: ./.github/actions/download-rust-ext with: - name: ${{ inputs.rust_ext_artifact }} - path: python/sglang/srt/ + artifact_name: ${{ inputs.rust_ext_artifact }} - name: Install dependencies timeout-minutes: 20 - env: - SGLANG_BUILD_RUST_EXTS: ${{ steps.rust_ext.outcome == 'success' && 'none' || '' }} run: | CUSTOM_BUILD_SGL_KERNEL=${{inputs.sgl_kernel}} bash scripts/ci/cuda/ci_install_dependency.sh diffusion @@ -466,20 +431,14 @@ jobs: merge-multiple: true pattern: wheel-python3.10-cuda* - - name: Download prebuilt Rust extensions - id: rust_ext - if: ${{ inputs.rust_ext_artifact != '' }} - continue-on-error: true - uses: actions/download-artifact@v4 + - uses: ./.github/actions/download-rust-ext with: - name: ${{ inputs.rust_ext_artifact }} - path: python/sglang/srt/ + artifact_name: ${{ inputs.rust_ext_artifact }} - name: Install dependencies timeout-minutes: 20 env: SGLANG_CI_EARLY_LD_LIBRARY_PATH: "1" - SGLANG_BUILD_RUST_EXTS: ${{ steps.rust_ext.outcome == 'success' && 'none' || '' }} run: | CUSTOM_BUILD_SGL_KERNEL=${{inputs.sgl_kernel}} bash scripts/ci/cuda/ci_install_dependency.sh diffusion @@ -530,19 +489,12 @@ jobs: merge-multiple: true pattern: wheel-python3.10-cuda* - - name: Download prebuilt Rust extensions - id: rust_ext - if: ${{ inputs.rust_ext_artifact != '' }} - continue-on-error: true - uses: actions/download-artifact@v4 + - uses: ./.github/actions/download-rust-ext with: - name: ${{ inputs.rust_ext_artifact }} - path: python/sglang/srt/ + artifact_name: ${{ inputs.rust_ext_artifact }} - name: Install dependencies timeout-minutes: 20 - env: - SGLANG_BUILD_RUST_EXTS: ${{ steps.rust_ext.outcome == 'success' && 'none' || '' }} run: | CUSTOM_BUILD_SGL_KERNEL=${{inputs.sgl_kernel}} bash scripts/ci/cuda/ci_install_dependency.sh diffusion diff --git a/.github/workflows/pr-test-sgl-kernel.yml b/.github/workflows/pr-test-sgl-kernel.yml index 8c3872716..4c7b926e2 100644 --- a/.github/workflows/pr-test-sgl-kernel.yml +++ b/.github/workflows/pr-test-sgl-kernel.yml @@ -7,7 +7,7 @@ on: required: true type: string rust_ext_artifact: - description: 'Artifact of prebuilt Rust extension modules, from rust-ext-build. Empty, or a download that fails, means this job compiles them during install.' + description: 'Artifact of prebuilt Rust extension modules, from rust-ext-build. Empty, or a download that fails, falls back to the cache; a miss there compiles during install.' type: string default: '' runner_config: @@ -58,19 +58,12 @@ jobs: merge-multiple: true pattern: wheel-python3.10-cuda* - - name: Download prebuilt Rust extensions - id: rust_ext - if: ${{ inputs.rust_ext_artifact != '' }} - continue-on-error: true - uses: actions/download-artifact@v4 + - uses: ./.github/actions/download-rust-ext with: - name: ${{ inputs.rust_ext_artifact }} - path: python/sglang/srt/ + artifact_name: ${{ inputs.rust_ext_artifact }} - name: Install dependencies timeout-minutes: 20 - env: - SGLANG_BUILD_RUST_EXTS: ${{ steps.rust_ext.outcome == 'success' && 'none' || '' }} run: | CUSTOM_BUILD_SGL_KERNEL=${{inputs.sgl_kernel}} bash scripts/ci/cuda/ci_install_dependency.sh diffusion @@ -104,19 +97,12 @@ jobs: merge-multiple: true pattern: wheel-python3.10-cuda* - - name: Download prebuilt Rust extensions - id: rust_ext - if: ${{ inputs.rust_ext_artifact != '' }} - continue-on-error: true - uses: actions/download-artifact@v4 + - uses: ./.github/actions/download-rust-ext with: - name: ${{ inputs.rust_ext_artifact }} - path: python/sglang/srt/ + artifact_name: ${{ inputs.rust_ext_artifact }} - name: Install dependencies timeout-minutes: 20 - env: - SGLANG_BUILD_RUST_EXTS: ${{ steps.rust_ext.outcome == 'success' && 'none' || '' }} run: | CUSTOM_BUILD_SGL_KERNEL=${{inputs.sgl_kernel}} bash scripts/ci/cuda/ci_install_dependency.sh @@ -162,19 +148,12 @@ jobs: merge-multiple: true pattern: wheel-python3.10-cuda* - - name: Download prebuilt Rust extensions - id: rust_ext - if: ${{ inputs.rust_ext_artifact != '' }} - continue-on-error: true - uses: actions/download-artifact@v4 + - uses: ./.github/actions/download-rust-ext with: - name: ${{ inputs.rust_ext_artifact }} - path: python/sglang/srt/ + artifact_name: ${{ inputs.rust_ext_artifact }} - name: Install dependencies timeout-minutes: 20 - env: - SGLANG_BUILD_RUST_EXTS: ${{ steps.rust_ext.outcome == 'success' && 'none' || '' }} run: | CUSTOM_BUILD_SGL_KERNEL=${{inputs.sgl_kernel}} bash scripts/ci/cuda/ci_install_dependency.sh diffusion diff --git a/.github/workflows/pr-test.yml b/.github/workflows/pr-test.yml index 6d39630ef..4b4df3147 100644 --- a/.github/workflows/pr-test.yml +++ b/.github/workflows/pr-test.yml @@ -511,7 +511,7 @@ jobs: 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: '' + skip_prebuilt_rust_ext: true secrets: inherit base-c-test-8-gpu-b300: diff --git a/.github/workflows/rerun-test.yml b/.github/workflows/rerun-test.yml index 92d26923a..f188c0695 100644 --- a/.github/workflows/rerun-test.yml +++ b/.github/workflows/rerun-test.yml @@ -104,6 +104,9 @@ jobs: - uses: ./.github/actions/check-maintenance + # No artifact_name: a workflow_dispatch has no rust-ext-build job of its own. + - uses: ./.github/actions/download-rust-ext + - name: Install dependencies timeout-minutes: ${{ fromJson(inputs.install_timeout) }} env: @@ -195,6 +198,8 @@ jobs: - uses: ./.github/actions/check-maintenance + - uses: ./.github/actions/download-rust-ext + - name: Install dependencies (diffusion) timeout-minutes: 20 run: bash scripts/ci/cuda/ci_install_dependency.sh diffusion @@ -270,9 +275,16 @@ jobs: - name: Install uv uses: astral-sh/setup-uv@v5 + # Worth the most of the three jobs: this runner is hosted, so it has no + # persistent cargo target dir and every dispatch compiled cold. Its + # setup-python pins the same 3.10 the modules were built against. + - uses: ./.github/actions/download-rust-ext + id: rust_ext + # Needed by setuptools-rust to build the bundled native gRPC extension # (rust/sglang-grpc) when installing the main `sglang` wheel from source. - name: Install protoc + Rust toolchain + if: ${{ steps.rust_ext.outputs.hit != 'true' }} timeout-minutes: 10 run: bash scripts/ci/utils/install_rust_protoc.sh diff --git a/scripts/ci/utils/ensure_zstd.sh b/scripts/ci/utils/ensure_zstd.sh new file mode 100755 index 000000000..2b643ed31 --- /dev/null +++ b/scripts/ci/utils/ensure_zstd.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# Install zstd when missing, for any job that reads or writes an actions/cache entry. +# actions/cache identifies an entry by key *and* a version derived from the +# compression tool, so a runner without zstd cannot see what one with it saved - +# a silent miss every run. Warn, not fail: both sides work without the cache. +set -uo pipefail +if ! command -v zstd >/dev/null 2>&1; then + if [ "$(id -u)" = "0" ]; then SUDO="" + elif command -v sudo >/dev/null 2>&1; then SUDO="sudo" + else SUDO=""; fi + ${SUDO} apt-get update || true + ${SUDO} apt-get install -y --no-install-recommends zstd || true +fi +command -v zstd >/dev/null 2>&1 \ + || echo "::warning::zstd unavailable on ${RUNNER_NAME:-this runner}; actions/cache entries here will not match the ones saved with it"