Skip to content

[Apple Silicon] [CI] Move the MLX lane to the check-changes + pr-gate composite - #30121

Merged
Kangyan-Zhou merged 9 commits into
sgl-project:mainfrom
jlee5814:mlx-lane-composite-gate
Jul 11, 2026
Merged

Kangyan-Zhou merged 9 commits into
sgl-project:mainfrom
jlee5814:mlx-lane-composite-gate

Conversation

@jlee5814

@jlee5814 jlee5814 commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Motivation

#29691 landed the MLX lane (pr-test-mlx.yml) with standalone gating. This PR began as a migration to the shared check-changes plus pr-gate composite used by the other hardware lanes. Implementations include: a separate sgl_kernel filter output following _pr-test-check-changes.yml, and a staged layout aligned with the other backends, wired for the smoke tests from #29440. All three are in this PR, so it is a gate migration plus a staged restructure. Per @yeahdongcn's review, the scope is inclusive of moving stage A onto run_suite.py suite registration, matching how every other hardware lane selects its tests instead of an explicit file list.

Modifications

Gate migration

  • A dorny/paths-filter check-changes job plus the reusable pr-gate workflow replace the inline label gate. pr-gate live fetches labels at runtime, so adding run-ci and rerunning failed jobs restores the suite. The old frozen
    payload gate never could.
  • The workflow level permissions block is removed; it zeroed the pull-requests and actions scopes the paths filter and the gate API reads require. The vendor lanes running this same chain declare no block.

Filter split

  • main_package and sgl_kernel are separate filter outputs, following _pr-test-check-changes.yml; the sgl_kernel glob is copied verbatim from that file. pr-gate keys off a changes_exist aggregate, matching the MUSA and NPU lanes.
  • Stage A gates on main_package or sgl_kernel, matching the base stages of pr-test.yml, so the trigger surface is unchanged from the single key filter.

Staged layout and #29440 wiring

  • mlx-unit-test becomes stage-a-unit-test-mlx. Invocation, env, and runner are unchanged: model free unit tests, HF_HUB_OFFLINE=1, GitHub hosted macos-26.
  • A new stage-b-e2e-test-mlx job is defined for the [MLX] Add correctness tests for qwen2_moe and qwen3_moe #29440 smoke tests: served correctness for qwen2_moe and qwen3_moe plus the reference equivalence test. Those tests load 8 GB to 17 GB models and are tuned for 24 GB of unified memory; GitHub hosted macos-26 runners have 7 GB. Stage B therefore activates only through a workflow_dispatch target_stage input until a self hosted Apple Silicon runner registers. The mechanism is copied from the MUSA lane, with two corrections to make dispatch functional. Stage B currently has no scheduled execution; it fires only via the constrained dispatch input, pending the self hosted runner.
  • workflow_dispatch with a target_stage input is added for per stage dispatch; the input is a constrained type: choice following the AMD lane (a free text field, per the MUSA original, silently no-ops on a typo).
  • The finish job adopts the MUSA pattern: iterate over needs, fail on failure or cancellation, tolerate skipped.

