Community编程与开发github.com

land-renovate

批量合并当前仓库中由 Renovate 创建的安全 PR:遍历、分类、批准并重新基准合并,提示冲突或需人工处理的 PR。

land-renovate 是什么?

本技能(land-renovate)用于自动化处理当前 GitHub 仓库中由 Renovate 机器人创建的所有开放 Pull Request(PR)。它会先通过 `gh` CLI 枚举这些 PR,然后根据状态检查、合并状态和冲突情况将它们分为 GREEN(绿色,可直接合并)、CONFLICTING(冲突)、REAL_FAILURE(真实失败)和 HOLD(需人工介入)四类。对于标记为 GREEN 的 PR,技能会自动批准并执行 rebase-merge;对于 CONFLICTING 的 PR,它会勾选 Renovate 的 rebase 复选框以触发重新基准,并启动一个监控循环等待新的检查通过;对于 REAL_FAILURE 和 HOLD 的 PR,它会跳过或报告给用户,绝不自动合并。该技能完全基于远程 PR 操作,不涉及本地提交。它适用于 GitHub 平台,并通过 `gh` CLI 与 GitHub API 交互。使用场景包括用户说“/land-renovate”、“合并 Renovate PR”、“清理 Renovate 队列”或希望批量合并依赖更新 PR。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/langri-sha/skills/tree/main/land-renovate

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

land-renovate 是做什么的?

遍历当前仓库中所有开放的 Renovate PR 队列,安全地合并其中的 PR:枚举、分类、按 PR 编号升序批准并执行 rebase-merge,对冲突的 PR 勾选 rebase 复选框进行提示,并在遇到真实失败或 HOLD 情况时干净地停止。

此技能完全通过 gh 操作现有的远程 PR。它不会调用 /create-commit、/create-pr 或 /wrap,也不会创建本地提交。

参数

参数默认值描述
limit=N30限制最多遍历的 PR 数量。
<pr-number>...所有 Renovate 创建的开放 PR空格分隔的 PR 编号;仅操作这些 PR。

默认值:当前仓库(通过 gh repo view --json nameWithOwner 获取)、Renovate 创建的开放 PR、按 PR 编号升序、无标签过滤。

工作流程

1. 解析仓库

REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)

2. 枚举 Renovate PR

列出所有开放的、由 Renovate 创建的 PR,按编号升序(最旧的优先):

gh pr list -R "$REPO" --author "app/renovate" --state open --limit 30 \
  --json number,title,mergeable,mergeStateStatus,statusCheckRollup

按 number 升序排序并遍历。如果传入了显式的 PR 编号作为参数,则限定到这些 PR。

注意: gh pr list 常常返回 mergeable: UNKNOWN,因为 GitHub 惰性计算合并性。对单个 PR 执行 gh pr view <n> --json mergeable 可以强制计算。当某个 PR 的 mergeable 是 UNKNOWN 时,在分类前先用 gh pr view 重新读取。

3. 分类每个 PR

使用 statusCheckRollup + mergeable + mergeStateStatus 将每个 PR 归入以下桶:

桶信号操作
GREENrollup 中没有 FAILURE/CANCELLED/TIMED_OUT,没有待处理项,mergeable=MERGEABLE批准 + rebase-merge(步骤 4)
CONFLICTINGmergeable=CONFLICTING 或 mergeStateStatus=DIRTY勾选 rebase 复选框(步骤 5),然后监控
REAL_FAILURErollup 中包含非后升级自动修复的 FAILURE跳过;留给人工排查
HOLD需要跨文件协调(人工检查清单 — 见下文)提示用户;不继续处理

rollup 中的检查在待处理状态是指 CheckRun 的 status != COMPLETED 或 StatusContext 的 state 为 PENDING/EXPECTED。失败状态是指 CheckRun.conclusion 为 FAILURE/CANCELLED/TIMED_OUT/ACTION_REQUIRED/STARTUP_FAILURE,或 StatusContext.state 为 FAILURE/ERROR。

