执行摘要
- 一句话:ROCM Python-only CI 改用同构建 wheel 与源码 overlay
- 推荐动作:值得精读,尤其关注 run-amd-test.sh 中「git archive overlay + VLLM_VERSION_OVERRIDE + 同构建 wheel」的组合处理模式,这是 vLLM native/artifact CI 架构的关键一环,对理解后续 ROCm CI 演进很有帮助;同时它示范了「测试必须验证同一次构建产物」的 CI 最佳实践,对任何依赖预编译产物的项目都有参考价值。
功能与动机
PR body 明确要求 "Package the verified checkout into the native artifact workspace and install the wheel produced by that same build",并 "Preserve the source tree and merge-base identity needed by the Python-only installation test"。此前 ROCm native artifact 工作区只包含 wheel 与测试文件,没有源码树和 .git,python_only_compile.sh 只能从 wheels.vllm.ai 拉取 merge-base 对应的预编译 wheel——这既依赖发布流水线进度(需要 5 分钟 × 5 次轮询等待 metadata 发布),又导致测试验证的并非当前 commit 的构建产物,可能掩盖新回归或产生假失败。
实现拆解
- 测试脚本 wheel 来源重构(tests/standalone_tests/python_only_compile.sh):先探测
is_rocm(VLLM_TARGET_DEVICE / ROCM_PATH / /opt/rocm / rocminfo),ROCm 环境下优先读取 VLLM_PRECOMPILED_WHEEL_LOCATION 指定的同构建 wheel(校验文件存在且 basename 匹配 vllm-*.whl 并 realpath),否则从 legacy 镜像的 /opt/vllm-wheels 取唯一 wheel;两者都不存在时才回退到旧逻辑(CI_STANDALONE_MERGE_BASE 或 git merge-base + wheels.vllm.ai metadata.json 轮询)。安装分支新增 VLLM_PRECOMPILED_WHEEL_LOCATION 环境变量路径,走 setup.py develop --no-deps,避免无编译器环境下触发源码编译。
- native workspace 的源码树 overlay(.buildkite/scripts/hardware_ci/run-amd-test.sh):
prepare_native_workspace 新增 test_commands 参数;当命令包含 python_only_compile.sh 时,要求 BUILDKITE_BUILD_CHECKOUT_PATH 存在且为 git worktree,校验 checkout 的 HEAD 与 artifact 记录的 recorded_commit 一致,然后用 git archive 将 verified commit 打包解压到 workspace(而非直接拷贝 worktree,避免 dirty/untracked 文件污染),并检查 setup.py、pyproject.toml、vllm 目录是否齐全。
- 版本与 wheel 环境变量注入:由于 overlay 故意不带 .git,setuptools-scm 无法从 git 推导版本,脚本用
importlib.metadata 读取已安装 vllm 的版本写入 VLLM_VERSION_OVERRIDE 并导出,同时把 artifact 中的 wheel 路径写入 VLLM_PRECOMPILED_WHEEL_LOCATION;在 native runtime 分支对 Python-only 作业强制 VLLM_TARGET_DEVICE=rocm,明确该 no-GPU 作业验证的是 ROCm 预编译/editable 安装路径而非 CPU 平台选择。
- 作业平台迁移与管道配置:.buildkite/test-amd.yaml 将 Python-only Installation 从 mi250_1(mirror_hardwares: amdgfx90anightly/amdmi250)迁到 mi300_1(amdgfx942nightly/amdmi300)并加
dind: false;.buildkite/test_areas/misc.yaml 的 AMD mirror 同步改为 device: mi300_1 与 dind: false。此前手动触发时出现目录创建权限问题,经 infra 排查后解决,review 阶段又按 tjtanaa 建议重新启用了该作业(不再是 input-gated,但 optional 标志保留)。
- 测试与配置配套:没有新增单元测试,验证依赖多次 Buildkite 全量 CI 与 AMD CI 手动触发结果;最终由 tjtanaa 批准合入。
关键文件:
tests/standalone_tests/python_only_compile.sh(模块 安装测试;类别 test;类型 test-coverage): Python-only 安装测试的核心脚本,重构 wheel 来源选择逻辑,优先使用同构建 wheel,是本次变更的验证目标所在。
.buildkite/scripts/hardware_ci/run-amd-test.sh(模块 作业脚本;类别 infra;类型 infrastructure): native workspace 准备逻辑的核心改动:为 Python-only 作业 overlay 完整源码树并注入 wheel/版本环境变量,是本次变更的机制中枢。
.buildkite/test-amd.yaml(模块 流水线配置;类别 config;类型 configuration): AMD 专属 CI 流水线定义,Python-only Installation 作业从 mi250_1 迁移到 mi300_1 并启用 dind: false。
.buildkite/test_areas/misc.yaml(模块 测试编排;类别 config;类型 configuration): 通用 CI 测试区域中的 AMD mirror 配置同步调整,跟随作业平台迁移。
关键符号:prepare_native_workspace, is_native_runtime
关键源码片段
tests/standalone_tests/python_only_compile.sh
Python-only 安装测试的核心脚本,重构 wheel 来源选择逻辑,优先使用同构建 wheel,是本次变更的验证目标所在。
# 优先使用同一次构建(same-build)的 ROCm wheel,而不是去 wheels.vllm.ai
# 拉取 merge-base 对应的预编译产物,保证 Python-only CI 验证的就是当前
# commit 构建出来的 wheel。
rocm_wheel=""
is_rocm=0
_vllm_target_lower="$(printf '%s' "${VLLM_TARGET_DEVICE:-}" | tr '[:upper:]' '[:lower:]')"
if [[ "${_vllm_target_lower}" == "rocm" || -n "${ROCM_PATH:-}" || -d /opt/rocm ]] \
|| command -v rocminfo >/dev/null 2>&1; then
is_rocm=1
fi
unset -v _vllm_target_lower
if [[ "${is_rocm}" == "1" ]]; then
# Native CI 通过环境变量显式传入已验证的 wheel 产物路径;
# legacy ROCm 镜像则把同一个构建的 wheel 放在 /opt/vllm-wheels。
if [[ -n "${VLLM_PRECOMPILED_WHEEL_LOCATION:-}" ]]; then
rocm_wheel="${VLLM_PRECOMPILED_WHEEL_LOCATION}"
# 校验文件存在且命名符合 vllm-*.whl,避免误传其他路径
if [[ ! -f "${rocm_wheel}" || "$(basename "${rocm_wheel}")" != vllm-*.whl ]]; then
echo "ERROR: invalid ROCm wheel location: ${rocm_wheel}" >&2
exit 1
fi
rocm_wheel="$(realpath -- "${rocm_wheel}")"
elif [[ -d /opt/vllm-wheels ]]; then
shopt -s nullglob
rocm_wheels=(/opt/vllm-wheels/vllm-*.whl)
shopt -u nullglob
if [[ "${#rocm_wheels[@]}" -ne 1 ]]; then
echo "ERROR: expected exactly one vLLM wheel in /opt/vllm-wheels, found ${#rocm_wheels[@]}." >&2
exit 1
fi
rocm_wheel="${rocm_wheels[0]}"
fi
fi
# 只有拿不到本地 wheel 时才回退到 wheels.vllm.ai 的 merge-base 发布产物
if [[ -n "${rocm_wheel}" ]]; then
echo "INFO: using same-build ROCm wheel: ${rocm_wheel}"
else
# 旧逻辑:解析 CI_STANDALONE_MERGE_BASE 或 git merge-base,
# 再轮询 wheels.vllm.ai 的 metadata.json(5 次 × 5 分钟)
# ...(此处省略与 base 版本一致的 merge-base 解析与轮询代码)
fi
# ROCm 场景走 setuptools develop + 预编译 wheel;--no-deps 避免在
# 无编译器环境下触发依赖源码编译。
if [[ -n "${rocm_wheel}" ]]; then
VLLM_PRECOMPILED_WHEEL_LOCATION="${rocm_wheel}" VLLM_USE_PRECOMPILED=1 python3 setup.py develop --no-deps
elif [[ "${is_rocm}" == "1" ]]; then
VLLM_PRECOMPILED_WHEEL_COMMIT=$merge_base_commit VLLM_USE_PRECOMPILED=1 python3 setup.py develop --no-deps
else
VLLM_PRECOMPILED_WHEEL_COMMIT=$merge_base_commit VLLM_USE_PRECOMPILED=1 pip3 install -vvv -e .
fi
.buildkite/scripts/hardware_ci/run-amd-test.sh
native workspace 准备逻辑的核心改动:为 Python-only 作业 overlay 完整源码树并注入 wheel/版本环境变量,是本次变更的机制中枢。
# prepare_native_workspace 的收尾部分:对 Python-only 安装作业,把
# Buildkite checkout 中已验证 commit 的完整源码树 overlay 到 artifact
# workspace,因为 artifact 只含 wheel + 测试工作区,没有 setup.py 和
# vllm 源码树。
if [[ "${test_commands}" == *python_only_compile.sh* ]]; then
checkout="${BUILDKITE_BUILD_CHECKOUT_PATH:-}"
if [[ -z "${checkout}" || ! -d "${checkout}" ]]; then
echo "Python-only native CI requires BUILDKITE_BUILD_CHECKOUT_PATH" >&2
return 1
fi
# 校验 checkout 的 commit 必须与 artifact 记录的 commit 一致,
# 防止把其他 commit 的源码混进本次构建产物
checkout_commit=$(
git -c "safe.directory=${checkout}" -C "${checkout}" rev-parse HEAD
) || return 1
if [[ "${checkout_commit}" != "${recorded_commit}" ]]; then
echo "Buildkite checkout ${checkout_commit} does not match ROCm artifact ${recorded_commit}" >&2
return 1
fi
# overlay 故意不带 .git,setuptools-scm 无法推导版本号,
# 所以从已安装的 wheel 里取版本,保证 editable 安装与产物一致
VLLM_VERSION_OVERRIDE=$(
python3 -c 'import importlib.metadata as m; print(m.version("vllm"))'
) || return 1
export VLLM_VERSION_OVERRIDE
VLLM_PRECOMPILED_WHEEL_LOCATION="${wheels[0]}"
export VLLM_PRECOMPILED_WHEEL_LOCATION
# 用 git archive 而不是直接拷贝 worktree,
# 避免 dirty/untracked 文件污染 artifact 对应的 workspace
git -c "safe.directory=${checkout}" -C "${checkout}" \
archive --format=tar "${recorded_commit}" \
| tar --no-same-owner -C "${workspace_dir}" -xf - || return 1
for required_source in setup.py pyproject.toml vllm; do
if [[ ! -e "${workspace_dir}/${required_source}" ]]; then
echo "Full source checkout is missing ${required_source}" >&2
return 1
fi
done
fi
评论区精华
- tjtanaa 在合并前提出顺序依赖:"I think we should merge this after this PR #49365. I have added review to #49365.",保证两个 native workspace 相关改动按序合入。
- tjtanaa 手动触发 AMD CI 后发现 Python-only 测试组不通过:"This test group is not triggered on AMD CI... result not passing";AndreasKaratzas 定位为 "permission issue regarding creating a dir. Will check with infra",与基础设施团队确认后修复。
-
tjtanaa 在批准时再次指出门控问题:"LGTM, but I think that step is still gated behind input block? Should we enable it so that it always run now that we fixed the test?",AndreasKaratzas 回复 "I re-enabled it",随后作业恢复常态化触发。
-
合并顺序:先合 #49365 (other): 按协作顺序等待 #49365 先合,本 PR 随后合入。
- AMD CI 上 Python-only 测试组未自动触发且手动运行失败 (other): 与基础设施团队协作解决权限问题后测试通过。
- 作业是否仍被 input block 门控 (other): 作业已重新启用,纳入常规触发(optional 标志保留)。
风险与影响
- 风险:
- run-amd-test.sh 的 commit 一致性校验非常严格:若 Buildkite checkout 与 artifact 记录的 commit 不一致,Python-only 作业会直接失败(fail fast);但由于分支只对包含 python_only_compile.sh 的作业生效,不影响其他 native 作业。
VLLM_VERSION_OVERRIDE 依赖已安装 wheel 的版本元数据(importlib.metadata),若 artifact 中 vllm 未安装或安装损坏会失败;同时 overlay 用 git archive 整体覆盖 workspace,若 artifact 中恰好有同名目录(如 vllm/)会被源码树覆盖。
- 作业平台从 mi250_1 迁移到 mi300_1 并启用 dind: false:若 mi300 镜像缺少运行该脚本的条件(如 /opt/vllm-wheels 布局差异),作业可能失败;目前有
optional: true(test-amd.yaml)与 soft_fail: true(misc.yaml mirror)缓冲。
- 对 wheels.vllm.ai 外部依赖的解除是正向变化,但保留了完整回退路径,双路径维护略微增加脚本复杂度。
- 影响:影响范围为 AMD/ROCm CI 的 Python-only Installation 测试组及其运行平台:测试保真度提升(验证同构建产物)、稳定性提升(不再受 wheels.vllm.ai 发布时序和 5 分钟轮询影响)、并解除了对 merge-base 旧产物的隐式依赖。对产品代码和最终用户无感知;对 CI 维护团队而言,作业平台迁移(mi250→mi300)与 input gate 重新启用会带来一定的运维关注成本,但整体收益大于成本。
- 风险标记:平台迁移(mi250→mi300), VLLM_VERSION_OVERRIDE 依赖已安装 wheel, git archive overlay 覆盖工作区文件
关联脉络
- PR #49365 (标题不在输入上下文中): tjtanaa 在评论中明确要求先合并 #49365 再合本 PR,二者同属 ROCm native/artifact workspace CI 演进;该 PR 不在输入的历史列表中,标题无法确认。
参与讨论