Prhub

#2538 release: miles version release workflow

原始 PR 作者 yueming-yuan 合并时间 2026-08-15 10:57 文件变更 26 提交数 17 评论 3 代码增减 +1051 / -86

执行摘要

新增 CI 门控的版本发布工作流,冻结依赖三元组并发布官方镜像。

PR body 明确说明:官方发布必须保留通过 CI 的精确 Miles、SGLang、Megatron-LM 源码组合,而此前 CI 无法针对任意 release ref 运行全量发布范围,也无法在分支切割、hotfix、打 tag、镜像发布之间携带冻结的三元组,维护者缺少一条可复现、受支持的发布路径。

值得精读。本 PR 展示了多个高价值设计决策:用 commit status 做跨工作流门控、cadence 覆盖隔离 release 与 nightly 基线、retag 规避镜像清理周期、cherry-pick 与镜像层一致性约束。发布维护者应重点阅读 docs/ci/04-release.mdrelease-tag.yml 的 force 逃生门;普通贡献者需要了解 bot-cherry-pick.yml 的限制。

讨论亮点

三条核心 review 讨论全部围绕发布安全性与可复现性:

  1. CodeQL bot 指出 release-docker.yml 未显式限制 GITHUB_TOKEN 权限,最终补上 permissions: contents: read
  2. guapisolo 的 P1 指出 release-tag.yml 用 run 创建时间判断 CI 新旧会误拒首次 cut run(run 创建早于 lockfile commit),最终改为 release-branch-cut.yml 最后通过 finalizer 在 tested SHA 上打 release-ci commit status,release-tag 改为校验该 status。
  3. guapisolo 的 P1 指出 workflow_call 继承 caller 事件导致 docker-paths 不识别 Docker 变更,CI 会用旧冻结镜像而发布构建新镜像,最终通过 bot-cherry-pick.yml 拒绝所有触碰镜像层文件的 cherry-pick 来闭环。

实现拆解

1. CI 策略层:新增 release cadence 与 cadence 覆盖

  • tests/ci/ci_policy.py:新增 RELEASE_CADENCE 并纳入 CI_CADENCESresolve_policy 中 release 与 weekly 一样全范围、admit_nightly_tests=Truebypass_fastfail=True,但 write_baseline 保持 False(冻结 SHA 的 release 运行写基线会污染 nightly 对比);resolve_workflow_inputs 新增 cadence_override 参数并优先于触发器推断,避免被调用工作流继承调用方 event_name 时静默降级为 regular 范围。
  • .github/workflows/pr-test.yml:新增 workflow_call 输入 refcadence(默认 release)、image_tagresolve-ci-policy 任务故意不 checkout inputs.ref(防 CodeQL 缓存投毒);concurrency group 改为字面量前缀 pr-test- 并加入 inputs.ref,解决被调用时 github.workflow 解析为调用方名称导致 CUDA/ROCm 互相取消的问题;各 stage 透传 ref
  • pr-test-rocm.yml 与可复用 _run-ci*.yml 同步透传 ref,保证 release 分支 smoke 也测试正确 commit。
文件 模块 状态 重要度
.github/workflows/release-branch-cut.yml 发布编排 added 6.28
.github/workflows/release-tag.yml 标签门控 added 6.13
.github/workflows/release-docker.yml 镜像发布 added 5.88
tests/ci/ci_policy.py CI 策略 modified 5.87
.github/workflows/bot-cherry-pick.yml 热修挑选 added 5.8
.github/scripts/release/write_release_lock.py 依赖冻结 added 5.43
.github/workflows/pr-test.yml CI 编排 modified 5.35
docs/ci/04-release.md 发布文档 added 4.38
tests/ci/test/test_run_suite.py 策略测试 modified 4.44
.github/scripts/release/bump_miles_version.py 版本脚本 added 4.99
.github/workflows/bot-bump-miles-version.yml 版本提交 added 4.71

关键符号

resolve_policy resolve_workflow_inputs strip_run_ci_prefix write_release_lock.main bump_miles_version.main

关键源码片段

tests/ci/ci_policy.py core-logic

CI 策略核心:新增 release cadence 与 cadence_override,保证 release 运行不写性能基线。

# release 与 weekly 同范围,但绝不写性能基线
RELEASE_CADENCE = "release"
CI_CADENCES = frozenset({REGULAR_CADENCE, NIGHTLY_CADENCE, WEEKLY_CADENCE, RELEASE_CADENCE})
​
​
def resolve_policy(cadence: str, raw_labels: set[str]) -> RunPolicy:
    """根据显式 cadence 与 raw labels 解析选择与 fast-fail 行为。"""
    if cadence not in CI_CADENCES:
        raise ValueError(f"Unknown CI cadence {cadence!r}")
    if "nightly" in raw_labels and cadence != NIGHTLY_CADENCE:
        raise ValueError("The nightly workflow label requires cadence='nightly'")
