前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
返回 AI 情报前线
All News · 全部资讯9258
  • 2026 年 GPU 选型指南:H100 与 A100 成本效益对比
  • AI Agent 测试方法论:从单元测试到混沌工程
  • AI Skill跑通一次不算测试
  • 用Milvus+Ollama自建私有RAG实战
  • 上下文窗口不是记忆:AI Agent 记忆机制的深层误解
  • 上下文窗口不是记忆:AI Agent 记忆机制的深层误解
  • 智谱 GLM-5.3 发布:编程能力最强开源模型,Terminal-Bench 得分暴涨 5 倍
  • LLM 可解释性实战:用 Sparse Autoencoder 破解 Transformer 黑盒
  • Gemini 3.7 Flash发布,Google AI开发重回焦点
  • AI编程时代:系统设计比写代码更重要
  • 智谱GLM 5.3正式发布,推理能力与效率进一步提升
  • 十七行Python检查LLM网关是否抽成
  • LLM选型矩阵:按功能挑最便宜可靠模型
  • Figma MCP 做 UI 代码:截图只能验证布局,数值必须从节点读取
  • 苹果在中国训练本地AI模型,集成阿里千问
  • Obsidian Skills:让 AI 编程助手读懂你的笔记库
  • 一行Python代码构建OpenAI兼容网关,支持多模型代理
  • AI 生成数据库迁移的正确姿势:先在临时库重放验证
  • holaOS:一个空间运行任意 Agent,共享记忆
  • AI 代码补丁三验 Loop:合同、执行、回归
  • 用 AI 给 CI 失败先分类再读日志
  • AI 时代面试已失效:会做题≠会工程
  • DeepSeek V4-Pro 对 token 上限参数置若罔闻
  • Unsloth Desktop:本地一键跑大模型和训练,集成Claude Code/Codex/MCP
  • AI 在自动化工作流中的四种核心角色
  • ChatGPT工作原理深度解析
  • 通过单一Chatbot API接入三个降级模型:JSON Schema校验与回退策略
  • LLM 工单分类实战:用 JSON Schema 控制输出+重试+成本计量
  • Node.js 应用添加 OpenAI 兼容模型降级方案
  • 成功 AI 产品中反复出现的 3 种 Agent 模式
  • GitHub Copilot 8月10日更新:便携插件与Agent工作流
  • 未提供的上下文会被模型自行补全——这是安全漏洞的根源
  • 从零构建推理小模型:SupraLabs 推理语料流式微调实战
  • 金额不能用浮点数:AI演示里那个隐藏的经典Bug
  • Google 发布 Gemini 3.7 Flash:编程能力提升33%,$0.75/1M tokens
  • 何时该用LangGraph而非简单Tool-Calling
  • AI 生成代码:看起来对≠真的对
  • AI Agent 实战:七个生产环境失败模式及修复方案
  • Cerebras + OpenAI 实现 750 tokens/s 推理
  • 架构文档约束失效,AI 编程代理的隐性风险
  • AI编程工具成团队依赖瓶颈:Copilot用尽后的协作困境
  • OpenAI 收购 Astral:Python 基础设施可能被重构
  • AI 蠕虫已真实存在:多伦多大学 self-replicating 攻击研究解析
  • DeepSeek V4:稀疏注意力实现低成本百万 token
  • 别把巨型 OpenAPI spec 一股脑塞给 AI Agent
  • Biome:56 倍速替代 ESLint+Prettier 的 Rust 工具链
  • 为何每个AI Agent不应重复学习你的数据模型
  • DeepSeek Harness预览:模型评测与部署框架完整指南
  • 零结果不等于不存在:数据库空结果的严谨表达
  • AI 改了查询语句,但没改变指标的业务语义
  • Mac版ChatGPT推出Computer History,取代截图记忆
  • 已加载 51 / 9258
8.0
热点
AI SCORE
编程提效2026-08-14 12:16

用 AI 给 CI 失败先分类再读日志

dev.to · AI#CI/CD#AI分类#MonkeyCode
Editor brief · 编辑速览

在团队频道收到 CI 红色警报后,先用免费模型+LMonkeyCode 对失败进行分类(infra/code/flake/test_logic),再决定读哪条日志。

文章思维导图
Knowledge map
拖拽缩放
Full translation

完整中文译文

CI 因为与你的改动无关的原因变红。共享 runner 上的端口冲突、期望时钟走动的测试、缺失的依赖镜像、过期的缓存、终于抓到真实回归的断言。当每个失败都以原始堆栈跟踪的形式涌入频道时,昂贵的不是失败本身;而是决定打开哪条日志。在任何人读一行日志之前,先做一个小小的分类步骤就可以整理好队列。

下面的脚本使用 MonkeyCode 的免费模型访问和免费服务器选项,所以你可以在定时任务中运行它而无需添加基础设施。披露:本文是作为 MonkeyCode 产品推广的一部分撰写的。

一张分诊卡,不是根因裁决

目标不是解释失败。目标是生成一张分诊卡,包含三个字段,帮助你决定下一步读什么:类别(category)、置信度(confidence)、建议的下一步(suggested_next_step)。

用这些类别开始:

  • infra:网络、端口、超时、磁盘、内存、权限、连接被拒绝
  • code:导入错误、语法错误、缺失模块、配置解析、构建失败
  • flake:竞态、顺序依赖、重试成功、时间或时钟敏感
  • test_logic:断言不匹配、期望值改变、无效 fixture
  • ambiguous:日志截断、通用错误、无堆栈跟踪、无关噪声

模型提出其中一个标签只是一份草稿,不是最终决定。脚本将这份草稿与一些你已经知道的关键词的确定性提示合并,然后打印出一张卡片,让你在打开完整日志之前扫一眼。

