ClickHouse CI 构建失败排查实战:从 artifacts-build.md 读懂构建日志工件
2026/9/7 6:09:58 网站建设 项目流程

ClickHouse CI 构建失败排查实战:从 artifacts-build.md 读懂构建日志工件

【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse

当你面对 ClickHouse 持续集成流水线中一个Build (amd_binary)之类的构建失败时,真正有价值的线索往往不在 CI 页面截断后的摘要里,而在 S3 上那份完整的build_clickhouse.log(或它的 zstd 压缩版本)中。本文以仓库中的 CI 排查技能文档 artifacts-build.md 为主体,完整讲解如何从 CI 工件中定位编译错误、clang-tidy 错误与链接错误:包括压缩规则、fetch_ci_report.js已提供的日志窗口、完整构建日志的拉取与过滤命令,以及日志截断标记背后的源码实现。读完后,你可以对任意一次 ClickHouse CI 构建失败独立完成从“报告链接”到“具体报错行”的全链路定位。

背景:构建失败工件在 investigate-ci 技能中的位置

.claude/skills/investigate-ci/目录下有一组技能文档,用于指导对 ClickHouse CI 失败的端到端只读排查。SKILL.md 定义了整体流程:解析 PR/报告 URL、拉取失败测试、检索既有 issue 与修复、用 master 历史判定 flaky/real,最后才按需下载工件做根因分析。在“工件布局”部分,SKILL.md 明确列出了四种工件族文档:

  • artifacts-integration.md— 集成测试(logs.tar.gz归档结构、pytest_parallel.jsonlschema、各节点 server 日志)
  • artifacts-stateless.md— stateless 与 fast 测试(独立日志文件、.zst拉取)
  • artifacts-stress.md— stress 测试(clickhouse-server.initial.logfatal.loghung_check.log
  • artifacts-build.md —构建失败(完整构建日志、截断标记、tidy 与编译错误的区分)

本文聚焦最后一项。技能文档的核心原则是:工件只在“读取错误信息与源码后仍有真实缺口”时才下载,而构建失败(INFRA/BUILD类)恰好是最典型必须看完整日志的场景——编译错误只出现在日志深处,报告页面上只能看到ninja: build stopped: subcommand failed这一句结论。

压缩规则:按文件大小决定 plain 或.zst

原文档开头给出了一个关键提示,理解它才能正确使用后续所有 URL:

Praktika 上传工件时,压缩与否取决于文件大小:小文件以纯文本上传,大文件以 zstd 压缩的.zst对象上传。--links显示的 URL 反映的是 S3 上真实的对象键(key),应原样使用;手动拼 URL 时应先试纯文件名,遇到 404 再补.zst后缀并解压。

这不是文档的口头约定,而是工具代码里的实际行为。fetch_ci_report.js 的抓取逻辑在收到 403/404 且 URL 不以.zst结尾时,会自动追加.zst重试(见 fetch_ci_report.js#L97-L99):

if ((res.statusCode === 403 || res.statusCode === 404) && !urlString.endsWith('.zst')) { return fetchUrl(urlString + '.zst', credentials).then(resolve).catch(reject); }

同一文件中,工具还内置了透明解压能力(zstd/gzip 均可识别,见 fetch_ci_report.js#L54-L57),并在--links输出时按后缀过滤出真正的工件链接——.log.log.zst.tar.gz.tar.zst.tgz.zst等(见 fetch_ci_report.js#L450-L464),同时排除praktika.html/json.html之类的导航链接。因此对使用者而言只需要记住一条经验法则:看 URL 后缀决定要不要解压,404 就试.zst

工具已经替你做了什么:result.info的头尾窗口

fetch_ci_report.js --failed会从报告 JSON 的result.info中提取一个“头 + 尾”窗口,其内容定义如下(完整继承自原文档):

  • Head(头部):日志的开头部分;对于大日志,则是 CI 框架截断标记~~~~~ truncated N lines at the beginning ~~~~~之后的位置;
  • Tail(尾部):日志的结尾,ninja: build stopped: subcommand failed和编译器报错(error:note:)就出现在这里。

对大多数编译错误,这个窗口已经足够——因为 ninja 的构建日志天然把错误集中在最后。只有当相关错误落在可见窗口之外(例如被头尾截断“夹”在中间),才需要去取完整日志。

这个“窗口”并非工具自己随意裁剪,其上游是 Praktika 的结果封装逻辑。ci/praktika/result.py#L1014-L1046 展示了截断策略的实现:命令输出超过MAX_LINES_IN_INFO = 300行时,会先扫描是否存在 clang-tidy 风格的: error:/: warning:行——

  • 找到了首个错误行:以它为锚点,取错误前 50 行、错误后约 249 行的上下文窗口,并在被裁掉的位置插入~~~~~ truncated N lines at the beginning ~~~~~/~~~~~ truncated N lines at the end ~~~~~标记;
  • 没找到错误行:退化为保留最后 300 行,头部插入~~~~~ truncated N lines ~~~~~标记。

从源码结构看,这正是 clang-tidy 任务(错误散布在日志中段而非末尾)仍能“免费”看到首错上下文的原因;而截断标记的两种形态也与artifacts-build.md中描述的完全对应。

拉取完整构建日志:=== Artifact Links ===与实战 grep 命令

完整日志文件名是build_clickhouse.log(或build_clickhouse.log.zst),它列在--links输出的=== Artifact Links ===区块下(该区块由 fetch_ci_report.js#L993 打印)。完整构建的日志可能非常大——文档明确提示“全量构建可达数百 MB”,所以不要直接下载到本地再慢慢翻,用流式管道边拉边过滤。以下是原文档给出的四条可复制命令,按 URL 后缀(plain 或.zst)二选一:

# Plain 日志 — 流式拉取并 grep 错误 curl -sL '<url>' | grep -E '^[^ ].*(error|FAILED):' | head -50 # 压缩日志 curl -sL '<url>' | zstd -dcq | grep -E '^[^ ].*(error|FAILED):' | head -50 # clang-tidy(plain):过滤掉被抑制警告的噪音 curl -sL '<url>' | grep -v 'Suppressed\|NOLINT\|warnings generated' \ | grep -i 'error:' | head -50 # clang-tidy(压缩): curl -sL '<url>' | zstd -dcq | grep -v 'Suppressed\|NOLINT\|warnings generated' \ | grep -i 'error:' | head -50

使用要点:

  1. grep -E '^[^ ].*(error|FAILED):'要求错误行必须以非空白字符开头,用于排除缩进的构建进度行;
  2. zstd -dcq-q表示静默,避免诊断信息污染管道;
  3. clang-tidy 日志中每个源文件都会打印一段“N warnings generated / Suppressed M warnings”的计数汇总,SuppressedNOLINTwarnings generated是主要噪音来源,先grep -v排除再找error:,能显著减少误报。

日志截断:识别“错误在被裁掉的部分”

原文档的“Log truncation”一节给出一个判断准则:当result.info同时出现头部和尾部两个截断标记(顶部~~~~~ truncated N lines at the beginning ~~~~~、底部~~~~~ truncated N lines at the end ~~~~~)时,说明真正的错误正好落在被裁掉的中间区段——此时不要再依赖报告窗口,直接拉取并检索完整build_clickhouse.log

结合前面 ci/praktika/result.py#L1014-L1046 的源码可以精确理解这个信号的含义:只有“以首个: error:行为锚点”的截断路径才会同时产生 beginning 和 end 两种标记,也就是说你看到的窗口是围绕首个错误上下文展开的;如果错误信息本身(或它关联的模板/宏展开上下文)跨越了 300 行窗口,头尾标记就会成对出现,提示你去完整日志中检索。此时建议的检索路径是:先用上面的grep命令在完整日志中定位所有error:行,再用行号回看上下文。

按构建类型区分关键报错模式

原文档按构建任务类型总结了三种报错模式,这是排查时的“分诊表”:

1. 常规编译错误(amd_binaryarm_debug等)

错误出现在日志末尾附近——寻找匹配error:的行,其紧随其后就是ninja: build stopped。这是最直接的一类:curl | grep管道取最后 50 条error:行,通常第一条就是根因(后续错误往往是同一编译单元或依赖头文件的连锁反应)。

2. clang-tidy(arm_tidyamd_tidy

tidy 任务的日志形态完全不同:

  • 每个源文件都会输出一段警告计数汇总(即N warnings generatedSuppressed M warnings那类行),它们不是错误;
  • 真正的 tidy 错误形如/path/to/file.cpp:NN:MM: error: [clang-tidy-check-name]出现在日志中段,与构建进度交错分布。

因此检索策略是“先降噪再定位”:grep -vSuppressed/NOLINT/warnings generated,再grep -i 'error:'。这也解释了为什么 ci/praktika/result.py 的截断逻辑专门为: error:/: warning:行设计了锚点窗口——它是为 tidy 这类中段报错场景定制的。

3. 链接错误

特征是把undefined referencecannot find -l<lib>这类字样,出现在非常靠后的位置、紧邻ninja: build stopped之前。与编译错误不同,链接错误的定位对象是目标文件与库名(-l<lib>),排查方向是新增/删除的源文件、CMakeLists.txt中的链接依赖变化,而非单个源文件的语法问题。

排查流程小结

artifacts-build.md的方法论压缩成一张可执行的检查清单:

  1. 先看报告窗口node .claude/tools/fetch_ci_report.js "<url>" --failed --links,阅读result.info的头尾窗口与=== Artifact Links ===区块,拿到build_clickhouse.log(或.log.zst)的真实 URL;
  2. 判断窗口是否够用
    • 只见尾部、错误清晰 → 直接读编译器报错,结束;
    • 头尾截断标记成对出现→ 错误在被裁区段,进入第 3 步;
  3. 流式检索完整日志:按 URL 后缀选择 plain 或zstd -dcq管道,按构建类型选择 grep 策略(tidy 任务先滤噪);
  4. 对号入座:编译错误看末尾error:+ninja: build stopped;tidy 错误找file.cpp:NN:MM: error: [check-name];链接错误找undefined reference/cannot find -l<lib>
  5. 结合报告 commit 读源码:技能文档(SKILL.md 第 4 步)强调用git show <sha>:<path>在报告对应的 commit 上读源码,行号才与报错一一对应——这一步属于排查技能的整体约定,构建失败场景同样适用。

整个方法的价值在于:它把“数百 MB 的构建日志”变成了“一次curl管道 + 一次 grep”的常成本操作,并且通过截断标记这一显式信号,让你明确知道什么时候窗口可信、什么时候必须下钻。所有涉及的工件命名(build_clickhouse.log.zst后缀)、截断标记格式(~~~~~ truncated N lines ... ~~~~~)均可在 ci/praktika/result.py 与 fetch_ci_report.js 的源码中得到印证,按上述流程操作时若发现行为与预期不符,这两个文件是最直接的可查证依据。

【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse

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

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

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

立即咨询