HOLD 检查清单(人工判断 — 非硬编码)

HOLD 检测是代理的判断决策,而非自动化规则。当单独合并一个 PR 会破坏另一个文件中的内容时,将该 PR 视为 HOLD 候选,例如:

  • terraform-version 版本不匹配 — Terraform provider/CLI 升级需要在其他地方更新相应的版本约束(例如 .terraform-version、CI 工作流或 required_version 约束),否则不安全。
  • 需要代码编辑的 schema 升级 — 依赖项的主版本升级改变了手写代码仍在使用的 schema/类型;后升级钩子无法生成代码编辑。
  • 任何变更日志中指明需要后升级作业不会执行的协调编辑的升级。

当 PR 看起来像是 HOLD 时,将其展示给用户并询问 — 不要自动合并,也不要勾选 rebase 复选框。继续遍历队列中的其余 PR。

4. 批准 + 合并(GREEN)

gh pr review "$PR" -R "$REPO" --approve \
  --body "LGTM — 作为 Renovate 批量合并的一部分自动批准。"
gh pr merge "$PR" -R "$REPO" --rebase --delete-branch

5. 勾选 rebase 复选框(CONFLICTING)

勾选 Renovate 的 rebase 复选框以触发重新基准,然后监控:

body=$(gh pr view "$PR" -R "$REPO" --json body -q .body)
new=$(printf '%s' "$body" | sed 's|^\( *\)\(- \[ \] <!-- rebase-check -->\)|\1- [x] <!-- rebase-check -->|')
printf '%s' "$new" | gh pr edit "$PR" -R "$REPO" --body-file - >/dev/null

在勾选复选框之前,捕获当前头部 SHA 作为基线,然后运行监控(步骤 6),以便区分 rebase 和起始状态:

BASELINE=$(gh pr view "$PR" -R "$REPO" --json headRefOid -q .headRefOid)

绝对不要在 REAL_FAILURE 上勾选 rebase 复选框 — 这会浪费 Renovate 的周期并隐藏真正的问题。

6. 监控直至稳定

附带的 scripts/monitor-renovate-pr.sh 脚本会轮询单个 PR,直到其检查稳定并输出代理通过 Monitor 工具消费的判定结果。

