前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
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 · 全部资讯9321
  • AI API成本削减97.5%实战:绕过中间商反而更贵
  • 14款MCP服务器上下文窗口消耗实测
  • Bedrock多Agent文档分类方案实战
  • Jumio实时特征存储架构:亚100ms欺诈检测
  • failproof AI将编码Agent策略执行从700ms压至0.7ms
  • Claude Code周限额明日大幅下调三分之一
  • MCP Gateway: 统一多MCP服务器的架构方案
  • 实测:选对模型把我AI API账单削减90%
  • Agentic AI延迟问题:算力堆叠不是答案
  • NoWreck:验证AI代码修改是否属实的工具
  • AI Agent成为新型攻击面:自我复制威胁研究
  • 多模型API退出测试:成本账本才是选型关键
  • 为什么不能只用Claude做所有事
  • Axonius多租户AI Agent隔离方案实践
  • 用LiteLLM将Claude Code路由到DeepSeek节省成本
  • Claude Code支持AGENTS.md跨工具标准配置
  • Coding Agent 账单省 50-70%:利用 sticky routing 保住 Prompt Cache 命中
  • AI Agent 为何还在用 while(true) 循环——工程陷阱深度剖析
  • SEO Agent 选 MCP 还是 REST?一份实用决策框架
  • SGLang深度解析:如何高效服务DeepSeek-V4-Pro
  • FlakeFixer: 用Agent自动分析Flaky Test
  • AI编码Agent记忆系统设计的四个教训:删除不是过期
  • 盲人开发者为视障群体打造AI描述应用ScribeMe
  • AI代码审查员的验证悖论:声称完成≠真正完成
  • LLM API多租户安全清单:tenants-safety essential
  • AI Agent不应持有你的钥匙:权限最小化原则
  • Claude 多智能体系统上演自复制恶意软件攻防战
  • MCP Server 开发避坑指南:工具描述比 TypeScript 更难
  • 生产级 Solana Agent 交易生命周期深度解析
  • 5分钟让AI助手读懂你的代码库
  • 用Python构建AI简历筛选器
  • Agent上下文满了该丢什么:长对话记忆管理实战
  • Warp推出Factories:一站式AI软件开发工厂基础设施
  • AI Agent试点到生产:成本暴涨700倍的教训
  • Cursor发布Origin功能:AI编程上下文管理
  • TryHackMe 提示词注入 CTF 实战攻略
  • 面向 Agent 的运维队列:失败自动转Ticket
  • 四个静默失败的 CI 检查:它们都是绿的,但什么都没做
  • AI 编码工具会读取 .env:本地 DLP 代理 Anonmyz 在prompt边界截流
  • Google 开源 SAM:零配置的 AI Agent P2P 发现与调用网络
  • Cursor Skills完全指南:格式规范与跨Agent迁移实测
  • OpenAI Codex Skills规范详解:目录结构与官方文档未记载的细节
  • 用Gitea自建Claude Code内部插件市场,团队Skill统一分发
  • Claude Skills规范深度解读:从格式到团队协作
  • 2026年LLM应用架构实战:摆脱if/else链式判断
  • Anthropic CEO:AI天然趋向集中,开源只是转移权力
  • 微软 Copilot 隐藏参数漏洞可被利用窃取密码
  • LangChain 揭示:Agent 效果不佳时换模型是误区,换 Harness 才是关键
  • 三阶段工作流让 AI Agent 保持精准:Research-Plan-Implement
  • 小米MiMo桌面应用即将上线,AI编程助手6月已开源
  • Agent成熟度记分卡:追踪AI Agent可靠性的五个核心维度
  • 已加载 51 / 9321
8.0
热点
AI SCORE
编程提效2026-08-18 23:56

FlakeFixer: 用Agent自动分析Flaky Test

dev.to · AI#AI编程#CI/CD#测试工程
Editor brief · 编辑速览

用PyGithub抓取失败CI日志、LangChain+Pydantic分类失败原因、自动创建带修复建议的GitHub Issue的完整Pipeline。

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

完整中文译文