Test registration

  • Stage A now runs via python3 run_suite.py --hw mlx --suite stage-a-unit-test-mlx instead of an explicit pytest file list, matching how the XPU lane invokes run_suite.py. This adds HWBackend.MLX and register_mlx_ci() to the shared ci_register.py, plus a stage-a-unit-test-mlx entry in run_suite.py's per-commit suites.
  • test_quantization.py mixed a model-free class (TestMlxQuantizationOverride, previously cherry-picked via pytest ::ClassName) with a model-downloading class (TestMlxQuantization) in one file. run_suite.py only runs whole files, so TestMlxQuantizationOverride moves to its own file, test_mlx_quantization_override.py, registered for both base-a-test-cpu and the new MLX suite. test_quantization.py keeps only the model-dependent class, now registered under stage-b-e2e-mlx (it performs real HF loads, so it belongs with the gated model requiring suite rather than stage-a).
  • Test registration is now structural: a new model-free MLX unit test file registers itself with register_mlx_ci(...), the same pattern every other backend uses, instead of a line in the workflow's explicit list.
  • A review pass surfaced three MLX test files whose assertions had never executed in any CI configuration (CPU registered with MLX skip guards: skipped on Linux, invisible to the MLX suite). test_mlx_pool_dtype.py and test_tp_worker_routing.py now run in stage-a (verified green under the lane's exact env locally); test_quantization.py reclassified to stage B as above.

Dependencies and deferrals

Accuracy Tests

CI only change; no model or kernel behavior affected. The FakeOverlapScheduler stub desync from #29217 (AttributeError on forward_ct) is fixed on main via #30125, and stage A is expected green against the merge commit.

Speed Tests and Profiling

N/A.


CI States

Latest PR Test (Base): ❌ Run #28996751813
Latest PR Test (Extra): ❌ Run #28996751681

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Note

Gemini is unable to generate a review for this pull request due to the file types involved not being currently supported.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8dfb833c69

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/pr-test-mlx.yml
@jlee5814
jlee5814 force-pushed the mlx-lane-composite-gate branch from 8dfb833 to dfe0c49 Compare July 4, 2026 16:05
@jlee5814

jlee5814 commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

/tag-run-ci-label

Comment thread .github/workflows/pr-test-mlx.yml
Comment thread .github/workflows/pr-test-mlx.yml Outdated
# signature contracts, mocked Metal capture, dummy ServerArgs patching,
# and quant-config dicts.
uv run python -m pytest -v \
test/registered/unit/hardware_backend/mlx/test_runner_init_contract.py \

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you're here, could we revisit the design of the multi-stage CI tests? It would be great to align them with the approach used by the other backends.

Also, could we incorporate the smoke tests from #29440 into the multi-stage CI as well?

@jlee5814 jlee5814 Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Staged. Stage A: the existing macos-26 unit tests, unchanged. Stage B: wired the #29440 smoke tests, dispatch gated: they load 8 to 17 GB models while the hosted runners only have 7 GB. It activates once a self hosted runner exists and #29440 merges, which also fixes the stage A red on main (#29217).

Dispatch surfaced two MUSA bugs: input: for inputs:, so target_stage never registers, and missing base: main plus !cancelled().

check-changes → pr-gate → { stage-a, stage-b } → finish

@jlee5814

jlee5814 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

/tag-run-ci-label

@github-actions github-actions Bot added the quant LLM Quantization label Jul 6, 2026
- "test/**/!(*.md)"
- ".github/workflows/pr-test-mlx.yml"
sgl_kernel:
- "sgl-kernel/**/!(*.md|THIRDPARTYNOTICES.txt|LICENSE)"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this workflow now has a separate sgl_kernel filter output, I think .github/workflows/pr-test-mlx.yml should be listed under sgl_kernel as well, matching the MUSA/AMD split-filter pattern.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added .github/workflows/pr-test-mlx.yml under the sgl_kernel filter.

from sglang.test.ci.ci_register import register_cpu_ci, register_mlx_ci

register_cpu_ci(est_time=1, suite="base-a-test-cpu")
register_mlx_ci(est_time=1, suite="stage-a-unit-test-mlx")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this PR moves the MLX unit lane to run_suite.py, could we also tag the remaining model-free MLX unit tests with register_mlx_ci(..., suite="stage-a-unit-test-mlx")?

  • test/registered/unit/hardware_backend/mlx/test_mlx_runner_pool_contract.py
  • test/registered/unit/hardware_backend/mlx/test_scheduler_mixin.py

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both files are tagged into stage-a-unit-test-mlx (test_scheduler_mixin.py landed via #29217). This also establishes the pattern for new tests like #30097: a register_mlx_ci line in the test's own file.

Comment thread .github/workflows/pr-test-mlx.yml Outdated
test/registered/unit/hardware_backend/mlx/test_metal_profiler.py \
test/registered/unit/hardware_backend/mlx/test_attention_patching.py \
"test/registered/unit/hardware_backend/mlx/test_quantization.py::TestMlxQuantizationOverride"
test/registered/mlx/models_e2e/test_qwen2_moe_mlx_correctness.py \

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #29440 hasn't been merged yet, and this still uses the list-based mechanism. Could we switch it to the run-suite style as well?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#29440 merged, unblocked. The two smoke tests plus test_mlx_reference_correctness.py (model) register under stage-b-e2e-mlx, added to run_suite.py's table; dispatch gate unchanged. test_metal_profiler fails on unmodified main (#30550).

jlee5814 added 7 commits July 8, 2026 12:32
… composite

Replaces the inline mlx-label gate with the composite convention the other hardware lanes use: a dorny/paths-filter check-changes job carrying the sibling lanes' broad filter (python/sglang, test, sgl-kernel, the platform pyproject, and the workflow itself — the suite's contract tests import core srt, so narrow MLX-tree globs would miss the refactors they exist to catch), a pr-gate job calling the reusable run-ci gate, and mlx-unit-test hanging off both. The lane is now path triggered; 'labeled' leaves the trigger types since pr-gate live-fetches labels at runtime, so adding run-ci and re-running failed jobs un-skips the suite (the old frozen-payload gate never could).

The workflow-level permissions block goes with the gate: an explicit block zeroes pull-requests and actions scopes, which the paths filter and the gate's API reads require; the vendor lanes running this same chain declare no block. Job names, env, steps, and the finish job are unchanged.
…ree tests into stage-a, register model-requiring tests under gated stage-b run-suite
Comment thread test/run_suite.py
import sys
from typing import Dict, List, Optional

import tabulate

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This workflow now calls test/run_suite.py, but the install step only installs python[srt_mps] and pytest. run_suite.py imports tabulate at module import time, and in python/pyproject_other.toml tabulate is only part of the test extra, not srt_mps.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, the install now covers the test extra (python[srt_mps,test]), which provides tabulate and subsumes the standalone pytest line. Applied to both stages since they share the install block.

Comment thread .github/workflows/pr-test-mlx.yml Outdated

stage-b-e2e-test-mlx:
needs: [check-changes, pr-gate]
# Inert until a self hosted Apple Silicon runner registers and #29440

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you refresh this comment? #29440 is merged now, and this PR registers those smoke tests under stage-b-e2e-mlx. If stage B should remain manual-only because the self-hosted Apple Silicon runner is not generally available / hosted runners are too small, the comment should say that directly instead of saying it is waiting on #29440.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, it now states no available self-hosted Apple Silicon runner and that hosted runners too small for e2e.

jlee5814 added 2 commits July 8, 2026 23:42
…ting comment

run_suite.py imports tabulate at module level, but the install step only
covered python[srt_mps] plus a bare pytest; tabulate lives in the test
extra of pyproject_other.toml. Extend both stage-a and stage-b install
steps to python[srt_mps,test] (superset of the standalone pytest install).

sgl-project#29440 merged, so the stage-b comment no longer describes the real
blocker; restate it as manual-only pending a self hosted Apple Silicon
runner.
…elong; constrain stage dispatch input to enum

test_mlx_pool_dtype.py and test_tp_worker_routing.py were CPU-registered
with MLX skip guards, so they never ran on Linux (skipped) or on the MLX
lane (unregistered) -- verified green under the lane's exact env, now
registered into stage-a-unit-test-mlx.

test_quantization.py's TestMlxQuantization loads real HF models via
MlxModelRunner; stage-a forbids downloads (HF_HUB_OFFLINE=1) and this
was confirmed to fail with LocalEntryNotFoundError without a pre-warmed
cache. Registered into stage-b-e2e-mlx instead, matching the models_e2e
correctness tests' convention.

target_stage moves from free-text to a choice enum (mirroring
pr-test-amd.yml) so a typo can no longer silently no-op stage-b.
@yeahdongcn

Copy link
Copy Markdown
Collaborator

/tag-and-rerun-ci

@github-actions github-actions Bot added the run-ci label Jul 9, 2026
@Kangyan-Zhou
Kangyan-Zhou merged commit a91c2e6 into sgl-project:main Jul 11, 2026
222 of 265 checks passed
LarrySimingDeng added a commit to LarrySimingDeng/sglang that referenced this pull request Jul 26, 2026
…suites

pr-test-mlx.yml selects stage A tests via run_suite.py suite registration
since sgl-project#30121. Register test_sliding_window_attention under
stage-a-unit-test-mlx and test_gpt_oss_mlx_correctness under
stage-b-e2e-mlx, mirroring the existing MLX test registrations.
LarrySimingDeng added a commit to LarrySimingDeng/sglang that referenced this pull request Jul 26, 2026
pr-test-mlx.yml selects stage A tests via run_suite.py suite registration
since sgl-project#30121.
LarrySimingDeng added a commit to LarrySimingDeng/sglang that referenced this pull request Jul 26, 2026
pr-test-mlx.yml selects stage A tests via run_suite.py suite registration
since sgl-project#30121.
LarrySimingDeng added a commit to LarrySimingDeng/sglang that referenced this pull request Jul 26, 2026
pr-test-mlx.yml selects stage A tests via run_suite.py suite registration
since sgl-project#30121.
LarrySimingDeng added a commit to LarrySimingDeng/sglang that referenced this pull request Jul 26, 2026
pr-test-mlx.yml selects stage A tests via run_suite.py suite registration
since sgl-project#30121. The macOS stage-a runner exercises the real MPS branch;
elsewhere the test runs against the stub.
LarrySimingDeng added a commit to LarrySimingDeng/sglang that referenced this pull request Jul 26, 2026
pr-test-mlx.yml selects stage A tests via run_suite.py suite registration
since sgl-project#30121.
Chronostasys pushed a commit to MindLab-Research/sglang that referenced this pull request Aug 24, 2026
jakki-amd pushed a commit to jakki-amd/sglang that referenced this pull request Sep 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants