Prhub

#56356 [ROCm][CI] Accept `base-v2-preview` images during content hash lookup for ROCm base images

原始 PR 作者 micah-wil 合并时间 2026-09-11 15:30 文件变更 1 提交数 1 评论 4 代码增减 +7 / -3

执行摘要

ROCm 基础镜像内容查找接受 preview 标签并回填正式标签

PR body 明确指出问题:"Currently, post-merge CI runs do not use base-v2-preview during content hash lookup in refresh rocm base. As a result, the base image is rebuilt until some previous post-merge commit finishes rebuilding it and ultimately posts the final base-v2-<hash> image." 也就是说,PR 流水线已经按内容哈希推送了 preview 镜像,但 post-merge 侧只认 trusted 命名空间,导致同一份基础镜像被反复重建,拖慢 post-merge 验证反馈。作者同时给出了正确性前提:"The hashes are content-addressed and built in CI on PR's that touch Dockerfile.rocm_base, so if a hash hits, it should mean that the images are identical."

值得精读,但优先级限于 ROCm CI 维护者。建议重点看两点设计决策:一是三层内容命名空间(trusted / preview / stable)的候选查找顺序与回填条件,这实际上定义了一套镜像晋升协议;二是「内容哈希即等价」的信任假设,需要核验 base_hash 与 metadata_version 的计算输入是否覆盖 refresh-base-image.sh、Dockerfile.rocm_base 及全部依赖与构建参数。若哈希覆盖不完整,建议在脚本或文档中显式记录哈希输入清单,并补一条能够在 CI 中构造「preview 命中、trusted 缺失」时序的定向验证;对普通业务开发者,本 PR 只需知道 ROCm post-merge 构建会更快即可。

讨论亮点

本 PR 几乎没有实质性技术讨论:claude[bot] 的自动 review 因「This pull request is from a fork — automated review is disabled」被跳过,仓库维护者 AndreasKaratzas 直接以 APPROVED 通过,未留下任何 review comment 或行级讨论。评论区只有 4 条流水线触发与回执:/amd-ci run → AMD CI #12858,/ci run → CI #88218,均针对 commit 8af29ddf632b。也就是说,关于「preview→trusted 内容晋升是否安全」「回填条件的布尔改写是否有边界遗漏」这些问题,都在无对抗性审查的情况下被合并。