Flaky tests 是开发者效率的隐形杀手。它们随机失败、浪费数小时调试时间、且蚕食 CI 的信任度。作为一名开发者,我有过太多次这样的早晨:盯着 GitHub Actions 日志,试图判断一个失败是真正的 bug 还是仅仅是一次网络抖动。于是我构建了 FlakeFixer——一个监控 GitHub Actions workflow、提取失败日志、用 AI Agent 对根因进行分类(竞态条件、网络超时、基础设施抖动、依赖 flake)、并自动创建 GitHub Issue(附带通俗易懂的解释和建议的缓解方案)的工具。在这篇文章中,我将带你了解架构、技术栈,以及如何构建你自己的类似工具。

问题

Flaky tests 是那些在不修改任何代码的情况下随机通过和失败的测试。它们在 CI pipeline 中很常见,尤其是当测试依赖外部服务、时间、或共享状态时。手动调试 flaky tests 是痛苦的,因为:

  • 日志巨大且嘈杂。
  • 真正的错误往往埋藏在堆栈跟踪中。
  • 根因可能是基础设施的小故障,而不是代码 bug。

我想要一个能够自动完成以下工作的系统:

  • 抓取失败的 CI runs。
  • 提取相关的日志片段。
  • 用 LLM 推理失败原因并对其分类。
  • 将简明的分析发布为 GitHub Issue。

这正是 FlakeFixer 所做的事。

整体架构

系统有三个主要组件:

  • Data Ingestion — Python 脚本,使用 PyGithub 列出失败的 workflow runs 并下载日志。
  • Agentic Analysis — LangChain + Pydantic output parser,对失败进行分类并生成缓解建议。
  • Reporting — 自动创建带有分析结果的 GitHub Issues,按 flake 类别打标签。

构建 Flaky Test Lab

在构建这个工具之前,我需要一种能够按需生成 flaky failures 的方式。我创建了一个配套仓库 ci-flake-lab,故意产生几种类型的 flaky failures:

  • Race condition — 当线程访问共享列表时失败的测试。
  • Network timeout — 尝试连接不可路由 IP 的测试。
  • Infrastructure blip — 随机抛出 OSError: No space left on device 的测试。
  • Unknown — 不能干净地归入已知类别的失败,用于测试 agent 如何处理歧义。

我使用 GitHub Actions 环境变量来切换每次运行的 flake 类型,并使用 matrix 策略让多种 flake 类型并行运行。这给了我源源不断的失败日志来测试 pipeline——你可以在仓库中看到 resulting auto-filed issues,每个都带有 flaky-test 标签及其特定类别。

[Insert your screenshot of the ci-flake-lab issues list here]

以下是 workflow YAML:

name: Flake Farm
on: [push, workflow_dispatch]

jobs:
  flaky-tests:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        flake-type: [RACE, NETWORK, INFRA, UNKNOWN]
      fail-fast: false
    env:
      FLAKE_${{ matrix.flake-type }}: 1
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.10'
      - run: pip install pytest
      - run: pytest test_app.py -v

Data Ingestion with PyGithub

ingestion 模块使用 PyGithub 进行认证并列出失败的 workflow runs,然后下载日志归档并提取原始文本。

from github import Github
import requests, zipfile, io

class IngestionPipeline:
    def __init__(self, token, repo_name):
        self.gh = Github(token)
        self.repo = self.gh.get_repo(repo_name)

    def get_failed_runs(self, workflow_id, max_runs=20):
        workflow = self.repo.get_workflow(workflow_id)
        return list(workflow.get_runs(status="failure"))[:max_runs]

    def download_logs(self, run_id):
        run = self.repo.get_workflow_run(run_id)
        headers = {"Authorization": f"token {token}"}
        resp = requests.get(run.logs_url, headers=headers, allow_redirects=True)
        with zipfile.ZipFile(io.BytesIO(resp.content)) as zf:
            full_log = ""
            for name in zf.namelist():
                if name.endswith(".txt"):
                    full_log += zf.read(name).decode("utf-8", errors="replace") + "\n"
        return full_log

这给了我原始日志文本。在完整版本中,我还裁剪日志到最相关的部分(最后 100 行以及包含 FAILED 或 ERROR 的行),以将 LLM prompt 保持在 token 限制内。