​
    requested = strip_run_ci_prefix(raw_labels) & set(KNOWN_LABELS)
    # weekly 与 release 都包含全部注册标签;release 仅在不写基线这点上不同
    if "run-ci-all" in raw_labels or cadence in {WEEKLY_CADENCE, RELEASE_CADENCE}:
        scope = set(KNOWN_LABELS)
    elif cadence == NIGHTLY_CADENCE:
        scope = set(KNOWN_LABELS) - {"long", "ft-long"}
    elif "run-ci-image" in raw_labels:
        scope = set(KNOWN_LABELS) - {"long", "ft-short", "ft-long"}
    else:
        scope = set()
    full_cadences = {NIGHTLY_CADENCE, WEEKLY_CADENCE, RELEASE_CADENCE}
    return RunPolicy(
        cadence=cadence,
        include_labels=frozenset(scope | requested),
        admit_nightly_tests=cadence in full_cadences,
        bypass_fastfail=cadence in full_cadences or "bypass-fastfail" in raw_labels,
        # 冻结 SHA 的 release 运行写基线会污染 nightly 对比
        write_baseline=cadence in {NIGHTLY_CADENCE, WEEKLY_CADENCE},
    )
​
​
def resolve_workflow_inputs(
    event_name: str, schedule: str, pr_labels_json: str, cadence_override: str = ""
) -> WorkflowPolicy:
    """适配 GitHub 触发器事实为稳定策略输出。    `cadence_override` 显式携带 workflow_call 的 cadence(如 release 分支切割请求
    全量 release 运行),必须优先于触发器推断:被调用的工作流继承调用方的
    event_name,若按触发器推断会把 release 运行静默降级为 regular 范围。
    """
    if cadence_override:
        cadence, raw_labels = cadence_override, ()
    elif event_name == "pull_request":
        raw_labels = _canonical_pr_labels(pr_labels_json)
        cadence = NIGHTLY_CADENCE if "nightly" in raw_labels else REGULAR_CADENCE
    elif event_name == "schedule":
        cadence, raw_labels = SCHEDULE_POLICIES[schedule]
    elif event_name == "workflow_dispatch":
        cadence, raw_labels = REGULAR_CADENCE, ()
    else:
        raise ValueError(f"Unsupported PR Test trigger: {event_name}")
    run_policy = resolve_policy(cadence, set(raw_labels))
    return WorkflowPolicy(
        cadence=cadence,
        raw_labels=raw_labels,
        bypass_fastfail=run_policy.bypass_fastfail,
    )

评论区精华

release-docker.yml 缺少显式 permissions 安全

CodeQL bot 指出 workflow 未限制 GITHUB_TOKEN 权限,建议添加 permissions: contents: read。

结论:已在工作流顶部补充显式 permissions: contents: read,guapisolo 在最终审批中再次提醒 'need handle permission issue'。 · 已解决

release-tag 门控不能用 run 创建时间判断 正确性

guapisolo 指出首次 release-branch-cut run 的 createdAt 早于其 lockfile commit 时间,按 run 时间校验会拒绝第一个成功 cut run。建议记录并比较 post-cut SHA。

结论:改为 release-branch-cut 的 finalizer 在 tested SHA 上打 release-ci commit status,release-tag 检查该 status,彻底消除时间推断问题。 · 已解决

Docker 热修复后 CI 镜像与发布镜像不一致 正确性

guapisolo 指出 workflow_call 继承 caller 的 workflow_dispatch 事件,docker-paths 无法识别 release 分支的 Docker 变更,CI 会测试旧冻结镜像而发布构建新镜像。建议构建并测试 release ref 的镜像,或显式拒绝 Docker 相关 cherry-pick。

结论:在 bot-cherry-pick.yml 中拒绝所有触碰镜像层文件的提交,requirements.txt 例外;镜像层修复必须走新版本。 · 已解决

最终审批中的权限处理提醒 安全

guapisolo APPROVED 时附加评论 'need handle permission issue',指向 CodeQL 提出的权限收紧要求。

结论:release-docker.yml 补充 permissions: contents: read 后关闭。 · 已解决

风险与影响

  1. release-tag.yml 的门控完全依赖 release-ci commit status:若 finalizer 未打上或 status 被覆盖,会阻塞或误放行 tag;force=true 是设计好的审计逃生门,但存在滥用风险。
  2. release-docker.yml(PR body 已指出)手工 workflow_dispatchversionref 不交叉校验,可能构建出与 tag 不一致的镜像。
  3. release-branch-cut.yml 通过 retag 规避 docker-build 的 dev 标签清理,但依赖 Docker Hub API 与 buildx 的可用性;若 dev 镜像 tag 规则变化,release 镜像可能找不到。
  4. bot-cherry-pick.yml 只拒绝 docker/ 下的镜像层文件,requirements.txt 等运行时依赖变更仍可 cherry-pick,未来若构建引入新的镜像层来源需要同步更新黑名单。
  5. concurrency 字面量前缀依赖所有调用方保持命名一致,新增可复用工作流时容易踩坑。

对维护者:发布路径从手工操作变为可审计、可重复的 CI 流程,分支切割、CI 验证、打 tag、镜像发布之间有明确门控与证据链。对开发者:hotfix 提交策略受限(镜像层改动只能走新版本),cherry-pick 流程被机器人接管。对 CI 资源:release cadence 复用 weekly 全量范围,每次发布触发完整 CUDA/ROCm 套件,资源开销大但仅在发布时发生。对运行时与训练代码零影响。

门控依赖 commit status 镜像层 hotfix 受限 手工 dispatch 版本 /ref 不校验 concurrency 字面量前缀易失效 release cadence 资源消耗大

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论