Prhub

#25981 [CI] Improve bot-cherry-pick: accept PR number, require merged, explicit title

原始 PR 作者 Kangyan-Zhou 合并时间 2026-05-21 18:32 文件变更 1 提交数 1 评论 1 代码增减 +158 / -71

执行摘要

改进 cherry-pick 工作流:支持 PR 编号、要求已合并、显式标题

原有的 bot-cherry-pick 工作流只接受 commit_sha,且无法有效防止 cherry-pick 未合并的 commit,导致 cherry-pick 的语义不清晰。本次改进旨在:1)支持基于 PR 编号的 cherry-pick(推荐方式),自动获取合并提交和元信息;2)拒绝 cherry-pick 未合并的变更;3)为 cherry-pick PR 生成显式标题,包含原 PR 标题和编号,提高可追溯性。

值得精读,特别是需要维护发布分支的团队。该 PR 展示了如何结合 GitHub CLI 和 API 增强 CI 工作流的健壮性。设计决策如输入互斥校验、状态严格检查、显式 PR 标题等均可作为 CI 工作流编写的参考。breaking change 部分需关注。

讨论亮点

该 PR 的 review 环节无实质性讨论(仅有一条 Gemini 自动生成的无法 review 的提示)。因此未出现需要记录的设计交锋。

实现拆解

  1. 添加 pr_number 输入:与 commit_sha 互斥,在 validate 步骤增加校验:必须提供恰好一个,否则报错;PR 编号必须为正整数。
  2. 重写 Resolve PR / commit 步骤:当提供 pr_number 时,使用 gh pr view 获取 JSON 并检查 merged 字段,拒绝未合并的 PR;提取合并 commit SHA。当提供 commit_sha 时,首先验证 commit 存在,然后通过 gh api 查找关联的合并 PR;若未找到,要求 commit 从默认分支可达。
  3. 移除 create_pr 输入:工作流现在始终创建 PR。
  4. 显式 PR 标题:格式为 [Cherry-pick to release/vX.Y.Z] <原 PR 标题> (#<pr_number>);无关联 PR 时使用短 SHA。
  5. 自动检测合并提交:当 parent count > 1 时传递 -m 1git cherry-pick
  6. Shell 加固:在 resolve 步骤使用 set -eo pipefail; shopt -s inherit_errexit,不再抑制 gh 调用的 stderr,对每个关键变量赋值进行显式守卫。
文件 模块 状态 重要度
.github/workflows/bot-cherry-pick.yml CI 工作流 modified 5.83

关键源码片段

.github/workflows/bot-cherry-pick.yml infrastructure

唯一变更文件,完全重写了 cherry-pick 工作流的逻辑,包括输入验证、PR 解析、标题生成等核心功能。

set -eo pipefail
shopt -s inherit_errexit
​
SOURCE_PR=""
PR_URL=""if [[ -n "$PR_NUMBER" ]]; then
    # 使用 gh pr view 获取 PR 的合并状态与合并提交 SHA
    if ! PR_JSON=$(gh pr view "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --json state,merged,mergeCommit,title,number,url); then
        echo "::error::Failed to fetch PR #$PR_NUMBER"
        exit 1
    fi
    MERGED=$(jq -r '.merged' <<<"$PR_JSON")
    STATE=$(jq -r '.state' <<<"$PR_JSON")
    # 拒绝未合并的 PR
    if [[ "$MERGED" != "true" ]]; then
        echo "::error::PR #$PR_NUMBER is not merged (state=$STATE). Only merged PRs can be cherry-picked."
        exit 1
    fi
    FULL_SHA=$(jq -r '.mergeCommit.oid // empty' <<<"$PR_JSON")
    if [[ -z "$FULL_SHA" ]]; then
        echo "::error::PR #$PR_NUMBER is merged but has no merge commit."
        exit 1
    fi
    PR_TITLE=$(jq -r '.title // empty' <<<"$PR_JSON")
    PR_URL=$(jq -r '.url // empty' <<<"$PR_JSON")
    SOURCE_PR="#$PR_NUMBER"
else
    # commit_sha 路径:验证 commit 存在,并通过 API 查找关联 PR
    # (省略详细实现,核心是确保 commit 来自合并的 PR 或已到达默认分支)
fi

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

主要风险:

1) breaking changecreate_pr=false 的调用者无法继续使用,因为该输入已被移除;
2) 输入变更commit_sharequired: true 变为 required: false,但互斥校验保证仍然需要至少一个,旧的仅传递 commit_sha 的调用不受影响;
3) Shell strict mode:可能暴露此前被容忍的错误,但整体风险较低。

影响范围限于调用该工作流的 repos/用户。改进后 cherry-pick 流程更安全可靠,PR 标题可追溯性增强。所有 cherry-pick 都会创建 PR,增加了审查机会。breaking change 需要通知相关用户更新调用方式。

breaking change shell strict mode

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论