可复用的分诊脚本

脚本接受一个包含失败 CI 日志片段的目录,对每个文件的最后 4000 个字符调用模型,并添加正则提示,这些提示只能提升关注级别,永远不会降级。将 classify_log 存根替换为你有权限访问的端点。

# flake_triage.py
import json
import re
from dataclasses import dataclass
from pathlib import Path

CATEGORIES = {
    "infra": "network, port, timeout, memory, permission, connection refused",
    "code": "import error, syntax error, missing module, config parse, build failure",
    "flake": "race, order dependence, retry works, timing, clock, sleep",
    "test_logic": "assertion mismatch, expected value changed, invalid input fixture",
    "ambiguous": "log truncated, unrelated failure, no stack, generic error",
}

PROMPT = """Classify this CI failure log excerpt.
Categories: infra, code, flake, test_logic, ambiguous.
Return JSON with fields:
category, confidence (0-1), reason (one sentence), suggested_next_step (one sentence).
Do not claim a specific root cause beyond the log.
LOG:
{log}
"""

def classify_log(log: str) -> dict:
    # Replace with the model endpoint available to you.
    raise NotImplementedError

def rule_hints(log: str) -> dict:
    hints = []
    if re.search(r"connection refused|timed out|address already in use", log, re.I):
        hints.append("infra")
    if re.search(r"ImportError|ModuleNotFoundError|SyntaxError", log):
        hints.append("code")
    if re.search(r"flaky|retry|race|deadlock|eventually", log, re.I):
        hints.append("flake")
    return {"rule_hints": hints}

def triage_one(failure_blob: str) -> dict:
    model = classify_log(failure_blob)
    hints = rule_hints(failure_blob)
    # Model output is a draft; rule hints can add a competing hypothesis,
    # but they never override a lower-confidence label.
    if model.get("confidence", 0) < 0.6:
        model["suggested_next_step"] = "read the full log before deciding"
    return {"model": model, "rule_hints": hints}

def main(log_dir: Path):
    logs = sorted(log_dir.glob("*.log"))
    for log_path in logs:
        text = log_path.read_text(errors="ignore")[-4000:]
        result = triage_one(text)
        m = result["model"]
        print(f"{log_path.name}\t{m.get('category')}\t{m.get('confidence')}")
        print(f"  reason: {m.get('reason')}")
        print(f"  next:   {m.get('suggested_next_step')}")
        if m.get("confidence", 0) < 0.5 or result["rule_hints"]:
            print(f"  hints:  {result['rule_hints']}")

if __name__ == "__main__":
    main(Path("ci_logs"))

rule_hints 函数存在的原因是处理那些你已知会在环境中反复出现的词模式。如果日志说 address already in use,模型可能高置信度地称之为 infra,也可能低置信度地称之为 ambiguous。但无论如何,提示会保持可见,这样读卡片的人就可以挑战这个标签。

不是每个模型标签都值得同等的响应。用这张决策表把卡片转化为行动:

这张表故意保守。模型说 flake 并不意味着有权将该 issue 关闭为 flaky。它是在归咎责任之前测试确定性的提示。

用最近二十个失败来校准它

取二十个你已经知道真正根因的已关闭 CI 失败。运行脚本对保存的日志进行分类,并将提议的类别与真实情况对比。按类别计算精确率,而不只是总体准确率。你经常会发现 infra 和 code 很容易分类,因为它们的特征很明显,而 flake 和 test_logic 则很嘈杂。这个本地数字比任何外部基准都更有用,因为它反映了你自己的技术栈、runner 镜像和测试习惯。

当你更换模型端点时,重新运行同样的校准集。不同的指令调优模型即使在类别上达成一致,也会在置信度上产生分歧,而且你从一个端点学到的置信度阈值可能无法干净地迁移到另一个端点。

尾日志是有损的。如果只传递最后 4000 个字符,一个原因出现在前 500 行的失败看起来可能像是 ambiguous。

类别会重叠。竞态条件可能表现为连接被拒绝,缺失依赖可能看起来像 test_logic 失败。卡片是用来排序注意力的,不是用来宣称根因的。

脚本默认不访问你的测试代码或 diff。这是刻意的:它应该保持廉价和低上下文。如果你想获得更好的标签,只添加失败的测试名称和 diff 摘要,而不是整个仓库。

日志可能包含环境名称、文件路径和秘密。将它们发送到第三方模型端点是一个数据处理决策,需要与分享任何其他 CI 产物一样的审查。

不要基于模型标签自动关闭、自动重试或自动分配。此工作流中唯一的自动部分是为人审阅而进行的列表排序。

谁应该跳过此工作流

有合规或隐私规则禁止将 CI 日志发送到外部模型端点的团队。

小团队——每个红构建已经被同一个人阅读;添加分类反而是繁文缛节而非杠杆。

CI 非常稳定、flake 很少见、失败类别从文件名就能明显看出的仓库。

期望一步到位完成全自动根因分析或自动修复的团队。此工作流给你的是阅读顺序,不是修复方案。

从五个最近的失败 job 和每个的一行总结开始。重点不是减少日志;而是用更好的顺序去读它们。如果你已经通过 MonkeyCode 获得了免费模型访问,将脚本指向 CI 产物在一个免费服务器上,让它起草第一遍;人类仍然拥有最终决定权。

Original source

本文由 AI 翻译整理自 dev.to · AI,原文版权归原作者所有。

阅读英文原文
上一篇
AI 代码补丁三验 Loop:合同、执行、回归
下一篇
AI 时代面试已失效:会做题≠会工程