The Agentic Analysis Engine

对于 AI agent,我使用 LangChain 配合 Pydantic output parser 来强制 LLM 返回结构化 JSON。这确保我能够可靠地解析输出并用它来创建 issues。Prompt 要求 LLM 对失败进行分类,并提供解释和缓解建议。

from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain.output_parsers import PydanticOutputParser
from pydantic import BaseModel, Field

class FlakeAnalysis(BaseModel):
    flake_category: str = Field(description="race_condition, network_timeout, infrastructure_blip, unknown")
    explanation: str
    mitigation: str
    confidence: float

class FlakeAnalyzer:
    def __init__(self):
        self.llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.1)
        self.parser = PydanticOutputParser(pydantic_object=FlakeAnalysis)

    def analyze(self, log_snippet):
        prompt = ChatPromptTemplate.from_template("""
You are a flaky test analyst. Given the CI failure log, classify the root cause.
Log:
{log}

{format_instructions}
""")
        formatted = prompt.format_prompt(
            log=log_snippet[:6000],
            format_instructions=self.parser.get_format_instructions()
        )
        response = self.llm.invoke(formatted.to_messages())
        return self.parser.parse(response.content)

以下是 agent 返回的示例:

{
  "flake_category": "network_timeout",
  "explanation": "The test attempted to connect to an external service but timed out. This is likely an infrastructure or network issue, not a code bug.",
  "mitigation": "Add retry logic with exponential backoff and increase the timeout. Consider mocking external services in unit tests.",
  "confidence": 0.9
}

Automated Reporting — Creating GitHub Issues

最后一部分是 reporting 层。一旦 agent 返回分析结果,我就使用 PyGithub 创建一个带有分析结果、标签和日志片段的 GitHub Issue。

from github import Github

class Reporter:
    def __init__(self, token, repo_name):
        self.gh = Github(token)
        self.repo = self.gh.get_repo(repo_name)

    def create_flake_issue(self, analysis, run_id, log_snippet):
        title = f"[Flake] {analysis.flake_category.replace('_',' ').title()} (run #{run_id})"
        body = f"""## Flaky Test Analysis
**Category:** `{analysis.flake_category}`
**Confidence:** {analysis.confidence:.2f}

### Root Cause
{analysis.explanation}

### Suggested Mitigation
{analysis.mitigation}

<details><summary>Log snippet</summary>

{log_snippet[:1500]}

</details>

*Auto-generated by FlakeFixer agent.*
"""
        labels = ["flaky-test", analysis.flake_category]
        issue = self.repo.create_issue(title=title, body=body, labels=labels)
        return issue.html_url

你可以在 ci-flake-lab 的 issues 标签页看到真实的输出——每一个 [Flake] ... issues 都是由 FlakeFixer 自动创建的,而非手动。

Logs showing the issues annotated by the FlakeFixer

Open Source Contribution

在构建 FlakeFixer 的过程中,我注意到 pytest-github-actions-annotate-failures 没有截断过长的 annotation 消息,导致 PR 中出现杂乱。我提交了一个 PR 来为 annotation 输出添加截断功能。这是我第一次为该项目贡献代码,它强化了清晰、可读的 CI 输出的重要性。

Next Steps for FlakeFixer

  • 添加向量数据库来存储和检索相似的历史失败。
  • 在我标记好的 flake 数据集上微调一个小语言模型。
  • 生成每周的 flake 汇总报告。

结论

Flaky tests 不必成为开发者时间的黑洞。通过结合 GitHub Actions、LLM 和自动化,我们可以自动分类和记录 flaky failures,让维护者找回时间和理智。如果你对代码感兴趣或想看演示,请查看这些仓库:

  • https://github.com/Haadiyah-Zafar/FlakeFixer
  • https://github.com/Haadiyah-Zafar/ci-flake-lab

如果你也遇到过类似的问题或有改进的想法,请在评论区告诉我!

Original source

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

阅读英文原文
上一篇
SGLang深度解析:如何高效服务DeepSeek-V4-Pro
下一篇
AI编码Agent记忆系统设计的四个教训:删除不是过期