scripts/monitor-renovate-pr.sh <pr-number> <repo> <baseline-head-sha-short>
  • 每 45 秒(可通过 POLL_INTERVAL 覆盖)轮询 gh pr view --json headRefOid,mergeable,mergeStateStatus,statusCheckRollup,仅在签名 ${head:0:9}|<mergeable>:<state>|ok=N pend=M fail=K 变化时打印一行。
  • 一旦头部离开基线、没有待处理检查且签名在连续两次轮询中稳定,则发出判定。
  • 最终的标准输出行是以下之一:
    • GREEN: #<n> ready to merge → 返回步骤 4 并批准 + 合并。
    • NOT-GREEN: #<n> settled failures=X mergeable=Y state=Z → 重新分类;现在它是 REAL_FAILURE 或 HOLD。
  • 可选环境变量:POLL_INTERVAL(秒,默认 45)、MAX_POLLS(在 N 次轮询后放弃,0 = 无限制;超时时输出 NOT-GREEN: #<n> timeout ...)。

为什么使用轮询循环而不是 gh pr checks --watch

对于已经可合并且仅运行检查的 PR,gh pr checks <n> --watch 很好用,但它在本技能专门处理的 rebase 路径上会给出误导:

  • 它在过时的头部上返回绿色。 勾选 rebase 复选框后,PR 的_当前_检查已经终结 — 它们在 rebase 前(冲突)的头部上通过了。--watch 看到“没有待处理的检查”后立即返回成功,而 Renovate 甚至还没有开始 rebase。head moved off baseline 条件正是防止这种假绿色的守卫。
  • 它只知道检查,不知道合并性。 GREEN 判定需要 mergeable=MERGEABLE + mergeStateStatus=CLEAN,而 CONFLICTING 正是通过那些字段_检测_的 — gh pr checks 从不报告它们。一次 gh pr view 轮询即可同时覆盖两者。
  • 头部可能移动两次(Renovate 推送,然后应用机器人后升级推送)。在这两次推送之间存在一个窗口,已知的检查会暂时完成;--watch 可能在这个间隙退出。“没有待处理检查且稳定通过两次轮询”的守卫可以安全通过这个窗口。

7. 预期的 rebase 后提交链

勾选 rebase 复选框后(或 Renovate 自行 rebase),一个 GREEN 的合并通常会经过以下链 — 了解这一点可以帮助你了解监控中的波动是预期的,而非失败:

  1. Renovate 推送新的头部,作为 renovate[bot]。
  2. pull_request 工作流触发。check.yml 的后升级步骤运行 eslint --fix、prettier --write、vitest --update、projen 以及 beachball 变更条目。
  3. 如果后升级步骤产生了差异,commit-upgrade-changes 作业会通过 actions/create-github-app-token@v2 生成一个 App 令牌,并将修复推送为 <app-slug>[bot]。该机器人推送会重新触发 pull_request 工作流,因此头部第二次移动,检查重新运行。
  4. 最终就绪状态:mergeable=MERGEABLE、mergeStateStatus=CLEAN,所有检查为 SUCCESS/SKIPPED。

由于头部可能移动两次(Renovate,然后是应用机器人),监控器将判定条件定为“头部离开基线 + 无待处理检查 + 两次稳定轮询”,而不是仅看到第一次推送。

停止条件

  • 没有剩余的 GREEN PR — 完成。
  • REAL_FAILURE — 跳过,继续处理下一个 PR;绝不自动 rebase REAL_FAILURE。
  • HOLD 候选 — 展示给用户决策;不自动合并。
  • 用户取消。

约束

  • 提交主题不得包含问题/PR 引用(项目规则)。此处合并远程 PR 时不适用,但如果本技能将来扩展为创建本地提交,请将引用放在正文中而非主题中。参见 /create-commit。
  • 绝不勾选 REAL_FAILURE 的 rebase 复选框。
  • 绝不自动合并 HOLD 候选。
  • HOLD 检测是人工检查清单,而非硬编码规则。识别上述类别并展示候选,不要尝试自动化决策。

测试说明

干运行分类

枚举并直观检查桶分类而不执行任何操作:

gh pr list -R "$REPO" --author "app/renovate" --state open \
  --json number,title,mergeable,mergeStateStatus,statusCheckRollup \
  | jq -r '.[] | "\(.number)\t\(.mergeable)\t\(.mergeStateStatus)\t\(.title)"'

为每个 PR 添加 rollup 摘要以查看待处理/失败的检查:

gh pr list -R "$REPO" --author "app/renovate" --state open \
  --json number,statusCheckRollup \
  | jq -r '.[] | "\(.number)\t" + ([.statusCheckRollup[] | .conclusion // .state] | join(","))'

监控冒烟测试

对一个已知的 PR 运行监控,使用假的基线 SHA(这样头部已经算作“移动”),并使用短间隔观察状态行和最终判定:

POLL_INTERVAL=2 MAX_POLLS=4 \
  scripts/monitor-renovate-pr.sh <known-pr> "$REPO" deadbeef0

您应该看到每次签名变化时的状态行,然后是 GREEN: / NOT-GREEN: 判定。传递 PR 的真实头部作为基线则测试无 rebase 路径:头部从不移动,因此永不稳定,运行会在 MAX_POLLS 超时时结束。

不涉及的范围

  • 硬编码的 HOLD 检测规则(从上述人工检查清单开始;以后再扩展)。
  • 将此技能接入任何编排层。

相关技能