diff --git a/knowledge/general/bug/_index.md b/knowledge/general/bug/_index.md index 56e9d2f0..099f3a31 100644 --- a/knowledge/general/bug/_index.md +++ b/knowledge/general/bug/_index.md @@ -1,7 +1,7 @@ --- title: "Bug" created: 2026-08-07 -updated: 2026-08-07 +updated: 2026-11-09 type: index tags: [general, bug] sources: [] @@ -22,5 +22,5 @@ sources: [] | 遇到什么 | 查看哪里 | 说明 | |---|---|---| -| 按优先级与 SLO 计算 DI | [DI 计算说明](guides/di-calculation.md) | 分级表、偶现降级、按 SLO 累加 | +| 按优先级与 SLO 计算 DI | [DI 计算说明](guides/di-calculation.md) | 分级表、偶现降级、达到 SLO 升一级 | | 查找其他 Bug 专项 | [guides 索引](guides/_index.md) | 当前有效的 Bug 方法入口 | diff --git a/knowledge/general/bug/guides/di-calculation.md b/knowledge/general/bug/guides/di-calculation.md index 7e40e324..0dc7101a 100644 --- a/knowledge/general/bug/guides/di-calculation.md +++ b/knowledge/general/bug/guides/di-calculation.md @@ -1,40 +1,42 @@ --- title: "DI 计算说明" created: 2026-08-07 -updated: 2026-09-22 +updated: 2026-11-09 type: guide tags: [general, bug] -sources: [] +sources: ["PR #444 review 2026-11-09"] --- # DI 计算说明 -按 Bug 优先级给出基础 DI(Defect Intensity)与 SLO,并说明偶现降级与按 SLO 累加的计算方式。 +按 Bug 优先级给出基础 DI(Defect Intensity)与 SLO,并说明偶现降级与 SLO 升级的计算方式。 +现行口径不按未关闭天数累加:issue 达到 SLO 后严重度升一级,DI 取升级后级别的基础值。 相关入口:[bug 主题](../_index.md)、[调试](../../debug/_index.md)、[测试与 CI](../../ci/_index.md)。 ## Bug 分级标准 | Bug 优先级分类 | 划分标准 | DI 值 | SLO | |---|---|---|---| -| critical | 高优先级 | 10 | 1 天 | -| high priority | CI Failure | 3 | 5 天 | -| medium priority | 中优先级 | 1 | 10 天 | -| low priority | 低优先级 | 0.1 | 14 天 | +| critical | 数据损坏或结果错误、服务不可用、安全或凭据问题、静默路由错误 | 10 | 1 天 | +| high priority | 默认分支 CI 失败、主路径功能不可用、明确的精度或性能回退 | 3 | 5 天 | +| medium priority | 功能受损但存在可用绕过、非主路径报错 | 1 | 10 天 | +| low priority | 体验、日志、文档和提示类问题 | 0.1 | 14 天 | | invalid | 非问题 | 0 | / | -## 其他规则 +定级由 issue 负责人按上表判定;同一个问题同时满足多行时取最高一级,并以仓库实际使用的 +severity label 或发布记录留痕。 -1. **偶现降级**:若为偶现问题,分类等级自动降低一级。 -2. **按 SLO 累加**:每达到一次 SLO,DI 值累加一次。 +## 其他规则 -### 累加示例 +1. **偶现降级**:偶现问题在初始级别上降一级。 +2. **SLO 升级**:DI 不按天数累加;issue 未关闭时间达到 SLO 后严重度升一级,DI 取升级后级别 + 的基础值。重复升级的粒度以当期发布说明为准,最高不超过 critical。 +3. **invalid 恒为 0**:不参与剩余 DI 汇总。 -critical 等级 bug(基础 DI = 10,SLO = 1 天): +### 升级示例 -| 未关闭天数 | 达到的 SLO 次数 | DI | -|---|---|---| -| 第 1 天 | 1 | 10 | -| 第 2 天 | 2 | 20 | -| 第 3 天 | 3 | 30 | +medium 级 issue(基础 DI = 1,SLO = 10 天)在第 10 天仍未关闭时升为 high,DI 取 3;若继续 +跨过 high 的 SLO,则再升为 critical,DI 取 10。 -通式:`DI = 基础 DI × ⌈未关闭天数 / SLO 天数⌉`(`invalid` 始终为 0)。 +通式:`DI = 基础 DI(当前级别)`,`当前级别 = 初始级别 + 已跨过的 SLO 次数`(上限 critical, +`invalid` 始终为 0)。 diff --git a/knowledge/repos/vllm-router/_index.md b/knowledge/repos/vllm-router/_index.md index 63090289..1e7c12de 100644 --- a/knowledge/repos/vllm-router/_index.md +++ b/knowledge/repos/vllm-router/_index.md @@ -4,27 +4,32 @@ created: 2026-11-10 updated: 2026-11-10 type: index tags: [vllm-router] -sources: [] +sources: [pyproject.toml, .buildkite/README.md, "vllm-project/router@ddf78218cffdb6361579d3babd69a90ba6d63aaa"] --- # vLLM Router 仓库知识入口 ## 仓库和适用范围 -- 上游仓库:`vllm-project/router`。 +- 上游仓库:`vllm-project/router`。PyPI 包 `vllm-router`,Python 模块 `vllm_router`,console + script 与 Rust 二进制都叫 `vllm-router`;默认分支 `main`,tag 形如 `v0.1.17`。 - Canonical slug:`vllm-router`。别名包括 `vllm_router` 与 GitHub 仓库名 `router`。 -- 适用范围:该仓库的 issue 分诊与优先级打标。 +- 适用范围:该仓库的 issue 分诊与优先级打标,以及 CI 与发布知识;发版事实按 + `main@ddf78218` 与 tag `v0.1.17` 核对。 ## 什么时候查这里 - 用户给出 `vllm-project/router`、`vllm-router` 或 `router`,需要映射到本目录。 - 为该仓库的 issue 选择致命、高、中、低。 +- 判断本仓库怎么发版:tag 形态、版本号要同步哪几份文件、PyPI/镜像产物哪些是硬门禁。 +- 区分 L1 ready / L2 merge / L3 nightly 与 `release` 四条 Buildkite 通道的适用范围。 ## 不放什么 -- 换仓库仍然成立的方法放 [general](../../general/_index.md)。 +- 换仓库仍然成立的方法放 [general](../../general/_index.md),包括通用的发版、CI 和 DI 口径。 - 其他仓库的调度实现、模型或 CI 经验。 - 单次 issue 的调查时间线、PR 复盘和评测记录。 +- 机器地址、queue 凭据、本地 checkout 路径 → Git 忽略的 `local/`。 ## 目录内容 @@ -32,3 +37,12 @@ sources: [] |---|---|---| | 给 `vllm-project/router` 的 issue 定级或打标 | [issue 分级规则](bug/rules.md) | 致命 / 高 / 中 / 低;先看影响,再看特性 | | 查看本仓库的 Bug 主题入口 | [bug](bug/_index.md) | 只路由到分级规则 | +| 发版门禁、tag 与版本号同步、PyPI/Docker/GitHub Release 产物核对和常见失败 | [发布规范](ci/release-gates.md) | `release-pipeline.yml` 真实执行的门禁 + 发布前质量门槛 | +| L1/L2/L3 通道、pytest marker、GPU preset、nightly 与 release 的分工 | [CI 入口](ci/_index.md) | 只写本仓库相对通用 CI 的差异 | + +## 当前边界 + +本切片目前只有 `bug/` 与 `ci/` 两个工作主题。`components/`、`models/` 和代码 owner 路由 +(`_routes.yaml`)尚未建立;`adapters/vllm_router` 只在 issue 分诊时注入 briefing,不提供代码 +owner 路由。审查本仓库代码时不能把发布页当代码 owner,必须按 live 源码和 PR changed files +自行定位。 diff --git a/knowledge/repos/vllm-router/ci/_index.md b/knowledge/repos/vllm-router/ci/_index.md new file mode 100644 index 00000000..55d17f33 --- /dev/null +++ b/knowledge/repos/vllm-router/ci/_index.md @@ -0,0 +1,57 @@ +--- +title: "vLLM-Router CI" +created: 2026-11-06 +updated: 2026-11-09 +type: index +tags: [vllm-router, ci] +sources: [.buildkite/README.md, .buildkite/pipeline.yml, .buildkite/test-ready.yml, .buildkite/test-merge.yml, .buildkite/test-nightly.yml, .buildkite/release-pipeline.yml, .buildkite/ci_mirror_hardwares.yml, .buildkite/scripts/build-ci-image.sh, pytest.ini, tests/python/helpers/mark.py, "vllm-project/router@ddf78218cffdb6361579d3babd69a90ba6d63aaa"] +--- + +# vLLM-Router CI + +## 什么时候查这里 + +- 判断某类改动该进 L1 ready、L2 merge 还是 L3 nightly,或核对某个 job 的实际触发条件。 +- 发版前确认默认分支上哪条通道的结果才算证据 → 见下面目录里的发布规范。 + +## 不放什么 + +- 跨仓库通用的测试选择方法 → [通用 CI](../../../general/ci/_index.md)。 +- 具体 job 的历史失败复盘;需要时看对应 Buildkite build。 + +## 上传条件 + +`pipeline.yml` 先构建 Rust release 二进制、wheel 和 NVIDIA CI 镜像,再按分支和 label 上传三个 +测试文件。上传只依赖 `build` 组,彼此不依赖;GPU job 还要等 `image-build`。CI 镜像由 +`docker/Dockerfile.ci` 推到共享 ECR,tag 里带 `router-`,不会顶掉同 commit 的其他项目镜像。 + +| 通道 | 触发 | 内容 | 证据边界 | +|---|---|---|---| +| L1 ready | 非默认分支带 `ready` label(fork 也跑) | Rust 单测/集成(`--features cpu,ready`)、Python 单测(`-m "ready and cpu"`,`--ignore=tests/python/e2e`,产出 `coverage.xml`)、P/D smoke(4×L4,`SKIP_LM_EVAL`,1 条 sanity)、kv_aware e2e(2×L4)、gRPC P/D smoke(4×L4,`RUN_LM_EVAL=0`) | 只证明该 PR 自身可合并,不能当默认分支健康度 | +| L2 merge | 默认分支 push(`NIGHTLY != 1`)、merge queue(base 为默认分支)、或 `merge-test` label | xGMI smoke(`read_mode=true`、GSM8K `LM_EVAL_LIMIT=20`、基线 0.38 允许 −0.03)、RDMA `SMOKE_ONLY`(两节点) | 默认分支健康度与 ROCm 平台基线 | +| L3 nightly | 默认分支 `NIGHTLY=1`,或 `nightly-test` label | 单测(PR 同时带 `ready` 时整组跳过)、P/D 全量 GSM8K(HTTP 与 gRPC)、gRPC prefix-KV perf(`rust_grpc` + `python_http`,`c16-r32`、`hit99-c4`、`hit99-c64`,2×H100)、L1 encode perf(Qwen3-0.6B,1×L4,`hit0.30`/`hit0.99999` × `c4`/`c16`,L1 on/off)、ROCm xGMI 与 RDMA 的 read true/false 矩阵 | 覆盖最广,但不阻塞 PR,过期结果不能当发版证据 | +| release | `v*` tag 或手动触发 | 只构建 wheel/二进制、smoke、发 PyPI、发镜像 | 不跑 L1–L3,见发布规范 | + +几处窄 gate 容易漏:L1 与 L3 的 NVIDIA GPU job 在 `ROCM_ONLY=1` 时跳过;L3 的 xGMI 还接受 +UI/API 加 `RUN_ROCM_XGMI=1`,RDMA 只接受 schedule 加 `NIGHTLY=1`、`nightly-test` label,或 +UI/API 加 `RUN_ROCM_RDMA=1`。 + +## 测试分级标记 + +- 层级与机器用 pytest marker 表达:`ready`、`L4`、`MI300`、`cpu`、`cuda`、`rocm`、`gpu`、 + `cards_{1,2,4}`,登记在 `pytest.ini`;`hardware_test(res=..., num_cards=N)` 会派生对应 + SKU/平台/卡数 mark(`tests/python/helpers/mark.py`)。 +- 新增或改动测试必须带层级和机器标记,`pre-commit` 的 `check-mark` + (`tools/pre_commit/check_test_marks.py`)会拦缺标记的 PR;Rust 侧用 Cargo feature(`cpu`、`ready`)。 +- L3 的 Rust 与 Python 单测和 L1 用同一组 `--features cpu,ready` / `-m "ready and cpu"`,单测覆盖 + 不随层级变大;L3 多出来的是 GPU/ROCm 矩阵、GSM8K 和两个 perf job。 +- GPU job 在 `ci_mirror_hardwares.yml` 里按 preset 取机器:`l4_1`(L1 encode perf)、 + `l4_2`(kv_aware)、`l4_4`(P/D 与 gRPC)、`h100_2`(prefix-KV perf)、`mi300_2`(xGMI)、 + `mi300_rdma`(两节点 RDMA)。job 写 `mirror_hardwares`,由 `scripts/upload_pipeline.py` 展开成 + agents 和 plugins。 + +## 目录内容 + +| 遇到什么 | 查看哪里 | 说明 | +|---|---|---| +| 发版门禁、tag/版本一致性、PyPI 与 Docker 发布顺序、发布产物核对 | [发布规范](release-gates.md) | 硬门禁与质量门槛分栏,含常见失败模式 | diff --git a/knowledge/repos/vllm-router/ci/release-gates.md b/knowledge/repos/vllm-router/ci/release-gates.md new file mode 100644 index 00000000..b1de0150 --- /dev/null +++ b/knowledge/repos/vllm-router/ci/release-gates.md @@ -0,0 +1,144 @@ +--- +title: "vLLM-Router 发布规范" +created: 2026-11-06 +updated: 2026-11-09 +type: guide +tags: [vllm-router, ci] +sources: [.buildkite/release-pipeline.yml, .buildkite/scripts/build-wheel.sh, .buildkite/scripts/publish-release-images.sh, .buildkite/scripts/cleanup-nightly-router-builds.sh, .buildkite/README.md, docker/Dockerfile.router, pyproject.toml, Cargo.toml, py_src/vllm_router/version.py, docs/benchmarks/router_overhead.md, tests/python/e2e/perf/grpc/README.md, tests/python/e2e/perf/l1_encode/README.md, tests/python/e2e/pd_disagg_vllm/test_lm_eval_accuracy.py, .github/ISSUE_TEMPLATE/200-bug-report.yml, "vllm-project/router@ddf78218cffdb6361579d3babd69a90ba6d63aaa", "https://github.com/vllm-project/router/releases/tag/v0.1.17"] +--- + +# vLLM-Router 发布规范 + +发布由 tag 驱动:`.buildkite/release-pipeline.yml`(Buildkite `router-release`)只负责 +tag→产物的机械门禁,测试矩阵、质量门槛和 GitHub Release 正文都要维护者举证或手写。 +两者必须分开报告,不能把 `release` 流水线通过当成整轮质量验证。 + +相关入口:[CI 入口](_index.md)、[仓库入口](../_index.md)、[通用 CI](../../../general/ci/_index.md)、 +[DI 计算说明](../../../general/bug/guides/di-calculation.md)、[benchmark 合同](../../../general/benchmark/guides/benchmark-contract.md)。 + +## 版本号与 tag + +| 项 | 规定 | +|---|---| +| tag 形态 | `vX.Y.Z`(如 `v0.1.17`);流水线用 `build.tag =~ /^v.*/` 触发 | +| 版本唯一来源 | `pyproject.toml` 的 `project.version`;`version-check` 只把 tag 去掉 `v` 后与它比较 | +| 必须同步的文件 | `pyproject.toml`、`Cargo.toml`、`Cargo.lock`、`py_src/vllm_router/version.py`;`v0.1.17` 的 bump commit 同时改这四份,tag 指向该 commit | +| 包名与入口 | PyPI 包 `vllm-router`,模块 `vllm_router`,console script 与 Rust 二进制都叫 `vllm-router` | +| 产物范围 | 仅 Linux:`cp38-abi3` 的 manylinux_2_28 x86_64 与 aarch64 wheel,加 sdist;`requires-python = ">=3.8"`,一个 abi3 wheel 覆盖 3.8+,没有 macOS/Windows wheel | +| tag 类型 | 历史上 annotated(`v0.1.16`、`v0.1.16.1`)和轻量(`v0.1.17`)都出现过;类型不影响触发,但 tag 不能指向 bump 之前的 commit | +| 四段版本 | `v0.1.16.1` 的 `pyproject.toml` 仍是 `0.1.16`,而 `version-check` 在 `v0.1.16` 时就已在 release pipeline 里,所以这个 tag 的普通构建过不了该门禁;它只出现在手动 Docker 通道,PyPI 与 GitHub Release 都没有这一版 | + +### tag、PyPI、镜像、Release 要分别核对 + +`v0.1.11`、`v0.1.13`、`v0.1.14` 只有 tag;`v0.1.16.1` 只有 Docker 镜像;GitHub Release 只有 +`v0.1.16` 与 `v0.1.17`。2026-11-09 的实测状态: + +| 渠道 | 存在的版本 | +|---|---| +| git tag | `v0.1.9` … `v0.1.17`(含 `v0.1.16.1`) | +| PyPI | `0.1.9`、`0.1.10`、`0.1.12`、`0.1.15`、`0.1.16`、`0.1.17` | +| Docker Hub `vllm/vllm-router` | `v0.1.16`、`v0.1.16.1`、`v0.1.17`,加 `latest`、`nightly`(另有 `v0.0.0` 测试 tag) | +| GitHub Release | `v0.1.16`、`v0.1.17` | + +结论:tag 列表不能当发布清单用,验收要分别去 PyPI、Docker Hub 和 Releases 页核对。 + +## 流水线实际执行的门禁(硬) + +| # | 门禁 | 证据 job / 脚本 | 失败后果 | +|---|---|---|---| +| 1 | tag 版本 == `pyproject.toml` 版本 | `version-check`(仅 tag 构建) | 后续 build/publish 全部不执行 | +| 2 | 两架构产物构建成功:x86_64 出二进制 + wheel + sdist,aarch64 出 wheel;在 manylinux_2_28 镜像里 `cargo build --release` + `python -m build` + `auditwheel repair`,Rust 用 nightly 工具链 | `build_wheels_x86_64`、`build_wheels_aarch64` | PyPI 发布阻塞 | +| 3 | 二进制 smoke:`vllm-router --version`、`--help` 在 manylinux 容器内可执行 | `smoke-test-binary-x86_64` | PyPI 发布阻塞 | +| 4 | wheel smoke:两个架构各自 `pip install` 后 `import vllm_router` 并打印 `__version__` | `test-python-wheel-x86_64`、`test-python-wheel-aarch64` | PyPI 发布阻塞 | +| 5 | PyPI 上传用 `twine upload dist/*`(`PYPI_TOKEN`),依赖 2+3+4 全部通过,`soft_fail: false`,只在 tag 构建执行 | `publish-pypi` | 无 PyPI 产物 | +| 6 | Docker 正式版:先填 `X.Y.Z`(required),再依次解除 build 与 publish 两个 block;两个架构分别用 `docker/Dockerfile.router` 构建并推 `vX.Y.Z-{x86_64,aarch64}`,最后合并 manifest | `input-release-version`、两个 block、`publish-release-images.sh release` | 只缺镜像,PyPI 不受影响 | +| 7 | nightly 镜像:`NIGHTLY=1` 才构建 `nightly-{x86_64,aarch64}`,发布 `nightly` 与 `nightly-YYYYMMDD-`,随后清理旧 tag 只保留最近 14 个 | nightly 组、`publish-release-images.sh nightly`、`cleanup-nightly-router-builds.sh` | 只影响 nightly 通道 | + +门禁**不覆盖**的四处,举证时必须自己说明: + +- `release-pipeline.yml` 不跑 L1/L2/L3 测试矩阵(`.buildkite/README.md`:wheels and images only), + 只有上面 3、4 两条 smoke。 +- `vllm_router.__version__` 只被打印,不与 tag 比较;四份版本文件漏改一份,CI 不会报错。 +- wheel 用 nightly Rust 工具链构建,测试流水线固定 `rust:1.95.0`;CI 绿测不等于 wheel 里那份 + 二进制已验证。 +- Docker 通道不校验 tag 与 `pyproject.toml`(`version-check` 只对 tag 构建生效),所以可以只发镜像; + `v0.1.16.1` 就是这么来的。 + +Docker 通道还有两条运维前提:secret `ROUTER_DOCKERHUB_TOKEN` 只在 Docker job 上映射为 +`RELEASE_DOCKERHUB_TOKEN`,需要 Buildkite agent 3.106.0 以上支持 step-level secrets;secret 的 +访问策略限定在 `router-release` 流水线、main 或批准的版本 ref,以及 CPU/ARM release 队列。 + +## 发布前质量门槛(政策,需人工举证) + +发布前的质量门槛按本仓库现有的通道收敛:NVIDIA 与 ROCm 的平台覆盖、精度回退都包含在 L2/L3 +两行里,不另立单项;性能没有统一百分比,按场景口径举证;覆盖率目标在开工会确定。 +类型列中 `Gate` 指不分迭代的硬性门槛,`Guide` 指按当期迭代指南解释并举证。 + +| # | 要求 | 类型 | 说明 | +|---|---|---|---| +| 1 | 目标 commit 的 L2 merge 全绿,最近一轮 L3 nightly 无失败 | Gate | L2 有 xGMI smoke(GSM8K limit 20,基线 0.38 允许 −0.03)与 RDMA `SMOKE_ONLY`;L3 有 P/D 全量 GSM8K(HTTP 与 gRPC)、ROCm xGMI/RDMA 的 read true/false 矩阵、gRPC prefix-KV perf、L1 encode perf。证据给 Buildkite build 链接,L1 只证明 PR 自身,不能替代 | +| 2 | 单元测试覆盖率达到开工会确定的当期目标 | Guide | 目标在迭代开工会定成具体数值和统计范围。Python 覆盖率以 router 的覆盖率看板为准,CI 上传的 `coverage.xml` 是它的数据源;Rust 覆盖率目前没有现成工具,若纳入目标必须提前自建收集方式,见下方说明。没定目标按 N/A 记录 | +| 3 | 性能场景无回退,按各场景自己的口径举证 | Guide | 不设统一百分比,见下面“性能与覆盖率怎么举证” | +| 4 | 需求完成率 > 85% | Gate | 按当期需求清单核对,本仓库无自动化 | +| 5 | 剩余 DI < 30 | Gate | 按 [DI 计算说明](../../../general/bug/guides/di-calculation.md) 计算:不按天数累加,达到 SLO 升一级后取新级别的基础 DI;定级口径见下方说明 | +| 6 | 无未关闭 critical issue,剩余 bug 均有 assignee | Gate | critical 由同一套 issue 分级口径判定;本仓库无自动化 | + +### 性能与覆盖率怎么举证 + +- **性能不用统一阈值。** prefix-KV 用例按 `tests/python/e2e/perf/grpc/README.md` 的验收口径 + 分场景比较 rust gRPC(G)、rust HTTP(R)、python HTTP(P)的 `ttft_ms.avg` 与 `e2e_ms.avg`: + hit 0% 时 G 在 ttft 和 e2e 上不得回退于 R 与 P;hit 99% 时 G 在 ttft 和 e2e 上不得回退于 R, + e2e 不得回退于 P,且 G 的 ttft 要比 P 好 20% 以上(`ttft_G <= 0.8 * ttft_P`)。CI 的 L3 job + 只跑 `rust_grpc` 与 `python_http` 的 `c16-r32`、`hit99-c4`、`hit99-c64`,`rust_http` 需要本地补齐。 + L1 encode 用例按 `tests/python/e2e/perf/l1_encode/README.md` 比较 `wave.summary.encode_ms.p50` + 与 `encode_reuse.p50` 在 L1 on/off 之间的差异。CPU overhead 用同机 `cargo bench` 的 baseline + 对比。pytest 只校验每个 wave 的统计完整,跨后端验收要人工判读 `results/` 里的 `wave.summary`, + 不能声称 CI 已经断言 SLO。 +- **覆盖率目标来自开工会,数值以看板为准。** 当期目标要写进迭代记录(数值 + 统计范围), + 发布时直接引用 router 覆盖率看板的数值,不再自己解析 `coverage.xml`。看板目前只覆盖 Python + 单测(`-m "ready and cpu"`);Rust 覆盖率还没有现成框架或工具,如果当期目标包含 Rust,必须 + 在开工会前确定自建收集方式(工具、命令、上报口径)并写进记录,否则本期只按 Python 覆盖率 + 举证。目标缺失时该项只能记 N/A 并注明原因。 +- **DI 需要先有分级。** [DI 计算说明](../../../general/bug/guides/di-calculation.md) 要求每条未关闭 + issue 先定 critical / high / medium / low,并按“达到 SLO 升一级”计算,不再按天数累加。 + 本仓库 bug 模板只打 `bug` label,没有 severity 字段,因此发布前要先确认 router 与 agent-infer + 的 issue 分级策略并对齐到同一口径(用 label 或发布记录逐条定级)。口径未确认时 DI 记 N/A, + 不能拿 issue 数量代替。 + +## 发布步骤 + +1. 确认目标 commit 满足上面 1–6,把证据链接记进验收记录。 +2. 提一次版本 bump,四份文件同改,走正常 PR 合并;不要只改 `pyproject.toml`。 +3. 在 bump commit 上打 `vX.Y.Z` tag 并推送。 +4. 盯 `router-release`:`version-check` → 两架构 build → smoke → `publish-pypi`。 +5. 需要镜像时手动走 Docker 通道:填 `X.Y.Z`,依次解除 build 与 publish 两个 block,产出 + `vllm/vllm-router:vX.Y.Z`、`:latest` 与两个 per-arch tag。 +6. 在 GitHub Releases 补发布说明:现有 `v0.1.16`、`v0.1.17` 的结构是 Highlights / Key Improvements / + Note / Artifacts / Full Changelog / New Contributors,Artifacts 段列出 PyPI 三个文件的 SHA-256、 + 镜像多架构大小和单架构 tag。流水线里没有 `gh release` 或等价步骤,这段必须手写。 +7. `NIGHTLY=1` 只发 nightly:`vllm/vllm-router:nightly` 与 `nightly-YYYYMMDD-`,不碰 PyPI, + 不能当正式版本;nightly 构建只保留最近 14 个。 +8. 发布后把 tag、PyPI、Docker Hub、GitHub Release 四处状态并排核对一遍,缺哪一处就写明原因。 + +## 常见失败模式 + +- tag 与 `pyproject.toml` 不一致:`version-check` 直接失败,这是唯一能拦住后续所有产物的门禁。 +- 只改 `pyproject.toml`:wheel 装得上,但 `vllm_router.__version__` 还是旧值;smoke 只打印不比较。 +- 把 README 的 “CI/CD Pipeline” 当流程依据:该段仍写 `cibuildwheel` 和“`pyproject` 版本变化即发布”, + 与实际的 tag 驱动、四文件同步不一致;Dockerfile 路径 `/docker/Dockerfile.router` 倒是对的。 + 流程以 `.buildkite/release-pipeline.yml` 为准。 +- 用 tag 列表判断发布状态:`v0.1.11`、`v0.1.13`、`v0.1.14` 没有任何产物,`v0.1.16.1` 只有镜像。 +- 用 nightly 的绿测替代发版证据:nightly 覆盖面最广,但它不阻塞 PR、也不校验 tag 与版本文件, + 过期一轮的 nightly 结果不能当本次 tag 的门禁证据。 +- 只验证 x86_64:PyPI 与镜像都要求两个架构各自构建并 smoke。 +- 声明 macOS/Windows wheel:构建只在 manylinux_2_28 上做,一个 abi3 wheel 覆盖多个 Python 版本, + 不是跨平台承诺。 + +## 验收记录 + +发布说明或 checklist 逐项给出,缺一项按未通过处理: + +- 是否通过(Pass / Fail / N/A),硬门禁与政策门禁分开列。 +- 证据链接(Buildkite build、覆盖率看板快照与开工会目标、各场景性能 `wave.summary`、DI 定级记录、issue 列表)。 +- 发布产物核对表(tag / PyPI 版本 / Docker tag / GitHub Release 是否都存在)。 +- Guide 项写明当期 Guide 版本或链接;Docker 与 GitHub Release 是否发布单独列出。