[CI] Add PyTorch stable ABI audit check (#48164)

Signed-off-by: Chris Leonard <chleonar@redhat.com> Co-authored-by: Shengqi Chen <harry-chen@outlook.com>

Chris Leonard committed Jul 28, 2026 at 05:37 UTC 247470f23a4c8191a296c1993c4e86727ffb5191
6 files changed +130 -1
.buildkite/check-torch-abi.py new
+102
@@ -0,0 +1,102 @@
1 +# SPDX-License-Identifier: Apache-2.0
2 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 +
4 +"""Audit vLLM compiled libraries for PyTorch stable ABI compliance."""
5 +
6 +import fnmatch
7 +import sys
8 +from pathlib import Path
9 +
10 +from torch_abi_audit import inspect_package
11 +from torch_abi_audit.report import ExtensionReport, PackageReport
12 +
13 +# Temporary allowlist of extensions not yet on the stable ABI.
14 +# Shrink and remove over time.
15 +ALLOWED_UNSTABLE_LIBRARIES: tuple[str, ...] = (
16 + "vllm_flash_attn/_vllm_fa2_C.abi3.so",
17 + "vllm_flash_attn/_vllm_fa3_C.abi3.so",
18 + "third_party/deep_gemm/_C*.so",
19 +)
20 +
21 +
22 +def _relative_path(lib: ExtensionReport, package_root: Path) -> str:
23 + try:
24 + return lib.path.relative_to(package_root).as_posix()
25 + except ValueError:
26 + return lib.path.name
27 +
28 +
29 +def _is_torch_unstable(lib: ExtensionReport) -> bool:
30 + return lib.error is None and lib.torch.uses_torch and not lib.torch.stable
31 +
32 +
33 +def _matches_allowlist(rel_path: str, patterns: tuple[str, ...]) -> bool:
34 + return any(fnmatch.fnmatch(rel_path, pattern) for pattern in patterns)
35 +
36 +
37 +def _iter_libs(report: PackageReport) -> tuple[ExtensionReport, ...]:
38 + return (*report.extensions, *report.bundled_libs)
39 +
40 +
41 +def _collect_unstable(report: PackageReport) -> list[str]:
42 + return sorted(
43 + _relative_path(lib, report.root)
44 + for lib in _iter_libs(report)
45 + if _is_torch_unstable(lib)
46 + )
47 +
48 +
49 +def _find_stale_allowlist_entries(
50 + report: PackageReport, patterns: tuple[str, ...]
51 +) -> list[str]:
52 + """Allowlist patterns that match a built library which is no longer unstable."""
53 + stale: list[str] = []
54 + for pattern in patterns:
55 + for lib in _iter_libs(report):
56 + if lib.error is not None:
57 + continue
58 + if not fnmatch.fnmatch(_relative_path(lib, report.root), pattern):
59 + continue
60 + if not _is_torch_unstable(lib):
61 + stale.append(pattern)
62 + break
63 + return stale
64 +
65 +
66 +def check_torch_abi(
67 + package: str = "vllm",
68 + patterns: tuple[str, ...] = ALLOWED_UNSTABLE_LIBRARIES,
69 +) -> int:
70 + report = inspect_package(package)
71 + if report.error:
72 + print(f"error: failed to inspect {package!r}: {report.error}", file=sys.stderr)
73 + return 2
74 +
75 + unstable = _collect_unstable(report)
76 + unexpected = [
77 + rel_path for rel_path in unstable if not _matches_allowlist(rel_path, patterns)
78 + ]
79 + stale = _find_stale_allowlist_entries(report, patterns)
80 +
81 + if unexpected or stale:
82 + if unexpected:
83 + print(
84 + "Not allowed: torch-unstable libraries outside "
85 + f"ALLOWED_UNSTABLE_LIBRARIES: {', '.join(unexpected)}",
86 + file=sys.stderr,
87 + )
88 + if stale:
89 + print(
90 + "Not allowed: stale ALLOWED_UNSTABLE_LIBRARIES entries: "
91 + f"{', '.join(stale)}",
92 + file=sys.stderr,
93 + )
94 + return 1
95 +
96 + print("Torch stable ABI check passed.")
97 + return 0
98 +
99 +
100 +if __name__ == "__main__":
101 + print(">>> Auditing vLLM extension modules for PyTorch stable ABI compliance")
102 + sys.exit(check_torch_abi())
.buildkite/ci_config.yaml
+1
@@ -14,6 +14,7 @@ run_all_patterns:
14 - "setup.py"
15 - "csrc/"
16 - "cmake/"
17 + - ".buildkite/check-torch-abi.py"
18 run_all_exclude_patterns:
19 - "docker/Dockerfile."
20 - "csrc/cpu/"
.buildkite/test_areas/torch_abi.yaml new
+14
@@ -0,0 +1,14 @@
1 +group: Torch ABI
2 +depends_on:
3 + - image-build
4 +steps:
5 +- label: Torch Stable ABI Audit
6 + key: torch-stable-abi-audit
7 + timeout_in_minutes: 5
8 + source_file_dependencies:
9 + - .buildkite/check-torch-abi.py
10 + - csrc/
11 + - cmake/
12 + - setup.py
13 + commands:
14 + - python3 /vllm-workspace/.buildkite/check-torch-abi.py
requirements/test/cpu.txt
+6
@@ -1,5 +1,7 @@
1 # This file was autogenerated by uv via the following command:
2 # uv pip compile requirements/test/cuda.in -o requirements/test/cpu.txt --index-strategy unsafe-best-match --torch-backend cpu --python-platform x86_64-manylinux_2_28 --python-version 3.12
3 +abi3info==2025.11.29
4 + # via torch-abi-audit
5 absl-py==2.1.0
6 # via rouge-score
7 accelerate==1.13.0
@@ -763,6 +765,8 @@ pycparser==2.22
765 # via cffi
766 pycryptodomex==3.22.0
767 # via blobfile
768 +pycxxfilt==0.1.0
769 + # via torch-abi-audit
770 pydantic==2.12.0
771 # via
772 # -r requirements/test/../common.txt
@@ -1127,6 +1131,8 @@ torch==2.13.0+cpu
1131 # vector-quantize-pytorch
1132 # vocos
1133 # xgrammar
1134 +torch-abi-audit==0.0.1
1135 + # via -r requirements/test/cuda.in
1136 torchaudio==2.11.0+cpu
1137 # via
1138 # -r requirements/test/cuda.in
requirements/test/cuda.in
+1 -1
@@ -45,7 +45,7 @@ schemathesis>=4.0.0 # Required for openai schema test.
45 # quantization
46 bitsandbytes==0.49.2
47 buildkite-test-collector==0.1.9
48 -
48 +torch-abi-audit # CI check for PyTorch stable ABI compliance
49
50 genai_perf>=0.0.8
51 tritonclient>=2.51.0
requirements/test/cuda.txt
+6
@@ -1,5 +1,7 @@
1 # This file was autogenerated by uv via the following command:
2 # uv pip compile requirements/test/cuda.in -c requirements/cuda.txt -o requirements/test/cuda.txt --index-strategy unsafe-best-match --torch-backend cu130 --python-platform x86_64-manylinux_2_28 --python-version 3.12
3 +abi3info==2025.11.29
4 + # via torch-abi-audit
5 absl-py==2.1.0
6 # via rouge-score
7 accelerate==1.13.0
@@ -850,6 +852,8 @@ pycparser==2.22
852 # via cffi
853 pycryptodomex==3.22.0
854 # via blobfile
855 +pycxxfilt==0.1.0
856 + # via torch-abi-audit
857 pydantic==2.12.0
858 # via
859 # -c requirements/common.txt
@@ -1225,6 +1229,8 @@ torch==2.13.0+cu130
1229 # vector-quantize-pytorch
1230 # vocos
1231 # xgrammar
1232 +torch-abi-audit==0.0.1
1233 + # via -r requirements/test/cuda.in
1234 torchaudio==2.11.0+cu130
1235 # via
1236 # -c requirements/cuda.txt