[XPU][CI/Release][3/N] Add xpu wheel release to release pipeline (#52108)
Signed-off-by: Kunshang Ji <kunshang.ji@intel.com> Signed-off-by: Kunshang Ji <jikunshang95@gmail.com>
Kunshang Ji committed
Aug 14, 2026 at 14:00 UTC
8e6d8e4f6a0c84db0d79129ab648492edf640fe2
6 files changed
+99
-29
.buildkite/release-pipeline.yaml
+15
-1
@@ -164,7 +164,21 @@ steps:
164
env:
165
DOCKER_BUILDKIT: "1"
166
167
- - label: "Publish XPU Triton shim index"
167
+ - label: "Build wheel - x86_64 - XPU"
168
+ depends_on: ~
169
+ id: build-wheel-x86-xpu
170
+ agents:
171
+ queue: cpu_queue_release
172
+ commands:
173
+ - "DOCKER_BUILDKIT=1 docker build --build-arg max_jobs=16 --build-arg GIT_REPO_CHECK=1 --tag vllm-ci:build-image --target vllm-build --progress plain -f docker/Dockerfile.xpu ."
174
+ - "mkdir artifacts"
175
+ - "docker run --rm -v $(pwd)/artifacts:/artifacts_host vllm-ci:build-image bash -c 'cp -r dist /artifacts_host && chmod -R a+rw /artifacts_host'"
176
+ - "bash .buildkite/scripts/upload-nightly-wheels.sh"
177
+ - 'bash .buildkite/scripts/annotate-build-artifact.sh "$$BUILDKITE_LABEL" "s3://vllm-wheels/$$BUILDKITE_COMMIT/$(cd artifacts/dist && echo *.whl)" release-wheels'
178
+ env:
179
+ DOCKER_BUILDKIT: "1"
180
+
181
+ - label: "Publish and stage XPU Triton shim"
182
key: publish-xpu-triton-shim
183
depends_on: ~
184
agents:
.buildkite/scripts/generate-and-upload-nightly-index.sh
+3
-4
@@ -53,11 +53,10 @@ if [[ "${UPDATE_NIGHTLY_INDEX:-1}" == "1" && \
53
aws s3 cp --recursive "$INDICES_OUTPUT_DIR/" "s3://$BUCKET/nightly/"
54
fi
55
56
-# detect version from any wheel in the commit directory
57
-# download the first wheel we find to extract version metadata
58
-first_wheel_key=$($PYTHON -c "import json; obj=json.load(open('$obj_json')); print(next((c['Key'] for c in obj.get('Contents', []) if c['Key'].endswith('.whl')), ''))")
56
+# detect version from a vLLM wheel in the commit directory
57
+first_wheel_key=$($PYTHON -c "import json; obj=json.load(open('$obj_json')); print(next((c['Key'] for c in obj.get('Contents', []) if c['Key'].rsplit('/', 1)[-1].startswith('vllm-') and c['Key'].endswith('.whl')), ''))")
58
if [[ -z "$first_wheel_key" ]]; then
60
- echo "Error: No wheels found in $S3_COMMIT_PREFIX"
59
+ echo "Error: No vLLM wheel found in $S3_COMMIT_PREFIX"
60
exit 1
61
fi
62
first_wheel=$(basename "$first_wheel_key")
.buildkite/scripts/generate-nightly-index.py
+7
-3
@@ -91,9 +91,9 @@ def parse_from_filename(file: str) -> WheelFileInfo:
91
else:
92
if "+" in version:
93
version_part, suffix = version.split("+", 1)
94
- # Only treat known patterns as variants (rocmXXX, cuXXX, cpu)
94
+ # Only treat known patterns as variants (rocmXXX, cuXXX, cpu, xpu)
95
# Git hashes and other suffixes are NOT variants
96
- if suffix.startswith(("rocm", "cu", "cpu")):
96
+ if suffix.startswith(("rocm", "cu", "cpu", "xpu")):
97
variant = suffix
98
version = version_part
99
# Otherwise keep the full version string (variant stays None)
@@ -429,7 +429,11 @@ if __name__ == "__main__":
429
if PY_VERSION_RE.match(version):
430
# upload-wheels.sh ensures no "dev" is in args.version
431
wheel_files = list(
432
- filter(lambda x: version in x and "dev" not in x, wheel_files)
432
+ filter(
433
+ lambda x: (version in x and "dev" not in x)
434
+ or (x.startswith("triton-") and "+xpu-" in x),
435
+ wheel_files,
436
+ )
437
)
438
print(f"Non-nightly version detected, wheel files used: {wheel_files}")
439
else:
.buildkite/scripts/xpu/publish-triton-shim.sh
+11
-3
@@ -11,12 +11,17 @@ readonly WHEEL_SHA256="3c822f73e9870512f59a6ecf5dc305a4bcab11fa623f9ce91011f6043
11
readonly WHEEL_FILENAME="${WHEEL_URL##*/}"
12
readonly ENCODED_WHEEL_FILENAME="${WHEEL_FILENAME/+/%2B}"
13
readonly S3_PREFIX="s3://${BUCKET}/${PREFIX}/"
14
+readonly COMMIT="${BUILDKITE_COMMIT:-}"
15
readonly DRY_RUN="${DRY_RUN:-0}"
16
17
if [[ "$DRY_RUN" != "0" && "$DRY_RUN" != "1" ]]; then
18
echo "DRY_RUN must be 0 or 1" >&2
19
exit 2
20
fi
21
+if [[ "$DRY_RUN" == "0" && ! "$COMMIT" =~ ^[0-9a-f]{40}$ ]]; then
22
+ echo "BUILDKITE_COMMIT must be a full lowercase commit hash" >&2
23
+ exit 2
24
+fi
25
26
cd "$(dirname "${BASH_SOURCE[0]}")/../../.."
27
@@ -70,9 +75,9 @@ sed 's/import regex as re/import re/' \
75
# shellcheck disable=SC2086
76
$PYTHON "$index_generator" \
77
--version "$PREFIX" \
73
- --wheel-dir "$PREFIX" \
78
+ --wheel-dir "$work_dir/$PREFIX" \
79
--current-objects "$objects_path" \
75
- --output-dir "$index_output_dir" \
80
+ --output-dir "$work_dir" \
81
--comment "XPU Triton shim"
82
83
grep -Fq 'href="triton/"' "$index_output_dir/index.html"
@@ -87,4 +92,7 @@ if [[ "$DRY_RUN" == "1" ]]; then
92
else
93
aws s3 cp --recursive "$index_output_dir/" "$S3_PREFIX"
94
echo "Published XPU Triton shim index to https://wheels.vllm.ai/$PREFIX/"
90
-fi
\ No newline at end of file
95
+ aws s3 cp "$S3_PREFIX$WHEEL_FILENAME" \
96
+ "s3://$BUCKET/$COMMIT/$WHEEL_FILENAME"
97
+ echo "Staged XPU Triton shim for https://wheels.vllm.ai/$COMMIT/xpu/"
98
+fi
docker/Dockerfile.xpu
+30
-3
@@ -129,6 +129,35 @@ CMD ["/bin/bash"]
129
######################### UCX + NIXL BUILD STAGE #########################
130
# Build UCX and NIXL in a dedicated stage so compiler/autotools layers are
131
# never included in the final runtime image (mirrors ROCm's build_rixl stage).
132
+######################### WHEEL BUILD STAGE #########################
133
+# Produces a standalone dist/*.whl artifact (used by the release pipeline's
134
+# "Build wheel - XPU" step), independent of the runtime image below.
135
+FROM vllm-base AS vllm-build
136
+
137
+ARG GIT_REPO_CHECK=0
138
+
139
+RUN --mount=type=cache,target=/root/.cache/uv \
140
+ --mount=type=bind,src=requirements/common.txt,target=/workspace/vllm/requirements/common.txt \
141
+ --mount=type=bind,src=requirements/xpu.txt,target=/workspace/vllm/requirements/xpu.txt \
142
+ uv pip install grpcio-tools protobuf nanobind && \
143
+ uv pip install -r /workspace/vllm/requirements/xpu.txt
144
+
145
+# Keep source-dependent layers near the end so frequent code-only changes
146
+# don't invalidate heavy dependency layers.
147
+COPY . .
148
+
149
+# Drop the pre-built Rust artifacts into the source tree. setup.py detects
150
+# them and ships them as-is, skipping the local Rust build.
151
+COPY --from=rust-build /workspace/vllm/vllm-rs vllm/vllm-rs
152
+COPY --from=rust-build /workspace/vllm/_rust_*.so vllm/
153
+
154
+RUN --mount=type=bind,source=.git,target=.git \
155
+ if [ "$GIT_REPO_CHECK" != 0 ]; then bash tools/check_repo.sh; fi
156
+
157
+RUN --mount=type=cache,target=/root/.cache/uv \
158
+ --mount=type=bind,source=.git,target=.git \
159
+ VLLM_TARGET_DEVICE=xpu python3 setup.py bdist_wheel --dist-dir=dist --py-limited-api=cp38
160
+
161
FROM vllm-base AS ucx-nixl-build
162
163
ARG UCX_VERSION=v1.21.0-rc2
@@ -201,9 +230,7 @@ RUN --mount=type=cache,target=/root/.cache/uv \
230
--mount=type=bind,src=requirements/test/xpu.txt,target=/workspace/vllm/requirements/test/xpu.txt \
231
uv pip install grpcio-tools protobuf nanobind && \
232
uv pip install -r /workspace/vllm/requirements/xpu.txt && \
204
- uv pip install --no-build-isolation -r /workspace/vllm/requirements/test/xpu.txt && \
205
- uv pip uninstall triton triton-xpu && \
206
- uv pip install triton-xpu==3.7.2
233
+ uv pip install --no-build-isolation -r /workspace/vllm/requirements/test/xpu.txt
234
235
# Keep source-dependent layers near the end so frequent code-only changes
236
# don't invalidate heavy dependency and UCX/NIXL layers.
docs/getting_started/installation/gpu.xpu.inc.md
+33
-15
@@ -20,7 +20,26 @@ There is no extra information on creating a new Python environment for this devi
20
--8<-- [end:set-up-using-python]
21
--8<-- [start:pre-built-wheels]
22
23
-Currently, there are no pre-built XPU wheels.
23
+Pre-built vLLM XPU wheels are published to `wheels.vllm.ai`. Each XPU wheel
24
+index also contains the `triton==3.7.2+xpu` shim described below. PyTorch XPU
25
+packages are served from the PyTorch XPU index, so both index URLs are needed.
26
+
27
+#### Install the latest code
28
+
29
+To install the wheel built from the latest main branch:
30
+
31
+```bash
32
+uv pip install vllm --extra-index-url https://wheels.vllm.ai/nightly/xpu --extra-index-url https://download.pytorch.org/whl/xpu --index-strategy unsafe-best-match
33
+```
34
+
35
+#### Install specific revisions
36
+
37
+If you want to access the wheels for previous commits (e.g. to bisect the behavior change, performance regression), you can specify the commit hash in the URL:
38
+
39
+```bash
40
+export VLLM_COMMIT=730bd35378bf2a5b56b6d3a45be28b3092d26519 # use full commit hash from the main branch
41
+uv pip install vllm --extra-index-url https://wheels.vllm.ai/${VLLM_COMMIT}/xpu --extra-index-url https://download.pytorch.org/whl/xpu --index-strategy unsafe-best-match
42
+```
43
44
--8<-- [end:pre-built-wheels]
45
--8<-- [start:build-wheel-from-source]
@@ -36,25 +55,24 @@ pip install --upgrade pip
55
pip install -v -r requirements/xpu.txt
56
```
57
39
-- Then, install the correct Triton package for Intel XPU.
40
-
41
- The default `triton` package (for NVIDIA GPUs) may be installed as a transitive dependency (e.g., via `xgrammar`). For Intel XPU, you must replace it with `triton-xpu`:
42
-
43
- ```bash
44
- pip uninstall -y triton triton-xpu
45
- pip install triton-xpu==3.7.2 --extra-index-url https://download.pytorch.org/whl/xpu
46
- ```
47
-
48
- !!! note
49
- - `triton` (without suffix) is for NVIDIA GPUs only. On XPU, using it instead of `triton-xpu` can cause correctness or runtime issues.
50
- - For torch 2.13 (the version used in `requirements/xpu.txt`), the matching package is `triton-xpu==3.7.2`. If you use a different version of torch, check the corresponding `triton-xpu` version in [docker/Dockerfile.xpu](https://github.com/vllm-project/vllm/blob/main/docker/Dockerfile.xpu).
51
-
52
-- Finally, build and install vLLM XPU backend:
58
+- Then, install vLLM XPU backend:
59
60
```bash
61
VLLM_TARGET_DEVICE=xpu pip install --no-build-isolation -e . -v
62
```
63
64
+!!! note
65
+ `requirements/xpu.txt` pins `triton==3.7.2+xpu`, a compatibility shim
66
+ hosted on `https://wheels.vllm.ai/xpu` that transparently resolves to
67
+ the real Intel XPU implementation (`triton-xpu`). This exists because
68
+ some transitive dependencies (e.g. `xgrammar`) unconditionally
69
+ require a distribution literally named `triton`, which otherwise
70
+ resolves to the NVIDIA-only PyPI `triton` package on XPU and can
71
+ cause correctness or runtime issues. No manual uninstall/reinstall of
72
+ `triton`/`triton-xpu` is needed; both `pip install` and `uv pip
73
+ install --index-strategy unsafe-best-match` resolve the correct
74
+ package automatically.
75
+
76
--8<-- [end:build-wheel-from-source]
77
--8<-- [start:pre-built-images]
78