常见失败类型全景:构建失败、测试失败、部署失败,如何快速分类定位
先看这张图
所有CI失败归根结底逃不出这三个篮子。你拿不准的时候,看一眼这张图就能对上号。
所有CI失败归根结底逃不出这三个篮子。你拿不准的时候,看一眼这张图就能对上号。
构建失败:最常见也最好定位
我刚开始带CI的时候,十次失败里至少有六次是构建阶段出的问题。说白了,构建失败就是你代码还没进测试环境就挂了。原因很直白——依赖拿不到、语法写错了、或者环境没搭对。
| 子类型 | 典型现象 | 快速定位命令 |
|---|---|---|
| 依赖下载失败 | npm ERR! / Error: Could not resolve dependency | npm ci --prefer-offline 或检查 registry 配置 |
| 编译错误 | TypeScript 报错、GCC 报错、语法错误 | 看编译器第一行错误信息,通常有行号 |
| 环境配置问题 | 找不到 node_modules、JDK 版本不匹配 | node --version; java -version |
我曾经踩过的坑: 有一次构建一直超时,我查了半小时日志才发现是 npm 源被切换到了一个超慢的国内镜像。后来我在 pipeline 开头加了一行
npm config set registry https://registry.npmjs.org/,问题再没出现过。
构建失败的日志特征非常明显——日志开头就会显示 Build stage 或 Stage: build。你只要看到这些关键词,就不用往下翻到测试或部署部分了。直接盯紧依赖解析和编译输出。
测试失败:多数人先怀疑自己代码写错了
构建过了,测试阶段红了。这时候很多人第一反应是“我改的代码有bug”,但其实不一定是。测试失败又分三种情况,你得先看清楚报的是哪类测试。
- 单元测试失败: 通常是单个函数或模块逻辑问题。范围小,好定位。
- 集成测试失败: 模块间交互出问题了,比如 API 返回格式变了、数据库连接超时。我自己经常遇到这种——明明单元测试都过了,一到集成就挂。后来我发现是测试环境里 mock 的数据和真实数据字段对不上。
- 代码质检失败: lint 规则、代码覆盖率不达标。这种最冤,但也好修。
给你的快速区分法:
- 日志里出现
test/unit或*.spec.ts→ 单元测试 - 出现
test/integration或e2e→ 集成测试 - 出现
eslint/coverage/quality gate→ 质检失败
嗯,这里要注意一个细节:很多CI系统会把不同测试阶段的输出混在一起。我建议你在 jest 或 pytest 的运行命令上加 --verbose 参数,这样每个测试用例的结果单独一行,一眼就能看出是哪个文件、哪条用例挂的。
部署失败:环境差异永远是元凶
测试全绿,结果部署红了?别慌。部署失败多半不是你代码的问题,而是环境差异。我遇到过最离谱的一次:本地 Docker 镜像能跑,一推到 staging 服务器就报 exec format error。折腾半天才发现是 CI 服务器是 arm64 架构,而我的镜像编译参数没指定平台。
| 子类型 | 典型表现 | 对症下药 |
|---|---|---|
| 镜像推送失败 | docker push 返回 403 / timeout / connection refused | 检查 registry 登录状态、网络策略、tag 命名规则 |
| 环境差异问题 | 容器内运行时找不到某个动态库;权限不足 | 对比 CI 环境与生产环境的 OS 版本、环境变量、用户权限 |
| 配置文件错误 | kubectl apply 报错 Invalid YAML;环境变量没注入 | 用 kubectl --dry-run=client validate 或 helm template --debug |
我个人的习惯: 在部署步骤之前加一个 “环境预检” 阶段,用脚本把所有关键变量和环境信息打印出来。比如这样:
echo "=== 环境预检 ===
OS: $(uname -m)
Docker info: $(docker info --format '{{.OSType}}/{{.Architecture}}')
Kubeconfig: $(kubectl config current-context)
Env vars: $(env | grep -E 'MY_APP_|DB_|API_')"
这样即使部署失败,日志里也有完整的上下文,不用再重新跑一遍。
三句话总结快速分类逻辑
- 看 Stage 名称:
build→ 构建,test→ 测试,deploy→ 部署 - 看 第一个报错行:依赖、编译、语法 → 构建;断言、mock、覆盖率 → 测试;push、k8s、config → 部署
- 如果还在纠结,就用 排除法:先确认构建是否通过(看 exit code),再确认测试是否全部 green,最后看部署日志。
你记住一个原则就够了:失败发生在哪个阶段,就只看那个阶段的日志。别从头到尾翻一个 5000 行的 build log,浪费时间。我一般先 grep FAILED 或 error,再根据上面的分类去定位具体子类型,10 分钟内基本能锁定根因。