☰
Cloudpods PR 合并辅助脚本指南:approve.sh、approve_all.sh 与 lgtm.sh 的完整解析
2026/10/14 18:00:03 网站建设 项目流程
  • 后端
  • 云原生
  • 运维
  • 虚拟化
  • 人工智能
  • AI 应用

【免费下载链接】cloudpods

开源、云原生的多云管理及混合云融合平台

项目地址:https://gitcode.com/yunionio/cloudpods
点击查看免费下载

Cloudpods 仓库的 scripts/README.md 介绍了一组辅助 GitHub CI 机器人工作的脚本,用于在人工 code review 完成之后,安全、可控地给 Pull Request(PR)打标签并完成合并。本文以该文档为骨架,结合 scripts/approve.sh、scripts/approve_all.sh、scripts/lgtm.sh 及同目录下的配套脚本源码,逐一解析其检查项、标签协同机制与批量合并流程,帮助维护者理解这套 PR 合并工具链的工作原理与正确使用方式。

辅助脚本一览

围绕"给 PR 打标签 + 合并"这一目标,文档主体涉及三个脚本:

脚本作用用法
approve.sh完成 4 项前置检查后,对单个 PR 打/lgtm、/approve标签以触发合并./scripts/approve.sh <PRN> [check_reviewers]
approve_all.sh批量合并"master 主 PR + 各分支 cherry pick PR"这一整组 PR./scripts/approve_all.sh <PRN>
lgtm.sh给一个 PR 打上lgtm标签./scripts/lgtm.sh <PRN>

此外,scripts/label.sh 是被lgtm.sh和approve.sh复用的底层"打标签"原语,scripts/advchecks.py 负责 reviewer 审批核对,scripts/cherry_pick_pull.sh 则负责生成被approve_all.sh识别的 cherry pick PR。这些脚本都依赖hubCLI 与python,通过 GitHub REST API 与仓库交互。

approve.sh:合并前的四项前置检查

文档定义的检查项

approve.sh 是整套工具链的核心。文档明确列出了执行合并前的 4 项检查:

  1. 该 PR 的状态为open;
  2. 该 PR 的mergeable状态为true(如果有冲突,则mergeable=false);
  3. 该 PR 的所有 CI 检查都通过;
  4. 如果命令行第二个参数check_reviewers为非空字符串,则还会检查是否所有 requested reviewers 都/lgtm了这个 PR。

同时文档特别强调:执行脚本之前,请确认已经人肉 review 过代码。脚本只是为了方便合并、并确保合并前没有忽略检查,并不是为了替代人工 code review。

检查流程的源码实现

从 approve.sh 的函数实现看,四项检查对应如下调用链(均基于hub api访问 GitHub API):

检查一:PR 状态。pr_state()请求repos/{owner}/{repo}/pulls/$PRN,解析state字段;若不是open则直接退出(exit 0,属于无需处理的正常结束)。

检查二:mergeable 轮询。mergeable()并非只查一次——GitHub 在计算合并状态期间会返回mergeable: null,因此脚本使用while true循环,直到取到true(成功)或false(冲突,退出码 1),见 mergeable 轮询逻辑。

检查三:CI check-runs 全绿。last_commits()先拉取 PR 的提交列表,并用一段 awk 把提交顺序反转(最新提交在前);然后last_check()对最新一个有检查结果的提交请求check-runs接口(注意使用了application/vnd.github.antiope-preview+json这个 API 预览版本头),逐条解析conclusion字段。只要有任何一条不是success就中止;如果所有提交都查不到检查结果(CHECKED为空),说明 CI 尚未跑完,脚本会提示"give up and try later"。相关实现见 提交与检查解析 和 结果判定循环。

检查四:reviewer 审批核对。只有当第二个参数非空时才执行:脚本先把 PR 详情与全部 issue 评论分别落盘到临时文件,再交给 advchecks.py 做比对,失败则退出(见 reviewer 检查调用)。

标签如何"驱动"合并

检查全部通过后,脚本并不直接调用 merge API,而是按顺序给 PR 发两条"指令性"评论并轮询标签落库:先label "$PR" "/lgtm" "lgtm",再label "$PR" "/approve" "approved"(见 打标签流程)。label()的内部机制是:向 PR 发一次评论(如/lgtm),然后每隔 1 秒轮询一次issues/$PRN/labels,最多等 30 秒;整个流程最多重试 3 轮。从源码结构看,这种"发评论—等标签"的异步协同表明:真正给 PR 打上lgtm、approved标签的是仓库配套的 CI 机器人,而合并动作也由机器人在看到approved标签后触发——脚本本身只负责检查与下"指令"。

advchecks.py:reviewer 审批核对逻辑

advchecks.py 是一个独立的 Python 校验器,输入为两个 JSON 文件:PR 详情与 PR 评论列表。其核对规则是:

  • 从 PR 详情的requested_reviewers字段提取全部被指派的 reviewer(以login(id)标识);
  • 从评论中筛选正文精确等于/lgtm的评论,得到已表态的评审者集合;
  • 若没有任何 reviewer 被指派,直接以非零码退出("No reviwer is assigned");
  • 若还有 reviewer 未/lgtm,打印缺勤名单("Reviewers xxx needs /lgtm")并以非零码退出。

这保证了approve.sh <PRN> check_reviewers场景中"所有指派评审者均已认可"这一语义被严格验证,而不是仅凭评论数量判断。

approve_all.sh:批量合并主 PR 与 backport 组

文档语义

