From 400bddf24cac3d787690a95f3c30683ec8a9d675 Mon Sep 17 00:00:00 2001 From: Chang Su Date: Wed, 29 Oct 2025 11:11:45 -0400 Subject: [PATCH] [router] fix router release workflow and add build test in PR (#12315) --- .github/workflows/nightly-release-router.yml | 6 +- .github/workflows/pr-test-pd-router.yml | 4 +- .github/workflows/pr-test-rust.yml | 59 +++++++++++++++++-- .github/workflows/release-pypi-router.yml | 6 +- sgl-router/Cargo.toml | 7 ++- sgl-router/MANIFEST.in | 1 + sgl-router/README.md | 23 ++++---- sgl-router/py_src/sglang_router/router.py | 9 ++- sgl-router/py_test/unit/test_arg_parser.py | 2 +- sgl-router/py_test/unit/test_router_config.py | 2 +- .../py_test/unit/test_startup_sequence.py | 4 +- sgl-router/pyproject.toml | 14 ++--- sgl-router/src/core/mod.rs | 1 + 13 files changed, 99 insertions(+), 39 deletions(-) diff --git a/.github/workflows/nightly-release-router.yml b/.github/workflows/nightly-release-router.yml index 7b16c2127..4d12dd790 100644 --- a/.github/workflows/nightly-release-router.yml +++ b/.github/workflows/nightly-release-router.yml @@ -25,10 +25,10 @@ jobs: ls: dir target: x86_64 python-architecture: x64 - interpreter: 3.8 3.9 3.10 3.11 3.12 3.13 + interpreter: 3.9 3.10 3.11 3.12 3.13 - os: macos target: aarch64 - interpreter: 3.8 3.9 3.10 3.11 3.12 3.13 + interpreter: 3.9 3.10 3.11 3.12 3.13 - os: ubuntu platform: linux target: aarch64 @@ -94,7 +94,7 @@ jobs: with: target: ${{ matrix.target }} manylinux: ${{ matrix.manylinux || 'auto' }} - args: --release --out dist --interpreter ${{ matrix.interpreter || '3.8 3.9 3.10 3.11 3.12 3.13' }} + args: --release --out dist --interpreter ${{ matrix.interpreter || '3.9 3.10 3.11 3.12 3.13 3.14' }} rust-toolchain: stable docker-options: -e CI -e CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc -e CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++ before-script-linux: | diff --git a/.github/workflows/pr-test-pd-router.yml b/.github/workflows/pr-test-pd-router.yml index 9195fb87d..228f1f5eb 100644 --- a/.github/workflows/pr-test-pd-router.yml +++ b/.github/workflows/pr-test-pd-router.yml @@ -148,7 +148,9 @@ jobs: source "$HOME/.cargo/env" echo "Building sgl-router..." cd sgl-router - cargo build && python3 -m build && pip install --force-reinstall dist/*.whl + pip install maturin + maturin build --release --out dist + pip install --force-reinstall dist/*.whl - name: Start disaggregation servers id: start_servers diff --git a/.github/workflows/pr-test-rust.yml b/.github/workflows/pr-test-rust.yml index 9b177f24b..a5dbcb39a 100644 --- a/.github/workflows/pr-test-rust.yml +++ b/.github/workflows/pr-test-rust.yml @@ -21,6 +21,55 @@ env: SCCACHE_GHA_ENABLED: "true" jobs: + maturin-build-test: + if: github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'run-ci') + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + path: sglang-repo + + - name: Move sgl-router folder to root + run: | + mv sglang-repo/sgl-router/* . + rm -rf sglang-repo + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.13" + + - name: Install protoc and dependencies + run: | + sudo apt-get update + sudo apt-get install -y wget unzip gcc g++ perl make + cd /tmp + wget https://github.com/protocolbuffers/protobuf/releases/download/v32.0/protoc-32.0-linux-x86_64.zip + sudo unzip protoc-32.0-linux-x86_64.zip -d /usr/local + rm protoc-32.0-linux-x86_64.zip + protoc --version + + - name: Configure sccache + uses: mozilla-actions/sccache-action@v0.0.9 + with: + version: "v0.10.0" + + - name: Test maturin build + uses: PyO3/maturin-action@v1 + with: + args: --release --out dist + rust-toolchain: stable + sccache: true + + - name: List built wheel + run: ls -lh dist/ + + - name: Test wheel install + run: | + pip install dist/*.whl + python -c "import sglang_router; print('Python package: OK')" + python -c "from sglang_router.sglang_router_rs import Router; print('Rust extension: OK')" + python -m sglang_router.launch_router --help > /dev/null && echo "Entry point: OK" unit-test-rust: if: github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'run-ci') runs-on: ubuntu-latest @@ -116,8 +165,8 @@ jobs: source "$HOME/.cargo/env" export RUSTC_WRAPPER=sccache cd sgl-router - pip install setuptools-rust wheel build - python3 -m build + pip install maturin + maturin build --release --out dist pip install --force-reinstall dist/*.whl @@ -213,8 +262,8 @@ jobs: source "$HOME/.cargo/env" export RUSTC_WRAPPER=sccache cd sgl-router - pip install setuptools-rust wheel build - python3 -m build + pip install maturin + maturin build --release --out dist pip install --force-reinstall dist/*.whl - name: Run Python E2E response API tests @@ -237,7 +286,7 @@ jobs: finish: - needs: [unit-test-rust, pytest-rust, pytest-rust-2] + needs: [maturin-build-test, unit-test-rust, pytest-rust, pytest-rust-2] runs-on: ubuntu-latest steps: - name: Finish diff --git a/.github/workflows/release-pypi-router.yml b/.github/workflows/release-pypi-router.yml index 71122499e..32795daec 100644 --- a/.github/workflows/release-pypi-router.yml +++ b/.github/workflows/release-pypi-router.yml @@ -25,10 +25,10 @@ jobs: ls: dir target: x86_64 python-architecture: x64 - interpreter: 3.8 3.9 3.10 3.11 3.12 3.13 + interpreter: 3.9 3.10 3.11 3.12 3.13 - os: macos target: aarch64 - interpreter: 3.8 3.9 3.10 3.11 3.12 3.13 + interpreter: 3.9 3.10 3.11 3.12 3.13 - os: ubuntu platform: linux target: aarch64 @@ -79,7 +79,7 @@ jobs: with: target: ${{ matrix.target }} manylinux: ${{ matrix.manylinux || 'auto' }} - args: --release --out dist --interpreter ${{ matrix.interpreter || '3.8 3.9 3.10 3.11 3.12 3.13' }} + args: --release --out dist --interpreter ${{ matrix.interpreter || '3.9 3.10 3.11 3.12 3.13 3.14' }} rust-toolchain: stable docker-options: -e CI -e CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc -e CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++ before-script-linux: | diff --git a/sgl-router/Cargo.toml b/sgl-router/Cargo.toml index c863f4a9c..1b0c853b8 100644 --- a/sgl-router/Cargo.toml +++ b/sgl-router/Cargo.toml @@ -127,9 +127,14 @@ strip = true # Strip debug symbols [profile.dev] opt-level = 0 -debug = true +debug = 1 split-debuginfo = "unpacked" incremental = true +codegen-units = 256 + +[profile.dev.package."*"] +opt-level = 2 +debug = false [profile.dev.build-override] diff --git a/sgl-router/MANIFEST.in b/sgl-router/MANIFEST.in index 4baa6c84f..7f872d5a2 100644 --- a/sgl-router/MANIFEST.in +++ b/sgl-router/MANIFEST.in @@ -3,3 +3,4 @@ include Cargo.toml # Rust project configuration include build.rs # Build script for protobuf generation recursive-include src *.rs # Rust source files recursive-include src/proto *.proto # Protobuf definitions +recursive-include py_src *.py # Python source files diff --git a/sgl-router/README.md b/sgl-router/README.md index 5ba7887cd..ed7b27f25 100644 --- a/sgl-router/README.md +++ b/sgl-router/README.md @@ -67,14 +67,16 @@ cargo build --release ### Python Package ```bash -pip install setuptools-rust wheel build -python -m build -pip install dist/*.whl +pip install maturin -# Rebuild & reinstall in one step during development -python -m build && pip install --force-reinstall dist/*.whl +# Fast development mode (debug build, no wheel, instant) +maturin develop + +# Production build (optimized, creates wheel) +maturin build --release +pip install --force-reinstall dist/*.whl ``` -> **Note:** Editable installs (`pip install -e .`) are currently not supported; prefer wheel builds for development. +> **Note:** Use `maturin develop` for fast iteration during development (builds in debug mode and installs directly). Use `maturin build --release` for production wheels with full optimizations (opt-level="z", lto="fat"). The package uses abi3 support for Python 3.8+ compatibility. ## Quick Start @@ -562,20 +564,19 @@ curl -X POST "http://localhost:8080/add_worker?url=http://worker3:8000&api_key=w ## Development & Testing ```bash -# Build Rust components +# Build Rust components (debug mode, fast) cargo build # Run Rust tests cargo test -# Build & install Python bindings -python -m build -pip install --force-reinstall dist/*.whl +# Fast Python development (rebuilds and installs in debug mode) +maturin develop # Run Python tests pytest ``` -When modifying runtime behavior, rebuild the wheel or run the binary directly. Use `python -m sglang_router.launch_server` to co-launch router and SGLang workers in small clusters for local validation. +For production builds, use `maturin build --release` to create optimized wheels. During development, `maturin develop` rebuilds and installs instantly without creating wheel files. Use `python -m sglang_router.launch_server` to co-launch router and SGLang workers in small clusters for local validation. --- diff --git a/sgl-router/py_src/sglang_router/router.py b/sgl-router/py_src/sglang_router/router.py index 733848efe..0c06f4a41 100644 --- a/sgl-router/py_src/sglang_router/router.py +++ b/sgl-router/py_src/sglang_router/router.py @@ -1,8 +1,13 @@ from typing import Optional from sglang_router.router_args import RouterArgs -from sglang_router_rs import BackendType, HistoryBackendType, PolicyType, PyOracleConfig -from sglang_router_rs import Router as _Router +from sglang_router.sglang_router_rs import ( + BackendType, + HistoryBackendType, + PolicyType, + PyOracleConfig, +) +from sglang_router.sglang_router_rs import Router as _Router def policy_from_str(policy_str: Optional[str]) -> PolicyType: diff --git a/sgl-router/py_test/unit/test_arg_parser.py b/sgl-router/py_test/unit/test_arg_parser.py index d8881c668..f5e191e2a 100644 --- a/sgl-router/py_test/unit/test_arg_parser.py +++ b/sgl-router/py_test/unit/test_arg_parser.py @@ -406,7 +406,7 @@ class TestPolicyFromStr: def test_valid_policies(self): """Test conversion of valid policy strings.""" - from sglang_router_rs import PolicyType + from sglang_router.sglang_router_rs import PolicyType assert policy_from_str("random") == PolicyType.Random assert policy_from_str("round_robin") == PolicyType.RoundRobin diff --git a/sgl-router/py_test/unit/test_router_config.py b/sgl-router/py_test/unit/test_router_config.py index 51bceb7ba..6343d3b9e 100644 --- a/sgl-router/py_test/unit/test_router_config.py +++ b/sgl-router/py_test/unit/test_router_config.py @@ -10,7 +10,7 @@ from unittest.mock import MagicMock, patch import pytest from sglang_router.launch_router import RouterArgs, launch_router from sglang_router.router import policy_from_str -from sglang_router_rs import PolicyType +from sglang_router.sglang_router_rs import PolicyType class TestRouterConfigValidation: diff --git a/sgl-router/py_test/unit/test_startup_sequence.py b/sgl-router/py_test/unit/test_startup_sequence.py index 453adb81f..11799627b 100644 --- a/sgl-router/py_test/unit/test_startup_sequence.py +++ b/sgl-router/py_test/unit/test_startup_sequence.py @@ -28,7 +28,7 @@ def setup_logger(): return logger -from sglang_router_rs import PolicyType +from sglang_router.sglang_router_rs import PolicyType class TestSetupLogger: @@ -742,7 +742,7 @@ def test_router_defaults_and_start(monkeypatch): assert captured["decode_selector"] is None assert captured["cors_allowed_origins"] is None assert captured["worker_urls"] == ["http://w1:8000"] - from sglang_router_rs import PolicyType + from sglang_router.sglang_router_rs import PolicyType assert captured["policy"] == PolicyType.RoundRobin diff --git a/sgl-router/pyproject.toml b/sgl-router/pyproject.toml index d185f894d..df1eeedc7 100644 --- a/sgl-router/pyproject.toml +++ b/sgl-router/pyproject.toml @@ -1,6 +1,6 @@ [build-system] -requires = ["setuptools>=45", "wheel", "setuptools-rust>=1.5.2"] -build-backend = "setuptools.build_meta" +requires = ["maturin>=1.0,<2.0"] +build-backend = "maturin" [project] name = "sglang-router" @@ -41,10 +41,6 @@ dev = [ ] -# https://github.com/PyO3/setuptools-rust?tab=readme-ov-file -[tool.setuptools.packages] -find = { where = ["py_src"] } - -# workaround for https://github.com/pypa/twine/issues/1216 -[tool.setuptools] -license-files = [] +[tool.maturin] +python-source = "py_src" +module-name = "sglang_router.sglang_router_rs" diff --git a/sgl-router/src/core/mod.rs b/sgl-router/src/core/mod.rs index bc42e0684..4d66ebbc7 100644 --- a/sgl-router/src/core/mod.rs +++ b/sgl-router/src/core/mod.rs @@ -4,6 +4,7 @@ //! - Worker trait and implementations //! - Error types //! - Circuit breaker for reliability +//! - Token buckets for rate limiting //! - Workflow engine for multi-step operations //! - Common utilities