Skip to content

Commit 072da53

Browse files
authored
Add vllm-router 0.1.15 riscv64 build (#2982)
vllm-router (vllm-project/router) is a Rust/PyO3 request router/load balancer for vLLM deployments, built with setuptools-rust and published as a cp38-abi3 wheel (setup.py sets py_limited_api itself; pyo3 carries no abi3-pyNN feature, so this mirrors upstream's own single build rather than per-interpreter ones). Its dependencies (clap, axum, tokio, reqwest, kube, zmq, ...) are plain web/orchestration libraries with no GPU/CUDA requirement at build or install time; the router only proxies to GPU backends, never runs inference itself. Upstream ships no build/release CI of its own, so this workflow is cibuildwheel + setuptools-rust from scratch, built once on cp312 (the image's floor; the abi3 tag claims cp38) and tagged to match upstream's wheel. A small patch ships the Apache-2.0 LICENSE in the wheel, which upstream's own twine workaround currently drops.
1 parent 31067fc commit 072da53

3 files changed

Lines changed: 160 additions & 0 deletions

File tree

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# SPDX-FileCopyrightText: 2026 The RISE Project
2+
# SPDX-License-Identifier: MIT
3+
---
4+
# Upstream (vllm-project/router) ships no build/release CI of its own (only clippy,
5+
# codeql, codespell and format checks); wheels are published to PyPI out of band.
6+
# setup.py sets `py_limited_api = "cp38"` on bdist_wheel but Cargo.toml's pyo3 dependency
7+
# carries no `abi3-pyNN` feature, so this mirrors upstream's own single untagged build
8+
# (gotcha 34): one wheel, built once and labelled cp38-abi3 like upstream's.
9+
name: Build vllm-router wheels (riscv64)
10+
11+
on:
12+
workflow_dispatch:
13+
inputs:
14+
version:
15+
description: 'Version glob to (re)build; empty builds every version of docs/packages/vllm-router.yaml not released yet'
16+
required: false
17+
default: ''
18+
pull_request:
19+
branches: [main]
20+
paths:
21+
- '.github/workflows/build-vllm-router.yml'
22+
- 'docs/packages/vllm-router.yaml'
23+
- 'patches/vllm-router/**'
24+
push:
25+
branches: [main]
26+
paths:
27+
- '.github/workflows/build-vllm-router.yml'
28+
- 'docs/packages/vllm-router.yaml'
29+
- 'patches/vllm-router/**'
30+
31+
concurrency:
32+
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
33+
cancel-in-progress: true
34+
35+
permissions:
36+
contents: read # to fetch code (actions/checkout)
37+
38+
env:
39+
MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64
40+
41+
jobs:
42+
setup:
43+
uses: $/.github/workflows/_setup.yml
44+
with:
45+
package: vllm-router
46+
version: ${{ inputs.version }}
47+
48+
build_wheel:
49+
needs: [setup]
50+
if: needs.setup.outputs.versions != '[]'
51+
name: Build vllm-router ${{ matrix.version }} cp38-abi3-manylinux_riscv64
52+
runs-on: ubuntu-24.04-riscv
53+
timeout-minutes: 720
54+
55+
env:
56+
VLLM_ROUTER_VERSION: ${{ matrix.version }}
57+
58+
strategy:
59+
fail-fast: false
60+
matrix:
61+
version: ${{ fromJSON(needs.setup.outputs.versions) }}
62+
63+
steps:
64+
- name: Checkout vllm-router v${{ env.VLLM_ROUTER_VERSION }}
65+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
66+
with:
67+
repository: vllm-project/router
68+
ref: v${{ env.VLLM_ROUTER_VERSION }}
69+
persist-credentials: false
70+
71+
- name: Checkout python-wheels
72+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
73+
with:
74+
path: python-wheels
75+
persist-credentials: false
76+
77+
- name: Apply patches
78+
run: git apply "$GITHUB_WORKSPACE"/python-wheels/patches/vllm-router/${{ env.VLLM_ROUTER_VERSION }}/*.patch
79+
80+
- name: Build wheel
81+
uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0
82+
with:
83+
output-dir: wheelhouse/
84+
# cp312 first so cibuildwheel compiles the abi3 wheel there and only retests
85+
# it on cp313/cp314 (gotcha 96/633); the image ships no cp38 to build on.
86+
only: cp312-manylinux_riscv64
87+
env:
88+
CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }}
89+
# No Rust in the manylinux image; install it and put cargo on PATH. reqwest's
90+
# default-tls feature needs OpenSSL headers; the zmq crate's vendored libzmq
91+
# build needs cmake.
92+
CIBW_BEFORE_ALL_LINUX: >-
93+
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y &&
94+
dnf -y install openssl-devel cmake
95+
CIBW_ENVIRONMENT_LINUX: 'PATH="$PATH:$HOME/.cargo/bin"'
96+
CIBW_TEST_REQUIRES: pytest pytest-asyncio
97+
CIBW_TEST_SOURCES: py_test
98+
CIBW_TEST_COMMAND: >-
99+
python -c "import vllm_router; from vllm_router_rs import PolicyType, Router;
100+
print('Rust extension: OK')" &&
101+
python -m vllm_router.launch_router --help > /dev/null && echo "Entry point: OK" &&
102+
python -m pytest -v py_test/unit
103+
104+
- name: Check the wheel carries the Apache-2.0 licence
105+
run: |
106+
python3 - wheelhouse/*.whl <<'EOF'
107+
import sys, zipfile
108+
names = zipfile.ZipFile(sys.argv[1]).namelist()
109+
assert any(n.endswith(".dist-info/licenses/LICENSE") for n in names), names
110+
print(sys.argv[1], "->", [n for n in names if ".dist-info/licenses/" in n])
111+
EOF
112+
113+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
114+
with:
115+
name: vllm-router-${{ env.VLLM_ROUTER_VERSION }}-cp38-abi3-manylinux_riscv64
116+
path: wheelhouse/*.whl
117+
if-no-files-found: error
118+
119+
publish:
120+
name: Publish vllm-router ${{ matrix.version }}
121+
needs: [setup, build_wheel]
122+
if: needs.setup.outputs.versions != '[]'
123+
strategy:
124+
fail-fast: false
125+
matrix:
126+
version: ${{ fromJSON(needs.setup.outputs.versions) }}
127+
permissions:
128+
contents: write
129+
pull-requests: write
130+
uses: $/.github/workflows/_publish-wheel.yml
131+
secrets:
132+
app-private-key: ${{ secrets.RISEPROJECT_APP_PRIVATE_KEY }}
133+
with:
134+
artifact-pattern: vllm-router-${{ matrix.version }}-*-manylinux_riscv64

‎docs/packages/vllm-router.yaml‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package-name: vllm-router
2+
source-code: https://github.com/vllm-project/router
3+
license: Apache-2.0
4+
versions:
5+
- version: 0.1.15
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Upstream-Status: Inappropriate [twine#1216's workaround does not apply to our publish pipeline, which never runs twine, and it costs us the wheel's licence file]
2+
3+
`[tool.setuptools] license-files = []` disables setuptools' default LICENSE* glob, so every
4+
upstream wheel (and ours, unpatched) ships no licence text at all. Our publish pipeline does
5+
not use twine, so the workaround upstream added for pypa/twine#1216 does not apply here and
6+
only costs us the licence file. Dropping the override restores the default
7+
`license-files = ["LICEN[CS]E*"]` glob, which picks up the repository's root `LICENSE`.
8+
9+
--- pyproject.toml
10+
+++ pyproject.toml
11+
@@ -40,10 +40,6 @@ vllm-router = "vllm_router.launch_router:main"
12+
[tool.setuptools.packages]
13+
find = { where = ["py_src"] }
14+
15+
-# workaround for https://github.com/pypa/twine/issues/1216
16+
-[tool.setuptools]
17+
-license-files = []
18+
-
19+
[tool.distutils.bdist_wheel]
20+
py_limited_api = "cp38"
21+

0 commit comments

Comments
 (0)