昇腾 HCCL 开源仓 CI 失败诊断与修复指南:从/compile触发到passed的完整闭环
【免费下载链接】hccl集合通信库(Huawei Collective Communication Library,简称HCCL)是基于昇腾AI处理器的高性能集合通信库,为计算集群提供高性能、高可靠的通信方案项目地址: https://gitcode.com/cann/hccl
HCCL(Huawei Collective Communication Library)是 CANN 的核心集合通信库,其开源仓库通过 GitCode 上的 openlibing 平台承载 CI 流水线。本文聚焦该仓库 PR 场景下 CI 失败的系统性定位与修复方法:从失败信息的获取、常见失败模式的对照修复、codecheck 静态规则的处理,到环境坑的排查与已知非阻塞项的判定,最终给出"修复 → 本地验证 → 重触发 → 轮询通过"的完整闭环。读完本文,你将能够独立完成 HCCL 仓任意一次 CI 失败的三步定位(取日志 → grep 根因 → 对照修复),并能区分"代码问题"与"平台/环境抖动"。
一、CI 体系概览:openlibing 平台与任务清单
HCCL 仓库的 CI 由 openlibing 平台承载,触发方式是在 PR 下评论/compile(由贡献流程 skill 的--submit-pr子命令在创建 PR 后自动完成,见 .agents/skills/hccl-contribute/scripts/contribute.py)。一次/compile会拉起如下任务:
| 任务 | 职责 |
|---|---|
| Compile_Ascend_X86 / ARM(_ubuntu24) | 编译验证,对应产物形态由构建脚本决定 |
| codecheck(+ codestyle) | 静态检查,覆盖 C++ 与 Python 代码规范 |
| staticcheck(markdownlint 等) | Markdown 文档格式检查 |
| UT / ST | 单元测试与系统测试 |
| API_Check | 对外 API 兼容性检查 |
| precommit(OAT) | 开源合规检查(许可头、文件类型) |
| PreSmoke | 冒烟验证 |
任务失败后,GitCode 会在 PR 上打ci-pipeline-failed标签;通过则打ci-pipeline-passed。这些标签语义由脚本中的CI_LABEL_RUNNING/PASSED/FAILED常量固化,轮询时还会用saw_running状态机防止旧标签误判(见 .agents/skills/hccl-contribute/scripts/contribute.py 中的--ci-status实现)。
二、三步诊断路径:取日志、grep 根因、对照修复
无论失败发生在哪个任务,诊断都遵循同一套流程:
取失败信息:
pre-commit/markdownlint类任务的日志可从OBS 直链免登录下载——脚本--ci-logs子命令已内置 OBS 日志基地址(OBS_LOG_BASE常量)与流水线链接收集逻辑,一条命令即可拉取:python3 .agents/skills/hccl-contribute/scripts/contribute.py --ci-logs --repo hccl --pr <N> --output-dir ./ci_logs- 其他任务需查看cann-robot 评论里的流水线链接,在浏览器打开任务详情页查看日志。
grep 定位根因行:
grep -E "error|Error|ERROR|FAILED|exit 1" <日志文件>对照下文失败模式表修复;若判定为平台问题(见"已知非阻塞判定"节),则记录后直接重触发。
三、C++ 变更常见失败模式(仓主体语言)
HCCL 仓以 C++ 为主体语言(集合通信算子实现在 src/ops/,通用逻辑在 src/common/),C++ 变更占了 CI 失败的大头。下表是实践中归纳的失败模式、日志特征与修复方式:
| 失败模式 | 特征 | 修复 |
|---|---|---|
| 编译错误(Compile_X86/ARM) | 日志error: | 定位文件行号本地复现:Linux 环境bash build.sh --pkg(命令以仓 AGENTS.md 第 4 节为准);注意 CMake 缓存会掩盖错误,目录结构变更后须清 build 目录重编 |
| clang-format 风格(precommit) | precommit 失败,clang-format hook 报 diff | clang-format -i <文件>(版本须与 .pre-commit-config.yaml 的 rev 一致,当前为 v18.1.8);只对本次改动的文件跑,勿全仓格式化 |
| OAT 许可头(precommit) | 日志License Header Invalid | 新增源文件头加 CANN-2.0 许可头,与仓内已有 C++ 文件逐字节一致(对照 src/ 下任一.cc) |
| OAT 二进制误判(precommit) | Invalid File Type — Content: binary | 文件注释改纯英文 ASCII(中文多字节字符被 chardet 误判) |
| UT/ST 用例失败 | UT_Test/ST_Test 任务失败 | 先看是否环境抖动(见"已知非阻塞判定");真实失败按日志定位用例,本地bash build.sh -u(-s)复现 |
| 链接错误 | undefined reference to | 检查新增符号是否漏加进 CMakeLists.txt 的目标源文件列表;acl* 符号未定义通常是本地 CANN 版本差异,CI 不报则不阻塞 |
| add_subdirectory 被注释 | 特定模块 .o 缺失、chmod 报错 | 恢复被注释的add_subdirectory(BUILD_OPEN_PROJECT 依赖完整目录树) |
| 目录重命名遗漏 | fatal error: xxx.h: No such file | 全仓 grep 旧路径(含 experimental/):CMakeLists、#include相对路径、cmake/、build.sh、classify_rule.yaml、blacklist.txt |
| CMake 缓存掩盖 | 本地增量通过 CI 失败 | rm -rf build*后干净重编验证 |
| codecheck 静态告警 | codecheck 任务失败,详情页G.*规则 | 浏览器打开 cann-robot 评论里的 entryCheckDashCode 链接看告警清单,按规则修复 |
几个关键点结合源码展开:
本地复现命令:仓根 AGENTS.md 第 4 节给出了完整构建矩阵——
bash build.sh --pkg(编译 host 包,默认)、bash build.sh -u(编译并运行 UT)、bash build.sh -s(编译并运行 ST)、--static/--asan/--custom_ops_path=<PATH>/-j64等变体。推送前优先本地验证--pkg+ UT + ST,这是减少 CI 往返成本最有效的手段。clang-format 版本一致性:.pre-commit-config.yaml 中 clang-format hook 固定
rev: v18.1.8,本地clang-format版本必须与此一致,否则格式化结果可能不同。本地跑法:pip3 install pre-commit && pre-commit run --files <改动文件>。OAT 检查:pre-commit 阶段由 .pre-commit-config.yaml 中的
oat-checkhook(repo 为 compliance v1.0.5)执行,检查许可证头与文件类型(禁止二进制/归档文件)。本地也可用bash scripts/oat_check.sh <文件>单独验证,exit=0 才通过。新增源文件的 CANN-2.0 许可头应与仓内已有.cc文件逐字节一致。目录重命名是高频事故:HCCL 源码结构敏感,重命名目录后必须在
CMakeLists.txt、#include相对路径、cmake/、build.sh、classify_rule.yaml、blacklist.txt中同步更新引用,且要覆盖 experimental/ 下的试验性代码(该目录不编入商用版本,但同样是仓库的一部分,遗漏会引发No such file类编译错误)。AGENTS.md 第 8 节也明确要求"涉及src/目录重命名/移动时,同步检查 CMakeLists、测试 include 路径,并清理 build 目录后重新验证"。
四、codecheck 规则与修复模式(新增脚本文件常遇)
codecheck 不仅检查 C++,对 .agents/ 下的 Python 脚本也做全量检查;C++ 告警在 codecheck 任务详情页查看具体规则与行号。以下规则是新增脚本文件时最容易踩中的:
| 规则 | 含义 | 修复模式 |
|---|---|---|
| G.LOG.02 | 禁 print | 用logging(basicConfig + LOG.info) |
| G.FMT.02 | 行宽超 120 | 拆行(按字符数算,中文 1 字符) |
| G.FMT.03 | 嵌套 def 前缺空行 | 函数体内定义函数前补空行 |
| G.FMT.04 | 标点后多余空格 | 删多余空格 |
| G.FMT.05/07 | import 位置/顺序 | import 全部放顶部 |
| G.FNM.03 | 函数参数过多(>5) | 用类(如 NamedTuple)封装参数 |
| G.CTL.03 | if 布尔表达式过多(>3) | 提取中间变量或辅助函数 |
| G.EDV.05 | 外部命令无绝对路径 | shutil.which("git")解析绝对路径 |
| G.VAR.03 | 覆盖外部标识符 | 改名避免覆盖顶部 import |
| G.EXP.04 | 推导式子句过多(>2) | 改普通 for 循环 |
| G.CLS.06 | 类的方法排列(helper 应在测试方法后) | helper 方法移到类定义末尾,或提升为模块级函数 |
| G.NAM.02 | 禁单字符变量名(l/I/o) | 改有含义名(item/entry 等) |
| G.ERR.09 | 同一 except 捕父子类异常(如 HTTPError+URLError) | 只捕父类 |
这些规则在仓库自带脚本中有直接体现:例如 .agents/skills/hccl-contribute/scripts/contribute.py 使用logging.basicConfig+LOG.info输出(对应 G.LOG.02)、用shutil.which("git")解析 git 路径(对应 G.EDV.05)、把 import 全部置于文件顶部(对应 G.FMT.05/07),可作为"通过检查"的参考样例。
五、markdownlint(staticcheck_md_check)
Markdown 文档不合规会在 staticcheck 的 md_check 任务中按行号报出。三个高频规则:
- MD032:列表前缺空行
- MD029:有序列表编号风格不一致
- MD001:标题层级跳跃
修复方式就是按日志行号逐条改格式。HCCL 仓的文档编写还遵循 AGENTS.md 第 6 节的规范(中文文档在docs/zh/、英文在docs/en/、API 文档 PascalCase 命名、环境变量文档 UPPER_SNAKE_CASE 命名),改文档前先对照这些约束可少走弯路。
六、环境坑:本地跑 UT/ST 前先排查(全部实测踩过)
以下环境问题在 CI 中不一定出现,但本地复现 UT/ST 时几乎都会踩到,建议在跑测试前逐项排查:
| 症状 | 根因 | 处置 |
|---|---|---|
编译报acl* 符号 was not declared | master 用了新版 CANN 才有的符号,本机 CANN 落后 | grep <符号> $ASCEND_HOME_PATH/include/acl/acl_rt.h确认后,按 docs/zh/build/build.md 镜像站(最新时间戳目录)下载 toolkit 更新;勿改代码迁就旧 CANN |
UT 的 aicpu 套件报ccl_kernel.json is not a valid real path | 未安装 device kernel:须build.sh --pkg --full并安装到 CANN | 具体为:chmod -R u+w $CANN && bash build_out/cann-hccl_*.run --full --install-path=$CANN;装完重跑,且执行测试的 shell 须已 source set_env.sh |
WSLsource set_env.sh后$ASCEND_HOME_PATH仍为空 | set_env.sh 内read -r需要 stdin,bash -c "source ..."内联方式静默失败 | 用 heredoc(wsl << EOF ... EOF)方式执行并回显校验变量 |
ARM 环境 UT 大面积SIGILL/Illegal instruction(37 个测试 dumped core)或 mockcppVirtual method address should be odd失败 | mockcpp 2.7 的自由函数打桩(MOCKER(<libc函数>)的 trampoline)在 aarch64 + gcc 10 系组合下生成非法指令(gdb 可见被桩函数首指令被udf #0覆盖);仓内 CI 的 ARM 通道用 gcc-14 镜像无此问题,master 代码本身支持 ARM | 工具链限制而非代码问题:用 master 干净 worktree 对照确认后可判定环境性失败;在 gcc-14 环境(CI 或 x86)同用例通过即非阻塞 |
前两个环境坑的处置细节与 docs/zh/build/build.md 的构建/安装章节严格对应:--pkg --full生成 host + device 包,安装命令bash ./build_out/cann-hccl_<version>_linux-<arch>.run --full会将编译产物替换已安装 CANN Toolkit 中的 HCCL 相关软件;而source <CANN安装路径>/cann/set_env.sh && echo $ASCEND_HOME_PATH是环境是否就绪的最小校验。ut 执行建议用bash build.sh -u(LLT 测试入口)。
七、已知非阻塞判定:别在错误的地方浪费力气
并非所有FAILED都是你的代码问题。以下情形已被反复验证为非阻塞,可直接跳过或重触发:
- UT_Test FAILED ≠ 测试失败:日志里
[ PASSED ]/[ FAILED ]只看测试本身;增量覆盖率脚本get_ai_inc_cov.py报错导致的 FAILED 不影响ci_state_passed。先重触发一轮再判断。 - codecheck DEV-CODECI-35002:CI 平台级错误("构建任务执行失败"),与代码无关,重触发即可。
api-check-failed与ci-pipeline-passed并存:后者是 stale 残留标签(聚合流水线成功已含 API_Check),不需要重触发。- 流水线"过期"提示:GitCode 门禁校验流水线 commitID == PR 当前 head;push 新 commit 后旧 passed 失效属正常,重新
/compile即可。
与此配套,--ci-status的状态语义需要理解(见 .agents/skills/hccl-contribute/SKILL.md Step 6):running(运行中)/passed(本轮通过)/failed(本轮失败)/finishing(running 已消失、终态标签未上,稍等再查)/stale(无 running 历史的残留标签,不可作为本轮结论)/not_triggered(从未触发,需评论/compile)/timeout(轮询超时,稍后重查)。每次 push 后必须重新/compile(push 会自动失效旧ci-pipeline-passed),且不要重复触发(会打断在跑轮次并留下误导性 failed 标签)。
八、修复闭环:从失败到passed的完整循环
一次 CI 修复的完整闭环如下:
- 修复:按失败模式表与 codecheck/markdownlint 规则修改代码;
- 本地验证:C++ 变更按 AGENTS.md 构建命令(
bash build.sh --pkg,必要时-u/-s)验证;skill 脚本跑单测(python3 -m unittest discover -s .agents/skills/hccl-contribute/scripts -p test_contribute.py); - commit(
git user.email必须与 CLA 签署邮箱一致,否则 PR 会被打cann-cla/no); - push;
- 评论
/compile(单次,勿重复); - 轮询:
--ci-status --wait(默认 60s 间隔 / 30min 超时); - 直至
passed。
若反复失败且判定为环境/平台问题,可在 master 干净 worktree 上对照复现以佐证"环境性失败"结论(例如 ARM 工具链 SIGILL 场景)。
整套流程在 .agents/skills/hccl-contribute/SKILL.md 中被固化为可独立运行的子流程(Step 6 CI 监控 / Step 7 CI 失败修复),诊断规则即本文所讲的 .agents/skills/hccl-contribute/references/ci-triage.md。掌握这份手册,配合--ci-logs/--ci-status两个命令,即可在 HCCL 仓的贡献流程中高效地"把 CI 跑绿"。
【免费下载链接】hccl集合通信库(Huawei Collective Communication Library,简称HCCL)是基于昇腾AI处理器的高性能集合通信库,为计算集群提供高性能、高可靠的通信方案项目地址: https://gitcode.com/cann/hccl
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考