# PR #25981 完整报告

- 仓库：`sgl-project/sglang`
- 标题：[CI] Improve bot-cherry-pick: accept PR number, require merged, explicit title
- 合并时间：2026-05-21 18:32
- 原文链接：http://prhub.com.cn/sgl-project/sglang/pull/25981

---

# 执行摘要

- 一句话：改进 cherry-pick 工作流：支持 PR 编号、要求已合并、显式标题
- 推荐动作：值得精读，特别是需要维护发布分支的团队。该 PR 展示了如何结合 GitHub CLI 和 API 增强 CI 工作流的健壮性。设计决策如输入互斥校验、状态严格检查、显式 PR 标题等均可作为 CI 工作流编写的参考。breaking change 部分需关注。

# 功能与动机

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

# 实现拆解

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 1` 给 `git cherry-pick`。
6. **Shell 加固**：在 `resolve` 步骤使用 `set -eo pipefail; shopt -s inherit_errexit`，不再抑制 `gh` 调用的 stderr，对每个关键变量赋值进行显式守卫。

关键文件：
- `.github/workflows/bot-cherry-pick.yml`（模块 CI 工作流；类别 infra；类型 infrastructure）: 唯一变更文件，完全重写了 cherry-pick 工作流的逻辑，包括输入验证、PR 解析、标题生成等核心功能。

关键符号：未识别

## 关键源码片段

### `.github/workflows/bot-cherry-pick.yml`

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

```bash
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

```

# 评论区精华

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

- 暂无高价值评论线程

# 风险与影响

- 风险：主要风险：
 1) **breaking change**：`create_pr=false` 的调用者无法继续使用，因为该输入已被移除；
 2) **输入变更**：`commit_sha` 从 `required: true` 变为 `required: false`，但互斥校验保证仍然需要至少一个，旧的仅传递 `commit_sha` 的调用不受影响；
 3) **Shell strict mode**：可能暴露此前被容忍的错误，但整体风险较低。
 - 影响：影响范围限于调用该工作流的 repos/ 用户。改进后 cherry-pick 流程更安全可靠，PR 标题可追溯性增强。所有 cherry-pick 都会创建 PR，增加了审查机会。breaking change 需要通知相关用户更新调用方式。
 - 风险标记：breaking change, shell strict mode

# 关联脉络

- 暂无明显关联 PR