ClickHouse「CH Inc sync」CI 检查失效诊断与修复:fix-sync 技能驱动的私有仓库同步实战
【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse
本文以 ClickHouse 仓库内置的 Claude 技能 fix-sync 为主体,完整讲解公共 PR 上「CH Inc sync」提交状态检查的三种失败类型(conflicts found、build failed、tests failed)是如何产生的、如何用ghCLI 精准诊断,以及对应每一类失败的标准修复流程(合并冲突解决、私有代码适配、失败任务重跑)。读完本文,你将掌握 ClickHouse 公共仓库与私有仓库clickhouse-private之间的同步机制、同步分支sync-upstream/pr/<PR_NUMBER>的生命周期,以及一套可直接复制执行的 CI 排障命令序列。
一、「CH Inc sync」检查是什么:公私仓库同步机制
当有人在ClickHouse/ClickHouse上打开一个 PR 时,系统会自动在私有仓库ClickHouse/clickhouse-private中创建一个名为sync-upstream/pr/<PR_NUMBER>分支的同步 PR。公共 PR 上的「CH Inc sync」提交状态(commit status)实时反映这个私有同步 PR 的状态:同步 PR 一旦与私有master产生冲突、构建失败或测试失败,公共 PR 上的检查就会保持 pending 或 failing。
这个机制在仓库源码中有多处可直接验证的锚点:
- 检查名称常量定义在 ci/defs/defs.py:
SYNC = "CH Inc sync",整个 CI 体系都引用这个字符串; - set_sync_status_awaiting_hook.py 在
Code Review任务(每个 PR 必然运行)完成时,若该状态尚不存在,就向公共 PR 的 commit 写入一个pending状态、描述为awaiting,作为「同步流程可以开始」的标记; - set_dummy_sync_commit_status.py 在 Merge Queue 工作流中写入一个
success状态的 dummy 状态(描述为dummy status to enable merge),以便 PR 能先入队合并——真正的同步验证在合并后的私有 CI 中继续; - check_sync_pr_mergeable.py 在 CI 中做合并前的硬校验:用
gh pr list --state open --head sync-upstream/pr/<N> --repo ClickHouse/clickhouse-private --json number找到同步 PR,再查询其mergeable字段。逻辑上有几个值得注意的工程细节:- 找不到任何 open 的同步 PR 时放行(视为跳过检查);
- 找到多个同步 PR 时判定为错误并返回失败(
ERROR: Expected at most one open Sync PR ...); mergeable为UNKNOWN时会sleep(5)秒后重试一次,仍为UNKNOWN则放行,为CONFLICTING才判定失败——这正是 fix-sync 技能中「conflicts found」状态的来源之一;
- merge_sync_pr.py 负责在公共
master前进时把对应同步 PR 合入私有仓库。它从 GitHub push 事件的GITHUB_EVENT_PATHpayload 中解析出本批次的 merge-queue 合并提交:由于 GitHub 的 merge queue 可能把多个 PR 合并在同一次推送中,脚本不只看 head 提交,而是扫描整个commits数组,用锚定在行首的正则^Merge pull request #(\d+)提取每个 PR 号(锚定可排除Revert "Merge pull request #..."这类干扰),并按 payload 中从旧到新的顺序逐个执行gh pr ready+gh pr merge --merge,保证同步顺序与公共 master 的合并顺序一致。
此外,quick_sync.py 提供了一个仅对特定内部账号开放的快捷通道:手动触发私有仓库的private_quick_sync.yml工作流,并把公共 PR 的状态直接置为pending(描述sync started)或error(描述failed to start the sync)。
需要说明的是,SKILL.md 中提到的ci/jobs/private_sync_pr.py与ci/jobs/scripts/workflow_hooks/private_sync_complete_check.py(分别负责写conflicts found与build failed/tests failed状态描述)位于私有仓库clickhouse-private中,本公共仓库里看不到,这是文档给出的事实边界。
二、三类失败类型与状态语义
根据 SKILL.md 的定义,私有 CI 会把失败写成三种描述,各自对应不同的修复手段:
| 状态描述 | 含义 | 修复动作 |
|---|---|---|
conflicts found | 同步 PR 无法与clickhouse-private的master合并(mergeable == CONFLICTING) | 解决合并冲突并推送(步骤 4A) |
build failed | 同步 PR 能干净合并,但私有 CI 的构建任务失败;通常是上游改动重命名/移动/改了符号签名,而私有仓库中引用了这些符号的私有代码没跟上 | 适配私有代码并推送(步骤 4B) |
tests failed | 能合并、能构建,但测试任务失败;可能是 flaky/基础设施问题(重跑即可),也可能是真实回归(需调查) | 分类后重跑或调查(步骤 4C) |
testing(state 为pending) | CI 仍在运行 | 等待,不要操作 |
completed(state 为success) | 无异常 | 无需操作 |
fix-sync 技能是一个 Claude Agent 技能,其 frontmatter 声明了argument-hint: <pr-number-or-url>,并限定工具白名单为Task, Bash(gh:*), Bash(cd:*), Bash(git:*), Bash(ls:*), Bash(pwd:*), Bash(mktemp:*), Read, Grep, Glob, AskUserQuestion——即整个诊断修复过程只允许用gh、git与文件读取类工具,保证操作可审计、不越权。
参数
$0(必需):公共 ClickHouse PR 的编号或完整 URL(例如96005或 PR 的/pull/96005形式完整地址)。若未提供参数,技能会通过AskUserQuestion向用户询问。
三、标准诊断流程(第 1–3 步)
1. 解析 PR 编号
从$ARGUMENTS中提取 PR 编号;若传入的是完整 PR URL,则从 URL 中解析编号。
2. 定位同步 PR
在私有仓库中搜索对应同步分支的 PR:
gh pr list --repo ClickHouse/clickhouse-private --head sync-upstream/pr/<PR_NUMBER> \ --json number,url,state,mergeable,mergeStateStatus,headRefName,headRefOid- 找不到同步 PR:向用户报告并停止;
- 找到:向用户报告同步 PR 的编号与 URL。
这个「一个分支至多一个 open 同步 PR」的假设与 check_sync_pr_mergeable.py 中的len(sync_pr_numbers) > 1报错逻辑完全一致。
3. 诊断失败类型(关键步骤)
首选路径:读取公共 PR 上「CH Inc sync」状态的 description,它直接给出失败类型:
# 先拿到 HEAD SHA gh pr view <PR_NUMBER> --repo ClickHouse/ClickHouse --json headRefOid # 再过滤该 context 的提交状态 gh api repos/ClickHouse/ClickHouse/commits/<HEAD_SHA>/statuses \ --jq '.[] | select(.context == "CH Inc sync") | {state, description}'映射关系:
conflicts found→ 走步骤 4A;build failed→ 走步骤 4B;tests failed→ 走步骤 4C;testing(state 为pending)→ CI 还在跑,报告后停止;completed(state 为success)→ 无需操作,停止。
兜底路径:状态描述缺失或有歧义时,直接检查同步 PR:
mergeable为CONFLICTING(或mergeStateStatus为DIRTY)→ 归为Conflicts found(4A);- 否则用
gh pr checks <SYNC_PR_NUMBER> --repo ClickHouse/clickhouse-private查看私有 CI:失败的 job 名称以Build开头 →Build failed(4B);只有测试 job 失败 →Tests failed(4C)。
诊断结论必须先报告给用户,再执行任何修复动作。
四、第 4 步前置:定位本地私有仓库
4A 与 4B 需要本地可写的私有仓库工作副本,查找顺序为:
../ClickHouse_private../clickhouse-private- 校验目录存在且是 git 仓库、remote 中包含
ClickHouse/clickhouse-private
都找不到时用AskUserQuestion请用户提供路径,并在后续步骤中复用该路径。
五、4A:处理conflicts found
在私有仓库目录中执行:
# 拉取最新并获取同步分支 cd <private_repo_path> && git fetch origin && git fetch origin sync-upstream/pr/<PR_NUMBER> cd <private_repo_path> && git checkout sync-upstream/pr/<PR_NUMBER>若分支上有未提交的本地改动,先询问用户再继续。
然后合并私有master并解决冲突:
cd <private_repo_path> && git merge origin/master冲突处理规范:
- 列出冲突文件:
cd <private_repo_path> && git diff --name-only --diff-filter=U - 逐个文件解决:SKILL 建议使用
subagent_type=general-purpose的 Task 子代理,读取文件内容、分析冲突标记(<<<<<<<、=======、>>>>>>>),按以下原则确定解法,用 Edit 工具落盘后git add <file>:- 大多数同步冲突,上游(公共仓库)改动优先;
- 仅存在于私有仓库的文件,原样保留;
- CI/workflow 类文件要特别小心,保留私有仓库专属配置;
- 若冲突复杂或有歧义,展示冲突内容并用
AskUserQuestion请用户裁决,不得猜测。
- 完成合并:
cd <private_repo_path> && git commit --no-edit
最后按需更新子模块:
cd <private_repo_path> && git submodule update --init --recursive子模块更新失败时报告错误但继续流程。之后进入第 5 步。
六、4B:处理build failed
「能干净合并但构建失败」几乎总是意味着:上游改动重命名、移动或变更了某个符号,而私有独占代码还在依赖旧符号;也可能是冲突解决时漏掉的代码适配。
- 拿到构建日志,定位确切的错误:
gh run list --repo ClickHouse/clickhouse-private --branch sync-upstream/pr/<PR_NUMBER> \ --json databaseId,name,conclusion,headSha有报告 URL 时优先用公共仓库自带的 CI 报告工具 fetch_ci_report.js(见 CLAUDE.md 中的用法说明,例如
node .claude/tools/fetch_ci_report.js "<PR_URL>" --failed --download-logs),或直接gh run view --log-failed查看失败 job 日志。 - 定位构建错误(编译错误、链接错误、缺失符号),用 general-purpose 子代理分析日志,只返回相关错误片段与涉及的文件/符号。
- 在私有仓库中复现并修复:checkout 同步分支(若尚未合并则先 fetch + merge
origin/master),然后修改有问题的私有代码以匹配上游改动。原则是适配私有代码去迁就新的上游 API,而不是回退上游改动。 - 可选:本地重新构建验证(见第 5 步)。
七、4C:处理tests failed
合并与构建都正常,测试失败。首要任务是区分flaky/基础设施问题与真实回归:
- 获取失败详情:
gh pr checks <SYNC_PR_NUMBER> --repo ClickHouse/clickhouse-private gh run list --repo ClickHouse/clickhouse-private --branch sync-upstream/pr/<PR_NUMBER> \ --json databaseId,name,conclusion - 判定为 flaky/基础设施的判据:失败与 PR 改动无关,例如
Cannot start clickhouse-server、Timeout、网络/磁盘错误,或失败测试触及 PR 根本不修改的区域。SKILL 中给出了一个真实案例注记(pr-89842-sync-rerun):某个只改src/IO/*的 PR 出现了Cannot start clickhouse-server/Timeout失败,显然与本 PR 无关。- 动作:只重跑失败的任务,且不要做 merge:
gh run rerun <RUN_ID> --repo ClickHouse/clickhouse-private --failed - 报告已触发重跑后停止。
- 动作:只重跑失败的任务,且不要做 merge:
- 否则视为真实回归:用子代理抓取并总结失败测试日志,向用户报告失败用例与最可能的原因。未经确认不得推送猜测性修复——用
AskUserQuestion决定下一步。
4C 路径通常不推送(除非真的提交了修复),因此除非有代码变更,否则跳过第 5 步。
八、第 5–6 步:推送与验证(4A / 4B,以及 4C 提交了修复时)
可选构建验证
推送前用AskUserQuestion询问用户:
- 选项 1「Yes, build」:在私有仓库 build 目录中运行 ninja,输出重定向到构建日志文件,用子代理总结结果;
- 选项 2「No, skip build」:跳过构建直接推送。
推送
cd <private_repo_path> && git push origin sync-upstream/pr/<PR_NUMBER>验证同步 PR
推送(或重跑)之后:
gh pr view <SYNC_PR_NUMBER> --repo ClickHouse/clickhouse-private --json mergeable,mergeStateStatus gh pr checks <SYNC_PR_NUMBER> --repo ClickHouse/clickhouse-private按失败类型分别汇报:
- Conflicts found:
mergeable变为MERGEABLE则报告「同步 PR 现在可合并,CH Inc sync 检查应很快通过」;仍冲突则报告需要进一步调查; - Build failed:报告构建任务是否通过(CI 启动可能需要一些时间);
- Tests failed:报告重跑是否在进行中,或修复是否已推送。
最后附上同步 PR 的 URL 供用户自行查看。
九、技能内置的工程约定(Notes)
这些约定值得单独列出,它们解释了为什么流程必须「先诊断、再动作」:
- 永远先诊断失败类型再操作。对一个已经是
MERGEABLE的同步 PR 跑 merge 没有任何收益——构建/测试类失败的修复方式完全不同(pr-89842-sync-rerun案例:没有合并冲突时应重跑失败任务,而不是无脑跑/fix-sync); - 同步分支命名固定为
sync-upstream/pr/<PR_NUMBER>; - 私有仓库工作副本通常位于公共仓库的上一级目录;
- 大多数冲突都很直接,遵循「上游改动优先」即可解决;
- 切换分支前必须先 fetch,确保拿到最新状态;
- 禁止 rebase 或 amend,只能新增提交——这与 CLAUDE.md 中的项目级约定("When working with a branch, do not use rebase or amend - add new commits instead")完全一致;
- 推送后 GitHub 检查状态的刷新可能有几分钟延迟,属正常现象。
十、典型用法示例
/fix-sync 96005—— 对 PR #96005 做同步诊断与修复;/fix-sync <PR 完整 URL>—— 使用完整 URL 作为参数触发同样的流程。
小结
ClickHouse 的公私仓库同步体系把「同步是否健康」压缩成了「CH Inc sync」这一个提交状态的 description 字段:conflicts found指向 git 层面的合并冲突(修法是 mergeorigin/master并按「上游优先」原则解冲突),build failed指向私有代码对上游符号的引用失效(修法是适配私有代码而非回退上游),tests failed则要求先区分 flaky 与真实回归(前者gh run rerun --failed,后者先报告再决定)。fix-sync 技能正是把这套「诊断三分法 + 分路径修复 + 推送验证」沉淀成了可复现的 Agent 工作流,其命令序列与 ci/jobs/scripts/workflow_hooks/ 下各 hook 脚本的检查逻辑一一对应,可直接作为团队排障手册使用。
【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考