Scheduled Full Run #3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: PR Test Base | |
| run-name: >- | |
| ${{ | |
| github.event_name == 'schedule' && 'Scheduled Full Run' | |
| || github.event_name == 'workflow_dispatch' && format('Manual run by {0}', github.actor) | |
| || github.event_name == 'pull_request' && format('PR #{0} - {1}', github.event.pull_request.number, github.event.pull_request.title) | |
| || 'PR Test Base' | |
| }} | |
| on: | |
| schedule: | |
| - cron: '0 11,23 * * *' # Run 2x daily, 12h apart, off PR-push peaks | |
| pull_request: | |
| workflow_dispatch: | |
| inputs: | |
| force_continue_on_error: | |
| description: "Force continue-on-error (test scheduled CI behavior)" | |
| required: false | |
| type: boolean | |
| default: false | |
| test_parallel_dispatch: | |
| description: "Test parallel dispatch behavior (simulates scheduled run)" | |
| required: false | |
| type: boolean | |
| default: false | |
| run_all_tests: | |
| description: "Run all tests (mirrors the scheduled cron's behavior — combine with test_parallel_dispatch for full sim)" | |
| required: false | |
| type: boolean | |
| default: false | |
| workflow_call: | |
| inputs: | |
| git_ref: | |
| description: 'Git ref (branch, tag, or SHA) to test. If not provided, uses the default branch.' | |
| required: false | |
| type: string | |
| default: '' | |
| run_all_tests: | |
| description: "Run all tests (for releasing or testing purpose)" | |
| required: false | |
| type: boolean | |
| default: false | |
| skip_pr_test_health_check: | |
| description: "Skip PR test health check fast-fail (e.g. for release branch cuts)" | |
| required: false | |
| type: boolean | |
| default: false | |
| concurrency: | |
| # Concurrency group structure: pr-test-{event}-{branch}-{git_ref} | |
| # - event_name prevents scheduled runs from colliding with fork PRs whose branch is named 'main' | |
| # (without it, both resolve the branch segment to 'main' and block each other) | |
| # - github.head_ref (pull_request) or github.ref_name (workflow_dispatch) normalizes to branch name | |
| group: pr-test-${{ github.event_name }}-${{ github.head_ref || github.ref_name || 'default' }}-${{ inputs.git_ref || 'all' }} | |
| cancel-in-progress: ${{ github.event_name != 'workflow_call' }} | |
| env: | |
| SGLANG_IS_IN_CI: true | |
| SGLANG_CUDA_COREDUMP: "1" | |
| SGLANG_JIT_DEEPGEMM_FAST_WARMUP: true | |
| SKIP_PR_TEST_HEALTH_CHECK: ${{ (inputs.skip_pr_test_health_check == true || inputs.test_parallel_dispatch == true || inputs.run_all_tests == true) && 'true' || 'false' }} | |
| # Schedule / main-branch dispatch / workflow_call from main use refs/heads/main; PR events use refs/pull/*/merge | |
| PR_TEST_BYPASS_MAINTENANCE_ON_MAIN: ${{ github.ref == 'refs/heads/main' && 'true' || 'false' }} | |
| USE_VENV: false | |
| permissions: | |
| actions: write | |
| contents: read | |
| issues: read | |
| pull-requests: read | |
| jobs: | |
| # =============================================== check changes ==================================================== | |
| check-changes: | |
| uses: ./.github/workflows/_pr-test-check-changes.yml | |
| with: | |
| git_ref: ${{ inputs.git_ref || '' }} | |
| run_all_tests: ${{ inputs.run_all_tests == true }} | |
| force_continue_on_error: ${{ inputs.force_continue_on_error == true }} | |
| secrets: inherit | |
| call-pr-test-extra: | |
| if: github.event_name == 'schedule' || inputs.test_parallel_dispatch == true || inputs.run_all_tests == true | |
| uses: ./.github/workflows/pr-test-extra.yml | |
| with: | |
| git_ref: ${{ inputs.git_ref || '' }} | |
| run_all_tests: true | |
| secrets: inherit | |
| # =============================================== Wait Jobs for Sequential PR Execution ==================================================== | |
| # These jobs poll GitHub API to wait for previous stages to complete. | |
| # For PR runs: wait jobs run and enforce sequential execution via polling. | |
| # For scheduled runs: wait jobs are skipped, enabling parallel execution for easier retry. | |
| # For PRs with the `bypass-fastfail` label: wait jobs run but return success immediately | |
| # (handled inside the wait-for-jobs action), so downstream stages dispatch in parallel. | |
| wait-for-base-a: | |
| needs: [check-changes, call-gate] | |
| if: | | |
| always() && | |
| !cancelled() && | |
| needs.check-changes.result == 'success' && | |
| github.event_name == 'pull_request' && | |
| inputs.test_parallel_dispatch != true && | |
| (needs.check-changes.outputs.main_package == 'true' || needs.check-changes.outputs.sgl_kernel == 'true') && | |
| (needs.call-gate.result == 'success' || needs.call-gate.result == 'skipped') | |
| runs-on: ubuntu-latest | |
| outputs: | |
| base_a_result: ${{ steps.wait.outputs.result }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: ./.github/actions/check-maintenance | |
| - uses: ./.github/actions/wait-for-jobs | |
| id: wait | |
| with: | |
| stage-name: base-a | |
| jobs: | | |
| [ | |
| {"prefix": "base-a-test-1-gpu-small", "expected_count": ${{ fromJson(needs.check-changes.outputs.partitions)['base-a-test-1-gpu-small'].size }}}, | |
| {"prefix": "base-a-test-cpu", "expected_count": ${{ fromJson(needs.check-changes.outputs.partitions)['base-a-test-cpu'].size }}} | |
| ] | |
| max-wait-minutes: '240' | |
| wait-for-base-b: | |
| needs: [check-changes, call-gate, wait-for-base-a] | |
| if: | | |
| always() && | |
| !cancelled() && | |
| needs.check-changes.result == 'success' && | |
| github.event_name == 'pull_request' && | |
| inputs.test_parallel_dispatch != true && | |
| (needs.check-changes.outputs.main_package == 'true' || needs.check-changes.outputs.sgl_kernel == 'true') && | |
| (needs.wait-for-base-a.result == 'success' || needs.wait-for-base-a.result == 'skipped') && | |
| (needs.call-gate.result == 'success' || needs.call-gate.result == 'skipped') | |
| runs-on: ubuntu-latest | |
| outputs: | |
| base_b_result: ${{ steps.wait.outputs.result }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: ./.github/actions/check-maintenance | |
| - uses: ./.github/actions/wait-for-jobs | |
| id: wait | |
| with: | |
| stage-name: base-b | |
| jobs: | | |
| [ | |
| {"prefix": "base-b-test-1-gpu-small", "expected_count": ${{ fromJson(needs.check-changes.outputs.partitions)['base-b-test-1-gpu-small'].size }}}, | |
| {"prefix": "base-b-test-1-gpu-large", "expected_count": ${{ fromJson(needs.check-changes.outputs.partitions)['base-b-test-1-gpu-large'].size }}}, | |
| {"prefix": "base-b-test-2-gpu-large", "expected_count": ${{ fromJson(needs.check-changes.outputs.partitions)['base-b-test-2-gpu-large'].size }}}, | |
| {"prefix": "base-b-test-4-gpu-b200", "expected_count": ${{ fromJson(needs.check-changes.outputs.partitions)['base-b-test-4-gpu-b200'].size }}} | |
| ] | |
| max-wait-minutes: '480' | |
| # =============================================== PR Gate ==================================================== | |
| call-gate: | |
| needs: check-changes | |
| # Skip for scheduled runs (they run all tests) | |
| if: | | |
| github.event_name != 'schedule' && | |
| inputs.test_parallel_dispatch != true && | |
| ( | |
| needs.check-changes.outputs.main_package == 'true' || | |
| needs.check-changes.outputs.sgl_kernel == 'true' || | |
| needs.check-changes.outputs.jit_kernel == 'true' || | |
| needs.check-changes.outputs.multimodal_gen == 'true' | |
| ) | |
| uses: ./.github/workflows/pr-gate.yml | |
| secrets: inherit | |
| # =============================================== sgl-kernel ==================================================== | |
| sgl-kernel-build-wheels: | |
| needs: [check-changes, call-gate] | |
| # Skip for scheduled runs (they run stages independently). | |
| if: | | |
| github.event_name != 'schedule' && | |
| inputs.test_parallel_dispatch != true && | |
| needs.check-changes.result == 'success' && | |
| needs.check-changes.outputs.sgl_kernel == 'true' && | |
| needs.call-gate.result == 'success' | |
| uses: ./.github/workflows/_pr-test-sgl-kernel-build.yml | |
| with: | |
| runs_on: x64-kernel-build-node | |
| job_display_name: Build Wheel | |
| git_ref: ${{ inputs.git_ref || '' }} | |
| skip_pr_test_health_check: ${{ inputs.skip_pr_test_health_check == true }} | |
| secrets: inherit | |
| sgl-kernel-build-wheels-arm: | |
| needs: [check-changes, call-gate] | |
| # Skip for scheduled runs (they run stages independently). | |
| if: | | |
| github.event_name != 'schedule' && | |
| inputs.test_parallel_dispatch != true && | |
| needs.check-changes.result == 'success' && | |
| needs.check-changes.outputs.sgl_kernel == 'true' && | |
| needs.call-gate.result == 'success' | |
| uses: ./.github/workflows/_pr-test-sgl-kernel-build.yml | |
| with: | |
| runs_on: arm-kernel-build-node | |
| job_display_name: Build Wheel Arm | |
| arch_suffix: '-aarch64' | |
| git_ref: ${{ inputs.git_ref || '' }} | |
| 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: 1-gpu-5090 | |
| 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, rust-ext-build] | |
| if: | | |
| github.event_name != 'schedule' && | |
| inputs.test_parallel_dispatch != true && | |
| needs.check-changes.outputs.sgl_kernel == 'true' | |
| uses: ./.github/workflows/pr-test-sgl-kernel.yml | |
| with: | |
| runner_config: 4-gpu-b200 | |
| runs_on_map: ${{ needs.check-changes.outputs.runs_on_map }} | |
| 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, 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). | |
| if: | | |
| always() && | |
| ((github.event_name == 'schedule' || inputs.test_parallel_dispatch == true) || (!failure() && !cancelled())) && | |
| needs.check-changes.outputs.jit_kernel == 'true' | |
| uses: ./.github/workflows/pr-test-jit-kernel.yml | |
| with: | |
| runner_config: 4-gpu-b200 | |
| runs_on_map: ${{ needs.check-changes.outputs.runs_on_map }} | |
| jit_kernel: ${{ needs.check-changes.outputs.jit_kernel }} | |
| # On scheduled/parallel-dispatch runs sgl-kernel-build-wheels is skipped, so the wheel | |
| # artifact does not exist. Force sgl_kernel='false' there so the jit-kernel jobs skip the | |
| # wheel download and run against the released/pinned sgl-kernel instead of a fresh build. | |
| sgl_kernel: ${{ (github.event_name == 'schedule' || inputs.test_parallel_dispatch == true) && 'false' || needs.check-changes.outputs.sgl_kernel }} | |
| 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, rust-ext-build] | |
| if: ${{ !failure() && !cancelled() }} | |
| uses: ./.github/workflows/_pr-test-stage.yml | |
| with: | |
| self_name: base-a-test-1-gpu-small | |
| runner_config: 1-gpu-small | |
| check_changes: ${{ toJson(needs.check-changes.outputs) }} | |
| 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, rust-ext-build] | |
| if: | | |
| always() && | |
| needs.check-changes.result == 'success' && | |
| ((github.event_name == 'schedule' || inputs.test_parallel_dispatch == true) || (!failure() && !cancelled())) | |
| uses: ./.github/workflows/_pr-test-stage-cpu.yml | |
| with: | |
| self_name: base-a-test-cpu | |
| check_changes: ${{ toJson(needs.check-changes.outputs) }} | |
| caller_inputs: ${{ toJson(inputs) }} | |
| partitions: ${{ needs.check-changes.outputs.partitions }} | |
| run_timeout_minutes: '15' | |
| rust_ext_artifact: ${{ needs.rust-ext-build.outputs.artifact_name }} | |
| # No `secrets: inherit`: this stage has no secret consumer, unlike the GPU | |
| # stages' coredump upload. GITHUB_TOKEN and permissions inherit regardless. | |
| # Runs on 5090 (32GB, SM120) | |
| base-b-test-1-gpu-small: | |
| 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: | |
| self_name: base-b-test-1-gpu-small | |
| runner_config: 1-gpu-small | |
| check_changes: ${{ toJson(needs.check-changes.outputs) }} | |
| 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, rust-ext-build] | |
| if: ${{ !failure() && !cancelled() }} | |
| uses: ./.github/workflows/_pr-test-stage.yml | |
| with: | |
| self_name: base-b-test-1-gpu-large | |
| runner_config: 1-gpu-large | |
| check_changes: ${{ toJson(needs.check-changes.outputs) }} | |
| caller_inputs: ${{ toJson(inputs) }} | |
| 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, rust-ext-build] | |
| if: ${{ !failure() && !cancelled() }} | |
| uses: ./.github/workflows/_pr-test-stage.yml | |
| with: | |
| self_name: base-b-test-2-gpu-large | |
| runner_config: 2-gpu-large | |
| check_changes: ${{ toJson(needs.check-changes.outputs) }} | |
| 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, rust-ext-build] | |
| if: ${{ !failure() && !cancelled() }} | |
| uses: ./.github/workflows/_pr-test-stage.yml | |
| with: | |
| self_name: base-b-test-4-gpu-b200 | |
| runner_config: 4-gpu-b200 | |
| check_changes: ${{ toJson(needs.check-changes.outputs) }} | |
| 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, rust-ext-build] | |
| if: | | |
| always() && | |
| !cancelled() && | |
| ((github.event_name == 'schedule' || inputs.test_parallel_dispatch == true) || (!failure() && !cancelled())) && | |
| needs.check-changes.outputs.multimodal_gen == 'true' | |
| uses: ./.github/workflows/pr-test-multimodal-gen.yml | |
| with: | |
| runner_config: 4-gpu-b200 | |
| runs_on_map: ${{ needs.check-changes.outputs.runs_on_map }} | |
| multimodal_gen: ${{ needs.check-changes.outputs.multimodal_gen }} | |
| sgl_kernel: ${{ needs.check-changes.outputs.sgl_kernel }} | |
| continue_on_error: ${{ needs.check-changes.outputs.continue_on_error }} | |
| git_ref: ${{ inputs.git_ref || '' }} | |
| 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, rust-ext-build] | |
| if: ${{ !failure() && !cancelled() }} | |
| uses: ./.github/workflows/_pr-test-stage.yml | |
| with: | |
| self_name: base-c-test-4-gpu-h100 | |
| runner_config: 4-gpu-h100 | |
| check_changes: ${{ toJson(needs.check-changes.outputs) }} | |
| caller_inputs: ${{ toJson(inputs) }} | |
| partitions: ${{ needs.check-changes.outputs.partitions }} | |
| 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-8-gpu-h200: | |
| 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: | |
| self_name: base-c-test-8-gpu-h200 | |
| runner_config: 8-gpu-h200 | |
| check_changes: ${{ toJson(needs.check-changes.outputs) }} | |
| caller_inputs: ${{ toJson(inputs) }} | |
| partitions: ${{ needs.check-changes.outputs.partitions }} | |
| run_timeout_minutes: '30' | |
| timeout_per_file: '1800' | |
| # Per-model TP must match the test's launch in test/registered/ -- see | |
| # FALLBACK_ARGS in scripts/ci/cuda/warmup_deep_gemm.py for extra dp/ep | |
| # flags. Only models that actually invoke DeepGEMM kernels at runtime | |
| # are listed. Cold-cache ~13 min; warm-cache <=30 s via marker file. | |
| # 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, rust-ext-build] | |
| if: ${{ !failure() && !cancelled() }} | |
| uses: ./.github/workflows/_pr-test-stage.yml | |
| with: | |
| self_name: base-c-test-8-gpu-h20 | |
| runner_config: 8-gpu-h20 | |
| check_changes: ${{ toJson(needs.check-changes.outputs) }} | |
| 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-4-gpu-b200: | |
| 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: | |
| self_name: base-c-test-4-gpu-b200 | |
| runner_config: 4-gpu-b200 | |
| check_changes: ${{ toJson(needs.check-changes.outputs) }} | |
| caller_inputs: ${{ toJson(inputs) }} | |
| 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, rust-ext-build] | |
| if: ${{ !failure() && !cancelled() }} | |
| uses: ./.github/workflows/_pr-test-stage.yml | |
| with: | |
| self_name: base-c-test-4-gpu-gb300 | |
| runner_config: 4-gpu-gb300 | |
| check_changes: ${{ toJson(needs.check-changes.outputs) }} | |
| caller_inputs: ${{ toJson(inputs) }} | |
| 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. | |
| skip_prebuilt_rust_ext: true | |
| secrets: inherit | |
| base-c-test-8-gpu-b300: | |
| 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: | |
| self_name: base-c-test-8-gpu-b300 | |
| runner_config: 8-gpu-b300 | |
| check_changes: ${{ toJson(needs.check-changes.outputs) }} | |
| caller_inputs: ${{ toJson(inputs) }} | |
| partitions: ${{ needs.check-changes.outputs.partitions }} | |
| run_timeout_minutes: '60' | |
| timeout_per_file: '3600' | |
| rust_ext_artifact: ${{ needs.rust-ext-build.outputs.artifact_name }} | |
| 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: | |
| [ | |
| call-gate, | |
| check-changes, | |
| sgl-kernel-build-wheels, | |
| sgl-kernel-build-wheels-arm, | |
| call-sgl-kernel-tests, | |
| rust-ext-build, | |
| wait-for-base-a, | |
| wait-for-base-b, | |
| call-jit-kernel-tests, | |
| call-multimodal-gen-tests, | |
| base-a-test-1-gpu-small, | |
| base-a-test-cpu, | |
| base-b-test-1-gpu-small, | |
| base-b-test-1-gpu-large, | |
| base-b-test-2-gpu-large, | |
| base-b-test-4-gpu-b200, | |
| base-c-test-4-gpu-h100, | |
| base-c-test-8-gpu-h20, | |
| base-c-test-8-gpu-h200, | |
| base-c-test-4-gpu-b200, | |
| base-c-test-4-gpu-gb300, | |
| base-c-test-8-gpu-b300, | |
| ] | |
| if: always() | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check all dependent job statuses | |
| run: | | |
| # Convert the 'needs' context to a JSON string | |
| json_needs='${{ toJson(needs) }}' | |
| # Get a list of all job names from the JSON keys | |
| job_names=$(echo "$json_needs" | jq -r 'keys_unsorted[]') | |
| for job in $job_names; do | |
| # For each job, extract its result | |
| result=$(echo "$json_needs" | jq -r --arg j "$job" '.[$j].result') | |
| # Print the job name and its result | |
| echo "$job: $result" | |
| # Check for failure or cancellation and exit if found | |
| if [[ "$result" == "failure" || "$result" == "cancelled" ]]; then | |
| echo "The above jobs failed." | |
| exit 1 | |
| fi | |
| done | |
| # If the loop completes, all jobs were successful | |
| echo "All jobs completed successfully" | |
| exit 0 | |
| # =============================================== notify pr-states ==================================================== | |
| # Dispatches pr-states.yml after every attempt (initial + every rerun). | |
| # workflow_run.completed only fires on the initial completion (one | |
| # workflow_run record across attempts), so we explicitly dispatch — | |
| # workflow_dispatch is the only event GITHUB_TOKEN can cascade-create. | |
| # | |
| # Fork PRs are excluded: their pull_request GITHUB_TOKEN is forced | |
| # read-only regardless of declared `actions: write`, so dispatch 403s. | |
| # Fork PRs get pr-states updates via the workflow_run subscription | |
| # there (initial completion) and pull_request_target (push / label). | |
| notify-pr-states: | |
| needs: [pr-test-finish] | |
| if: | | |
| always() && | |
| github.event_name == 'pull_request' && | |
| github.event.pull_request.head.repo.full_name == github.repository | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Dispatch pr-states refresh | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| run: | | |
| gh workflow run pr-states.yml \ | |
| --repo ${{ github.repository }} \ | |
| --ref main \ | |
| -f pr_number="$PR_NUMBER" |