实现拆解

  1. 入口与变量准备:在 .buildkite/scripts/rocm/refresh-base-image.sh 的 build_base_image() 中新增 local preview_content_tag="" 局部变量,并在 trusted_content_tag / scoped_content_tag 计算完成后执行 preview_content_tag="${scoped_content_tag}",把 preview 命名空间的内容标签显式暴露为一个可引用的变量,避免后续逻辑直接复用含义模糊的 scoped_content_tag。

  2. 扩展内容哈希查找的候选集合:在 trusted_content_tag 与 scoped_content_tag 相等的分支里,调用 find_matching_base_content_ref 时把候选引用从原来的「trusted 内容标签 + stable 别名」扩展为「trusted 内容标签 + preview 内容标签 + stable 别名」。这样 post-merge 构建即使尚未产出 base-v2-<hash>,也能命中 PR 阶段推送到 preview 命名空间的同内容镜像,直接跳过重建。

  3. 放宽回填(retag)条件:复用分支的判断由 immutable_ref 去摘要 == stable_tag && writable_content_tag != stable_tag 改写为 immutable_ref 去摘要 != writable_content_tag &&(== stable_tag || == preview_content_tag)。语义上从「只允许从稳定别名回填」升级为「命中 preview 内容标签也允许回填」,并且用 != writable_content_tag 把「目标标签已经存在」的短路条件提到最前,命中后统一执行 docker buildx imagetools create --prefer-index=false -t "${writable_content_tag}" "${immutable_ref}" 完成标签晋升。${immutable_ref%@*} 用于剥离 @sha256:... 摘要后缀,只保留 repo:tag 做字符串比较。

  4. 测试与配置配套:本 PR 未新增任何测试或配置项,全部验证依赖 Buildkite 流水线实跑。评论区的 /amd-ci run(AMD CI #12858)与 /ci run(CI #88218)是针对同一 commit 8af29ddf632b 的两条流水线触发,属于人工冒烟验证而非针对 preview 命中时序的定向验证。

  5. 未改动部分:else 分支下 find_matching_base_content_ref 的候选列表未加入 preview 标签,说明本次只针对 trusted/main 路径放宽;该函数需要能接受不定数量的位置参数(新增候选是插入在中间位置而非追加),维护时需留意签名兼容性。

文件 模块 状态 重要度
.buildkite/scripts/rocm/refresh-base-image.sh 基础镜像 modified 3.73

关键符号

build_base_image find_matching_base_content_ref trusted_base_content_ref scoped_base_content_ref is_trusted_main_build

关键源码片段

.buildkite/scripts/rocm/refresh-base-image.sh core-logic

唯一改动文件:在 build_base_image() 中新增 preview_content_tag 变量,扩展 find_matching_base_content_ref 的候选引用列表,并放宽回填条件,使 post-merge 可复用 PR 阶段推送的 base-v2-preview-<hash> 镜像。

# .buildkite/scripts/rocm/refresh-base-image.sh(按改动重组的片段,省略号处为未改动代码)
build_base_image() {
  local stable_tag="${BASE_REPO}:base" # 人类可读的稳定别名
  local trusted_content_tag="" # <repo>:base-v2-<hash>,main 侧可信内容标签
  local scoped_content_tag="" # 当前构建作用域(preview)下的内容标签
  # 本 PR 新增:显式声明 preview 命名空间变量,让 post-merge 阶段也能把
  # base-v2-preview-<hash> 当作候选复用来源
  local preview_content_tag=""
  local writable_content_tag="" # 本次构建允许写入的目标标签
  ...
​
  trusted_content_tag=$(trusted_base_content_ref "${base_hash}" "${metadata_version}")
  scoped_content_tag=$(scoped_base_content_ref "${base_hash}" "${metadata_version}")
  # preview 与 scoped 指向同一份 exact-content 命名空间:
  # 多个堆叠 PR 只要内容哈希相同,就能复用同一镜像
  preview_content_tag="${scoped_content_tag}"
​
  # Preview 写入共享同一 exact-content 命名空间,堆叠 PR 之间可复用相同镜像;
  # 它们允许导入 trusted ref,但永远不会覆盖 trusted ref
  if is_trusted_main_build; then
    ...
  fi
​
  # 关键改动 1:在 trusted 内容标签与 stable 别名之间插入 preview 内容标签,
  # 这样 post-merge 构建即使还没产出 base-v2-<hash>,也能命中 PR 阶段已推送到
  # preview 命名空间的同内容镜像,从而跳过重复构建
  if [[ "${trusted_content_tag}" == "${scoped_content_tag}" ]]; then
    immutable_ref=$(find_matching_base_content_ref \
      "${base_hash}" "${metadata_version}" \
      "${trusted_content_tag}" "${preview_content_tag}" \
      "${stable_tag}") || reuse_status=$?
  else
    ... # 其它候选查找路径本 PR 未改动
  fi
​
  if [[ ${reuse_status} -eq 0 && -n "${immutable_ref}" ]]; then
    echo "Reusing ROCm base image with matching content: ${immutable_ref}"
    # 关键改动 2:放宽回填(retag)条件。
    # ${immutable_ref%@*} 去掉 @sha256:... 摘要后缀,只保留 repo:tag 用于比较;
    # 旧逻辑只在命中 stable 别名时回填,新逻辑额外接受 preview 内容标签,
    # 命中后统一 retag 成 writable_content_tag(main 上即 base-v2-<hash>)
    if [[ "${immutable_ref%@*}" != "${writable_content_tag}" \
      && ( "${immutable_ref%@*}" == "${stable_tag}" \
        || "${immutable_ref%@*}" == "${preview_content_tag}" ) ]]; then
      echo "Backfilling ROCm base content tag: ${writable_content_tag}"
      docker buildx imagetools create --prefer-index=false \
        -t "${writable_content_tag}" "${immutable_ref}"
    fi
  fi
}

评论区精华

fork PR 导致自动化 review 被跳过 other

claude[bot] 在 PR 上留言:"This pull request is from a fork — automated review is disabled. A repository maintainer can comment `@claude review` to run a one-time review." 最终没有任何维护者触发一次性 review。

结论:自动化审查缺位,改动由 AndreasKaratzas 人工 APPROVED 通过,未提出修改意见或行级讨论。 · 已解决

验证方式仅为双流水线冒烟 测试

评论区只有两条人工 CI 触发:`/amd-ci run` 与 `/ci run`,分别对应 Buildkite AMD CI #12858 与 CI #88218,二者都跑在同一个 commit `8af29ddf632b` 上。

结论:缺少针对「preview 已存在、trusted 尚未产出」这一目标时序的定向验证说明;由于改动本身是 CI 脚本,最终依赖真实 post-merge 流水线暴露问题。 · 未解决

preview 镜像晋升的信任边界 安全

脚本注释声明 preview 命名空间「可能导入 trusted ref,但永不覆盖 trusted ref」,而新逻辑允许把命中 preview_content_tag 的镜像 retag 成 writable_content_tag。作者在 PR body 中以待复用镜像由内容哈希寻址为由说明其等价性。

结论:未在 review 中被讨论即合并;该信任假设的成立完全依赖哈希输入覆盖完整,属于需要事后复核的点。 · 未解决

风险与影响

  1. 内容哈希等价性假设:整个改动成立的前提是「同一 hash ⇒ 镜像逐字节等价」。这取决于 base_hash 与 metadata_version 的输入是否完整覆盖 Dockerfile.rocm_base、依赖版本、构建参数以及 refresh-base-image.sh 自身;如果某个构建输入未参与哈希计算,post-merge 就可能复用一份与预期不符的 preview 镜像,而且这种错误是静默的——CI 不会报错,只会用错基础镜像继续跑。

  2. 信任边界被放宽:回填条件新增 immutable_ref 去摘要 == preview_content_tag,而脚本注释明确写着 preview 命名空间是「多个堆叠 PR 共享的 exact-content 命名空间,可以导入 trusted ref 但永不覆盖 trusted ref」。改动后,来自 PR 侧命名空间的镜像会被 retag 成 main 侧的 writable_content_tag,相当于把非可信来源的产物晋升为可信标签。内容哈希提供了完整性约束,但一旦哈希函数漏项(见上一点),这条路径就会变成污染 main 基础镜像的通道。

  3. 布尔条件改写:== stable_tag && != writable_content_tag → != writable_content_tag &&(== stable_tag || == preview_content_tag)。旧逻辑中 writable_content_tag != stable_tag 与 immutable_ref == stable_tag 互为约束,新逻辑把「已经是目标标签」作为最外层短路条件,需要确认在 writable_content_tag == preview_content_tag 等边界组合下不会出现走空的回填或多余 retag。

  4. 无测试、无定向验证:纯 shell 脚本没有单元测试,两条 CI 触发也只是回归冒烟。真正要验证的时序——「preview 已存在、trusted 尚未产出」——是否在本次 CI 中被覆盖,PR 中没有说明;这条路径一旦出错,会在下一次触发 refresh rocm base 时才暴露。

  5. 影响面:出错时波及全部 ROCm post-merge 构建,属 CI 可用性风险而非生产推理风险。

对最终用户与推理服务无直接影响,改动只在 Buildkite CI 脚本内。对 ROCm 开发者与 CI 团队的影响有三层:一是 post-merge 阶段可复用 PR 阶段已推送的同内容镜像,减少重复构建的基础镜像次数,缩短合并后验证反馈时间并节省构建机资源;二是改变了 ROCm 基础镜像的复用协议,trusted / scoped(preview)/ stable 三层命名空间的语义与晋升规则变得更隐式,后续维护 refresh-base-image.sh 的人需要先理解这层模型;三是影响范围虽然集中在单个脚本,但它是所有 ROCm 构建的公共入口,误复用的后果会被所有 ROCm 流水线继承。

内容哈希等价性假设 preview→trusted 信任边界放宽 缺少测试覆盖 回填布尔条件改写 影响全部 ROCm CI

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论