can be tested 标签之后。
如 GitHub checks 文档所述,这些检查结果会显示在 GitHub 拉取请求页面上。
如果某项检查失败,你可能需要修复它。
本页概述了你可能会遇到的检查,以及相应的处理方法。
如果看起来检查失败与你的更改无关,可能只是暂时性故障或基础设施问题。
向该拉取请求推送一个空提交,以重新启动 CI 检查:
与 master 合并
Cannot fetch mergecommit。
要修复此检查,请按 GitHub 文档 中的说明解决冲突,或者使用 git 将 master 分支合并到你的拉取请求分支。
文档检查 (Mintlify)
pr-autogenerated-docs 标签。
如果文档更改后检查失败,请打开报告并查找 ERROR 和 WARNING 消息。
描述检查
Docker 镜像
官方 Docker 库测试
clickhouse/clickhouse-server Docker 镜像 能否正常工作。
要添加新测试,请创建目录 ci/jobs/scripts/docker_server/tests/$test_name,并在其中创建 run.sh 脚本。
有关这些测试的更多信息,请参见 CI 作业脚本文档。
Marker 检查
风格检查
ci/jobs/check_style.py 中的一个 testname,并且都可以使用 --test <name> 单独运行 (见下文) 。
cpp
check_cpp.sh 进行基于 Regex 的 C++ 风格检查。如果检查失败,请根据代码风格指南修复相应的风格问题。
whitespace_check
catch_all
main 和 fuzzer 入口点以外使用 catch (...),因为在其他位置吞掉未知异常并不安全。
yamllint
.yamllint 检查 .github/ 下的 YAML 工作流文件。
xmllint
tests/ 和 programs/ 下的 XML 文件进行验证。
functional_tests_check
event_date 进行过滤的查询必须使用 >= yesterday(),而不能使用 today() (以避免在午夜前后出现不稳定情况) ;此外,测试文件名不得包含 fail。
test_numbers_check
tests/queries/0_stateless/<NNNNN>_*) 。
符号链接
其他
various_checks.sh 执行的各项仓库检查:对 system.query_log / system.parts / 等的查询必须按 currentDatabase 过滤,Replicated*MergeTree 的 ZooKeeper path 必须包含每个测试各自的前缀,集成测试目录必须包含 __init__.py,不得包含 UTF BOM,源码/数据文件不得设置可执行位,第三方 docker-compose image 不得使用 :latest 标签,等等。
在本地运行样式检查作业
clickhouse/style-test Docker 镜像,并在容器化环境中运行该作业。
除 Python 3 和 Docker 外,无需其他依赖。
运行无状态测试
前置条件
- Python 3 (仅需标准库)
- Docker
在本地运行 CI 作业
- 始终按 CI 报告中的显示结果原样引用作业名称 (其中可能包含空格和逗号) ,例如:
"Stateless tests (amd_debug, parallel)"。这样会使用与 CI 相同的 ClickHouse 配置,并运行相同的测试。 - 作业名称中的架构和构建类型 (例如
amd_debug) 是 CI 专用标记。在本地运行时,它们不会产生任何影响——作业会使用你提供的二进制文件,以及你当前所在架构。作业名称只决定 ClickHouse 配置和测试集 (除非用--test覆盖) 。 - 在 CI 中,功能测试会拆分成多个批次,以便更高效地利用资源。例如,
"Stateless tests (amd_debug, parallel)"和"Stateless tests (amd_debug, sequential)"合起来覆盖完整范围:可安全并行运行的测试会并发执行,其余测试则顺序执行。这种拆分通过尽可能提高并行度来缩短 CI 总耗时。若要在本地复现完整测试范围,请同时运行这两个批次。 - 此外还有一个
"Fast test"CI 作业,它会运行一小部分功能测试,以验证 ClickHouse 的基础功能——它使用的是不包含全部可选模块的构建,也是发现回归问题最快的方法。你也可以用同样的方式在本地运行它。将你的 ClickHouse 二进制文件放到默认搜索路径之一 (./ci/tmp/clickhouse、./build/programs/clickhouse或./clickhouse) ——否则该作业会先尝试构建 ClickHouse:
在 CI 作业中运行指定测试
--test 时,该作业会准备一套与 CI 中使用的完全相同的 ClickHouse 配置,但只运行选定的测试:
- 你可以传入多个测试名称:
- 提示:如果任意 ClickHouse 配置都可以,只是需要运行特定测试,请使用别名
functional,而不是完整的 job 名称:
其他自定义选项
--path PATH— ClickHouse 二进制文件的自定义路径。默认情况下,运行器会按顺序在以下位置查找:./ci/tmp/clickhouse、./build/programs/clickhouse、./clickhouse。--count N— 将每个测试重复执行 N 次。--workers N— 覆盖根据机器容量自动计算出的并行工作线程数。
构建检查
在本地运行构建
可用的构建作业
Build (amd_debug)- 带符号的调试构建Build (amd_release)- 优化后的发布构建Build (amd_asan)- Address Sanitizer 构建Build (amd_tsan)- Thread Sanitizer 构建Build (amd_msan)- Memory Sanitizer 构建Build (amd_ubsan)- Undefined Behavior Sanitizer 构建Build (amd_binary)- 不使用 Thin LTO 的快速发布构建Build (amd_compat)- 适用于旧系统的兼容性构建Build (amd_musl)- 使用 musl libc 的构建Build (amd_darwin)- macOS 构建Build (amd_freebsd)- FreeBSD 构建
Build (arm_release)- ARM64 优化后的发布构建Build (arm_asan)- ARM64 Address Sanitizer 构建Build (arm_coverage)- 带覆盖率插桩的 ARM64 构建Build (arm_binary)- 不使用 Thin LTO 的 ARM64 快速发布构建Build (arm_darwin)- macOS ARM64 构建Build (arm_v80compat)- ARMv8.0 兼容性构建
Build (ppc64le)- PowerPC 64 位小端Build (riscv64)- RISC-V 64 位Build (s390x)- IBM System/390 64 位Build (loongarch64)- LoongArch 64 位Build (wasm64)- 通过 Emscripten 构建的 WebAssembly 64 位。Experimental:构建clickhouse二进制文件,并验证clickhouse local可在 Node.js ≥ 24 下执行查询 (该模块也可在浏览器中运行,但 CI 尚未对此进行验证)
<repo_root>/ci/tmp/build 目录下。
注意: 对于不属于“其他架构”类别的构建 (“其他架构”类别使用交叉编译) ,你的本地机器架构必须与构建类型一致,才能按 BUILD_JOB_NAME 的要求生成相应构建。
示例
无状态功能测试
selected tests 结尾的 sanitizer 作业不会运行整个测试套件。
它们只运行针对变更选定的测试:拉取请求新增或修改的测试、该拉取请求中已失败的测试,以及根据覆盖率数据库覆盖已变更代码行的测试。
MSan/WasmEdge 作业仍会运行完整测试套件,因为现有的 Wasm UDF 测试与 MSan 不兼容。完整测试套件也会在 debug 和普通二进制配置中运行;启用 sanitizers 的构建则通过压力测试进行测试,master 分支则会在每种配置下运行完整测试套件。
集成测试
Bugfix validate 检查
压力测试
- 请先修复所有其他测试失败;
- 查看报告,找到服务器日志,并检查其中可能的错误原因。
兼容性检查
clickhouse 二进制文件能否在使用旧版 libc 的发行版上运行。
如果失败,请向维护者寻求帮助。
AST fuzzer
性能测试
回退 CI 回归问题
master 上运行,可能会回退已合并的拉取请求。
该作业会获取 CI 数据库在过去 24 小时内为 master 记录的失败测试,并按测试名称分组,涵盖该测试失败过的所有检查。
同一测试在 debug 和 tsan 构建中失败,视为一次具有单一待查原因的失败;该测试出现过的检查会作为证据纳入调查:破坏某项测试的更改通常会同时导致它在多个构建中失败。
未归属于任何测试的失败,例如构建失败或超时的作业,会被排除:“为什么这个检查失败”并没有可据以回退的单一答案。
测试工具以类似测试的名称记录整个脚本情况的行,例如 Test script failed 或 Server died,也会同样被排除。
在多个 master 提交中失败的测试会交给 AI 智能体处理;该智能体可访问包含完整 master 历史记录的仓库,以及 CI 数据库的只读权限,并回答一个问题:该失败是否由最近合并的拉取请求引入,以及是哪一个。
该智能体不持有 GitHub 凭据,也无法获取凭据 — 它以独立的非特权用户身份运行,环境为空,并且该用户对云凭据端点的访问已被防火墙阻断 — 它在仓库的一次性 clone 中工作,而非作业自身的 checkout 中,因此其得出的任何结论 — 以及可能遗留的任何内容 — 都无法到达 GitHub,除非通过下方的检查。
阈值按提交而非失败行计数,因此,一个在三个构建中失败的错误提交仍只算一次,不会被处理。
它还会按失败模式分别计数:记录的输出会生成指纹,并将易变部分 (地址、时间戳、随机数据库名称) 归一化移除;名称对应两种不同原因的测试 — 一个提交上的回归问题和另一个提交上无关的偶发失败 — 不会被视为重复失败,因此在某一原因单独重复之前,不会进行任何调查。
只有明确无歧义的答案才会触发操作。
当智能体以高置信度报告回归问题,且指定的拉取请求通过安全检查 (在过去三天内合并到 master、本身不是回退、尚未被回退,并且该回退可以干净地应用) 时,该作业会将其回退,立即合并回退而不等待检查,并创建一个标题为 Reapply "..." 的草稿拉取请求来重新引入该更改。
回归问题判定必须同时指明拉取请求及其引入时对应的 master 提交,且两者必须一致:该作业会根据 GitHub 中该拉取请求所产生的合并提交记录核对编号;若二者不一致,则不会采取任何操作。
失败消失后便不会再回退:失败停止后仍会在观察窗口中保留整整一天,因此作业会在回退前再次查询 CI 数据库;如果所有受影响的检查都已在最新的 master 提交上运行过,而其中未出现该失败,则会将其记录为已修复并不作处理。
最新提交以分支自身的历史为准,而不是以检查运行的时间为准 — 一个检查启动较晚的旧提交绝不能被视为新的绿色证据。
采用“未出现”而非“通过”,因为该作业调查的大多数问题没有可供查找的通过行:逻辑错误或卡住的检查会以失败本身的文本记录,并且仅在其发生时记录。
只有某个检查的一次运行完成了其测试,才算该检查已在某个提交上执行过测试:中途终止的运行 — 工具会将其记录为 Test script failed 或 Server died,并与实际产生的测试行并列 — 只运行了部分测试,未必包括这个测试;它没有报告该失败并不能作为证据,而同一检查在同一提交上完成的重新运行则可以。
需要多少次未出现才算数取决于失败发生的频率 — 对于每百次运行才失败一次的问题,几次正常提交没有意义,因此要求未出现的持续时间超过该失败记录中自身两次发生之间最长的沉寂期。
当问题根本无法回答时 — 记录到该失败的某个检查不再以该名称报告,或自失败开始以来的提交历史超过查询返回的范围 — 也会记录该情况,且不会执行回退。
每次运行最多回退两个拉取请求。
如果你的拉取请求被回退:
- 回退拉取请求会说明失败内容,以及为何将责任归于该更改。如果归因错误,请在那里说明并重新引入该更改。
Reapply "..."草稿拉取请求会原样保留你的更改。在该分支上修复失败,将其标记为准备审查,然后让它通过正常的 CI。
checks_investigated 表中,包括未回退任何内容的调查。
这些值会按其在 checks 中记录的原样保留,因此这两个表可以关联起来——直接通过 test_name 关联;对于将多个 checks 行汇集到数组中的列,则使用 has(check_names, check_name) 和 has(commit_shas, commit_sha);对于被归责的拉取请求,则使用 offending_pull_request_number = pull_request_number——作业检查了什么、得出了什么结论以及采取了什么操作的历史记录,均可在 play.clickhouse.com 上查询:
ci/jobs/revert_ci_regressions.py 中实现,并作为 Hourly 工作流的一部分运行。
使用 --dry-run 运行时,会检查并评估所有保护条件,但不会做任何更改:不会创建表、写入行、创建分支、拉取请求或合并;原本将写入的行会改为打印输出。
另一个工作流 .github/workflows/revert_broken_prs.yml 会回退在自身 CI 失败期间合入的合并;两者均使用相同的 revert-<pull request number> 分支名称,因此不会对同一拉取请求执行两次回退。
手动发起的回退也会被考虑在内:如果回退已在 master 上、已存在名为 revert-<pull request number> 或 revert-<pull request number>-<branch> (GitHub 上的 Revert 按钮会创建此类名称) 的分支,或者来自此类分支的拉取请求处于打开或已合并状态,该作业就会停止执行。