approve_all.sh 用于"合并一组 PR":这组 PR 由 master 上的主 PR 和 backport 到各个分支的 cherry pick PR 组成。文档规定:对 master 上的 PR 做全部 4 项检查,对其他(cherry pick)PR 只做前 3 项检查。

实现细节

脚本的执行逻辑与文档一一对应(见 approve_all.sh 主流程):

  1. 以per_page=1000拉取仓库最近一页全部 PR,提取每个 PR 的number与title;
  2. 用标题匹配Automated cherry pick of #<PRN>:找出所有与主 PR 关联的 cherry pick PR;
  3. 循环调用approve.sh依次合并:第一遍调用时传入REVIEWER_CHECK=yes(对应 master 主 PR 的 4 项检查),合并成功后将REVIEWER_CHECK置空,后续 cherry pick PR 即只执行前 3 项检查;任一 PR 合并失败则整体中止(exit 1)。

值得注意的一个边界情况:脚本把PRN自身放在组首,因此即使匹配不到任何 cherry pick PR,也等价于对主 PR 执行完整的approve.sh流程。

cherry_pick_pull.sh:cherry pick PR 组从何而来

approve_all.sh依赖的Automated cherry pick of #PRN:标题格式,来自同目录的 cherry_pick_pull.sh。该脚本脱胎于 Kubernetes 社区的 cherry-pick 工具(文件头注明 Copyright 2015 The Kubernetes Authors),其用法为:

./scripts/cherry_pick_pull.sh <remote branch> <pr-number>...

例如./scripts/cherry_pick_pull.sh upstream/release-3.14 12345会把 PR #12345 摘取到upstream/release-3.14分支并自动开 PR。关键行为(均可在 cherry_pick_pull.sh 中确认):

  • 新建分支名形如automated-cherry-pick-of-#12345-<target-branch>-<timestamp>(分支命名);
  • 下载https://github.com/<org>/<repo>/pull/<pr>.patch后以git am -3应用,冲突时会暂停并等待人工在另一窗口解决后确认继续;
  • 自动创建的 PR 正文首行即Automated cherry pick of #<pr1> #<pr2>(PR 描述生成),这正是approve_all.sh的标题匹配模式所依赖的约定;
  • 支持环境变量:DRY_RUN跳过 push 与建 PR(只把 cherry pick 留在本地分支)、UPSTREAM_REMOTE(默认upstream)、FORK_REMOTE(默认origin)、GITHUB_USER(必填,PR 来源用户名/组织);
  • 脚本要求hub版本不低于 2.13.0,且工作区必须干净、无进行中的git rebase/git am。

至此形成一条完整链路:cherry_pick_pull.sh在多个 release 分支上产生同标题族的 PR →approve_all.sh按主 PR 号一次性合并整族 PR。

lgtm.sh 与 label.sh:标签自动化的底层原语

lgtm.sh 自身只有一行核心逻辑:$CUR_DIR/label.sh $PRN /lgtm lgtm。它把"给 PR 打 lgtm 标签"统一委托给 label.sh,后者的完整用法是:

./scripts/label.sh <pr_number> <msg> <label>

即向 PR 发送评论msg,并轮询等待标签label出现,重试与轮询策略与approve.sh内置的label()完全一致(3 轮 × 30 秒)。这说明仓库内的标签体系遵循同一模式:脚本只发指令评论,标签由 CI 机器人异步添加,lgtm.sh则是该模式最轻量的入口。

同目录的其他辅助脚本

除文档列出的三个脚本外,scripts/目录还有两个轻量工具,与 CI 机器人协同生态相关:

  • comment.sh:向指定 PR 发送一条或多条评论(comment.sh <PRN> <msg>...),是approve.sh/label.sh中评论逻辑的独立版本;
  • webhook.py:一个基于标准库的调试用 HTTP 服务,默认监听0.0.0.0:20888,原样打印 POST 请求体及X-Yunion-Event请求头并返回{"result":"ok"},适合在本地验证 webhook 投递链路。

使用前提与注意事项

  1. 运行环境:脚本假定当前目录是目标仓库的 git 检出,并依赖hub(hub api repos/{owner}/{repo}/...需要 hub 依据仓库 origin 解析 owner/repo)与python可用;
  2. 平台前提:整套工具面向 GitHub 工作流(hub api、GitHub check-runs API、cherry-pick patch 下载地址等),迁移到其他代码托管平台时需要重写 API 调用层;
  3. 职责边界:approve.sh的 4 项检查(open 状态、无冲突、CI 全绿、reviewer 认可)是"防遗漏"机制,文档明确要求执行人工 review 之后再执行脚本,脚本不替代人肉 code review;
  4. CI 未完成时的表现:检查三项依赖 PR 最新提交上的 check-runs,若 CI 尚未开始,脚本会明确提示稍后再试而非误合并;
  5. 批量合并的原子性:approve_all.sh在组内任一 PR 检查失败时立即退出,已合并的 PR 不回滚,因此建议在 CI 状态稳定后再执行批量操作。

从 scripts/README.md 到各脚本源码可以看出,这套工具的设计思路是"检查在客户端、动作经机器人":脚本承担确定性检查与指令下发,标签与合并由 CI 机器人闭环执行,从而在保留人工 review 责任的同时,把重复性的状态核对与批量 backport 合并交给可复核的自动化流程。

  • 后端
  • 云原生
  • 运维
  • 虚拟化
  • 人工智能
  • AI 应用

【免费下载链接】cloudpods

开源、云原生的多云管理及混合云融合平台

项目地址:https://gitcode.com/yunionio/cloudpods
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询