Files
TARE-Learn/slidev/pages/day6/m4-ci-failure-loop.md
T
smart 67837df8d0 docs: 更新TRA编程培训课程材料、课件与AI技能交付包
- 新增全套考试卷、评估卷、参考答案与考试培训包模板
- 修正slidev培训课件:调整模块标题、链路图缩放,替换工单示例为通用业务对象
- 修正课堂红线表述为证据红线,将小组作业调整为个人作业要求
- 新增权限、状态流转、审计日志、看板指标四类可复用业务规则块
- 整理AI工程技能交付包,迁移旧资产至客户专属交付包并统一术语
- 新增考试输出模板与TRAE使用记录文档
2026-08-08 11:00:36 +08:00

285 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 模块 4:CI 失败日志分析
<div class="mt-6 text-sm">
CI 失败时,首先要判断失败来自代码、配置、依赖还是运行环境。
TRAE 可提取日志中的直接错误、关联改动和缺失证据;修复前仍要先确认失败来源。
</div>
<div class="grid grid-cols-5 gap-3 mt-8 text-sm">
<div class="p-3 rounded-xl bg-blue-500/10 border border-blue-500/30">代码</div>
<div class="p-3 rounded-xl bg-emerald-500/10 border border-emerald-500/30">测试</div>
<div class="p-3 rounded-xl bg-amber-500/10 border border-amber-500/30">配置</div>
<div class="p-3 rounded-xl bg-red-500/10 border border-red-500/30">依赖</div>
<div class="p-3 rounded-xl bg-purple-500/10 border border-purple-500/30">环境</div>
</div>
<!--
逐字稿:CI 失败时,最危险的反应是只看最后一行然后立即改代码。首先要判断失败属于代码、测试、配置、依赖还是运行环境,因为不同来源对应不同证据和处置边界。分类的目的不是贴标签,而是确定下一步该读取什么材料。
日志很长时,不要只看最后一行。先按失败来源分类,才能避免把环境或依赖问题误改成业务代码问题。
-->
---
# 先按失败来源分类
<div class="mt-5 text-xs">
| 失败来源 | 常见信号 | 首先核对的材料 | 处理边界 |
|---|---|---|---|
| 代码与类型 | 编译、lint、类型报错指向具体文件 | diff、调用方、类型定义 | 只修改能解释错误的实现 |
| 测试断言 | 预期与实际结果不同 | 测试用例、业务规则、测试数据 | 不能只为通过而改断言 |
| 构建配置 | 脚本、工作流、环境变量缺失 | package/pom、workflow、项目规则 | 先确认配置是否属于本次改动 |
| 依赖解析 | 版本冲突、锁文件不一致、制品缺失 | lockfile、依赖树、仓库配置 | 区分项目依赖与制品服务异常 |
| Runner 与环境 | 权限、磁盘、网络、系统工具失败 | Runner 日志、环境配置、重试结果 | 不把环境故障归因到源码 |
</div>
<div class="mt-6 p-3 rounded-xl bg-red-500/10 border border-red-500/30 text-sm">
分类不是为了快速贴标签,而是为了确定下一份该看的证据。
</div>
<!--
逐字稿:一份日志可能出现很多错误,但先找最早阻断流水线的直接错误。然后根据错误信号核对 diff、测试、构建配置、依赖信息或 Runner 日志,判断它来自哪一层。环境和依赖故障没有代码关联证据时,不应推动业务代码修改。
同一份日志可能同时出现多个错误,但应先定位最早阻断流水线的直接错误,再判断其来源。环境或依赖异常通常不应触发业务代码修改。
-->
---
# 日志必须和 diff 一起读
<div class="mt-5 text-xs">
| 日志现象 | 与 diff 的关系 | 正确结论 |
|---|---|---|
| 新增类型错误指向本次修改文件 | 直接命中新增或改动行 | 优先检查该改动与接口契约 |
| 测试失败在相邻模块,diff 未触及该模块 | 关联尚未建立 | 标记待确认,不把失败直接归因于本次改动 |
| 依赖下载失败,代码尚未进入编译 | 没有代码执行证据 | 按环境或依赖问题排查 |
| 同一失败在未改动分支也可复现 | 与本次 diff 无关 | 记录为基线问题或外部问题 |
</div>
<div class="mt-6 grid grid-cols-3 gap-3 text-sm">
<div class="p-3 rounded-xl bg-blue-500/10 border border-blue-500/30">日志给出直接错误</div>
<div class="p-3 rounded-xl bg-amber-500/10 border border-amber-500/30">diff 说明影响范围</div>
<div class="p-3 rounded-xl bg-emerald-500/10 border border-emerald-500/30">两者共同支持根因</div>
</div>
<!--
逐字稿:日志告诉我们直接报错,diff 告诉我们本次改动触及了什么,两者结合才能支持根因判断。错误在相邻模块但 diff 没有触及,或者在未改动分支也能复现,都只能说明需要继续确认。AI 可以建立关联,但关联本身不能直接当成因果。
模型擅长关联日志与变更,但关联不等于因果。只有错误位置、改动范围和执行阶段能互相印证时,才可以形成较强根因判断。
-->
---
# 代码修复与环境处置要分开
<div class="mt-5 text-xs">
| 场景 | 代码侧动作 | 环境侧动作 | 不应做的事 |
|---|---|---|---|
| 类型或编译失败 | 修正实现、类型或调用契约 | 保持环境不变 | 顺手升级无关依赖 |
| 测试预期冲突 | 复核业务规则和测试数据 | 保留失败记录 | 只改断言让流水线通过 |
| 依赖解析失败 | 核对锁文件与版本声明 | 核对制品源、缓存和网络 | 修改业务逻辑 |
| Runner 权限或资源不足 | 不改项目源码 | 调整 Runner 或重试并留存结果 | 误报为代码缺陷 |
</div>
<div class="mt-6 p-3 rounded-xl bg-amber-500/10 border border-amber-500/30 text-sm">
修复范围必须和失败来源一致;CI 通过也不应掩盖未验证的业务风险。
</div>
<!--
逐字稿:看到流水线失败并不等于业务代码一定有问题。类型和编译失败应回到实现与调用契约,依赖和 Runner 问题则需要回到制品源、缓存、网络或运行环境。代码修复和环境处置要分别记录、分别验证,不能用改业务逻辑来掩盖环境故障。
这张表的目的,是防止“看到 CI 红了就改代码”。代码修复和环境处置的证据、责任边界、验证方式都不同,应分别记录。
-->
---
# 公务用车模块:已执行的定向测试门禁
<div class="mt-5 text-xs">
```bash
mvn -pl jeecg-boot-module/jeecg-module-officialvehicle -am \
-DskipTests=false \
-Dtest=OfficialVehicleDispatchServiceImplTest \
-Dsurefire.failIfNoSpecifiedTests=false test
```
| 项目事实 | 该命令支持的结论 | 不能外推的结论 |
|---|---|---|
| 公务用车模块启用了 Maven Surefire 测试 | 模块依赖与指定 Service 用例能够被执行 | 接口、数据库、浏览器与审计链路已验证 |
| 用例传入全空白取消原因 | `cancel` 会在状态写入前拒绝空白原因 | 非空正常取消路径已经回归 |
| 2026-08-06 记录为 `BUILD SUCCESS`,1 项用例零失败 | 本次定向 Service 验证通过 | 全模块或生产可发布 |
</div>
<div class="mt-6 p-3 rounded-xl bg-emerald-500/10 border border-emerald-500/30 text-sm">
可执行命令、实际结果和结论边界一起保存,才构成一项可复核的质量门禁证据。
</div>
<!--
逐字稿:这里不是假设一条流水线,而是使用本项目已经执行过的 Maven 命令。它定向运行公务用车模块中的 Service 测试,验证全空白取消原因会在状态写入前被拒绝。记录中的 BUILD SUCCESS 只支持这一项定向验证;接口、数据库、浏览器和审计链路没有执行,就不能写成已通过。
这类命令可以成为 CI 的测试门禁,但是否由某条流水线调用,仍应以项目实际工作流配置为准。证据强度取决于实际执行的命令和结果,而不是门禁名称。
-->
---
# 真实失败案例:Maven 本地仓库无写入权限
<div class="mt-5 grid grid-cols-2 gap-4 text-xs">
<div>
```text
[WARNING] Failed to write tracking file
$HOME/.m2/repository/.../resolver-status.properties
[ERROR] java.io.FileNotFoundException
(Operation not permitted)
[ERROR] BUILD FAILURE
```
</div>
<div>
| 判断项 | 本次结论 |
|---|---|
| 首个直接错误 | Maven 更新本地仓库跟踪文件时被系统拒绝 |
| 失败来源 | 本地环境 / 文件权限 |
| 与业务 diff 的关联 | 未建立源码关联证据 |
| 正确处置 | 恢复 Maven 仓库写入条件,保留日志后重跑 |
| 不应做的事 | 修改派车 Service、测试断言或业务状态逻辑 |
</div>
</div>
<div class="mt-6 p-3 rounded-xl bg-red-500/10 border border-red-500/30 text-sm">
构建失败发生在依赖元数据写入阶段时,不能据此推断公务用车业务代码存在缺陷。
</div>
<!--
逐字稿:这段 Maven 失败记录来自实际保留的训练材料。最早的直接错误是本地 .m2 仓库的 resolver-status.properties 无法写入,错误信号是 Operation not permitted。它发生在 Maven 处理依赖元数据时,没有指向派车 Service 或测试源码,因此结论应当是环境和文件权限问题,而不是修改业务代码。
正确做法是保留原始日志,恢复 Maven 仓库的写入条件后重跑同一命令。CI 排障的价值就在于把“红色结果”分解为可被证据支持的处置边界。
-->
---
# CI 分析任务上下文契约
<div class="mt-5 text-xs">
```md
请分析以下 CI 失败日志。
输入材料:CI 日志、相关 diff、package/pom/workflow 配置、锁文件、项目 rules。
请输出:
1. 首个失败阶段与原始错误;2. 失败来源分类;
3. 与 diff 的关联证据;4. 有依据的根因判断;
5. 需要查看的文件或环境信息;6. 候选处置方案;7. 验证命令;
8. 是否适合沉淀为规则或检查清单。
要求:先解释失败原因,再给方案;不能只根据最后一行日志下结论;
区分代码修复与环境处置;证据不足时标记待确认。
```
</div>
<!--
逐字稿:让 TRAE 分析 CI 时,输入至少包含失败日志、相关 diff、构建配置和项目规则。输出先给出最早失败阶段和原始错误,再说明失败来源、关联证据、候选处置与验证命令。证据不足时必须标记待确认,不能依据最后一行日志直接给出修复结论。
输入尽量同时包含日志、相关 diff、构建配置和项目规则。没有这些上下文,模型很难区分源码、依赖和环境问题。候选方案必须落到具体文件或可复现的处置步骤。
-->
---
# CI 修复记录
<div class="mt-5 text-xs">
| 字段 | 内容 |
|---|---|
| 失败阶段 | lint / typecheck / test / build / dependency / environment |
| 原始错误 | 日志中的直接报错,不改写 |
| 失败来源 | 代码、测试、配置、依赖、Runner 或外部服务 |
| diff 关联 | 命中改动 / 无关联证据 / 待确认 |
| 根因 | 支持判断的日志、配置或代码证据 |
| 处置范围 | 代码修复或环境处置,涉及哪些位置 |
| 验证命令 | 本地或 CI 重新执行命令 |
| 结果 | 通过 / 未通过 / 待确认 |
| 资产沉淀 | rule / checklist / 任务上下文契约 / example / 不沉淀 |
</div>
<!--
逐字稿:CI 修复记录要把原始错误、失败来源和根因分开写。原始错误来自日志,失败来源是分类判断,根因需要由日志、配置或代码共同支撑。这样沉淀的是下一次诊断的方法,而不会把一次偶然有效的修复动作误当成通用结论。
记录要区分原始错误、失败来源和根因。这样下次面对相似日志时,才能复用诊断方法,而不是错误复用某一次的修复动作。
-->
---
# CI 质量门禁分别覆盖什么?
<div class="mt-5 text-xs">
| 门禁 | 作用 | 不能替代什么 |
|---|---|---|
| lint | 保证基础格式和规范 | 业务规则审查 |
| typecheck | 提前发现接口和类型不匹配 | 运行时行为验证 |
| unit test | 保护核心逻辑 | 完整集成链路 |
| coverage | 发现测试覆盖缺口 | 测试质量判断 |
| manual checklist | 覆盖权限、审计、状态和页面验收 | 可重复的自动化验证 |
</div>
<div class="mt-6 p-3 rounded-xl bg-emerald-500/10 border border-emerald-500/30 text-sm">
质量门禁不是越多越好,而是每道门禁都要清楚自己覆盖和不覆盖什么。
</div>
<!--
逐字稿:每一道 CI 门禁只覆盖一类问题。lint 不能替代业务规则审查,类型检查不能替代运行时验证,单元测试也不能替代完整集成链路和人工验收。质量门禁的价值不在数量,而在于每一项通过时,我们知道它能支持什么结论、又不能支持什么结论。
不同门禁支撑不同强度的结论。重点是避免以某一种通过结果替代全部质量判断。
-->
---
# 一条 CI 结论应当写清什么?
<div class="mt-5 text-xs">
| 信息 | 说明 |
|---|---|
| 失败阶段 | lint、类型检查、测试、构建、依赖或环境 |
| 原始错误 | 保留日志中的直接报错,不提前改写 |
| diff 关联 | 说明是否命中本次改动及依据 |
| 根因判断 | 说明对应的配置、代码或环境依据 |
| 处置范围 | 只指出确实需要调整的位置 |
| 验证方式 | 使用可重复的命令或 CI 结果确认 |
| 结论边界 | 证据不足时明确标记待确认 |
</div>
<div class="mt-6 p-3 rounded-xl bg-red-500/10 border border-red-500/30 text-sm">
先区分直接错误、失败来源和根因,再决定是否修改代码。
</div>
<!--
逐字稿:一条可审查的 CI 结论需要让读者回到原始材料复核。它应说明失败阶段、原始错误、与 diff 的关系、根因依据、处置范围和重跑验证方式。证据还不足时,最准确的结论就是待确认,而不是猜一个看似完整的原因。
一条可审查的 CI 结论,需要让读者回到日志、diff、配置或重跑结果中核对。结论没有证据时,应保留为待确认项。
-->