关于 triage-flaky-test
用于调查单个不稳定测试的 Agent 技能,可查看失败历史、模式和类别,并建议修复、隔离或升级。它依赖 dd-pup 技能,并可通过 Datadog MCP 工具或 pup CLI 工作。
主要功能
- 01查看不稳定测试详情
- 02分析近期失败历史
- 03统计受影响流水线
- 04按根因提出处理建议
- 05获批后隔离测试
适用场景
- 01定位测试失败的间歇性根因
- 02判断失败影响范围
- 03为高频失败测试制定隔离方案
MCP 相关
若可用,此技能会调用 Datadog MCP 工具查询测试和流水线数据,并在获批后更新测试状态;否则可通过 pup CLI 操作。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ datadog-labs/ agent-skills --skill triage-flaky-test安装后在 Claude Code 中输入/triage-flaky-test确认已加载。
详细介绍
不稳定测试分诊
一句话概述:调查某个不稳定测试——获取历史记录、失败模式和类别,然后建议修复、隔离或升级处理。
需要:dd-pup 技能(已安装并通过身份验证的 pup CLI)。
后端
检测——每次调用开始时,采取任何操作之前,先确定要使用的后端:
- 如果用户在任何位置传入了
--backend pup→ 立即使用 pup 模式。跳过步骤 2–4。 - 检查可用工具中是否包含
get_datadog_flaky_tests。 - 如果包含 → 全程使用 MCP 模式。严格按照本技能工作流各部分中的名称调用工具。
- 如果不包含 → 检查
pup是否可执行:通过 Bash 运行pup --version。如果命令成功退出(退出代码为 0),则 pup 可用。 - 如果 pup 有响应 → 全程使用 pup 模式。使用本文件底部的工具参考附录转换每次工具调用。
- 如果两者都不可用 → 停止并告知用户:
“Datadog MCP 服务和 pup CLI 均不可用。请连接 MCP 服务或安装 pup(
brew install datadog-labs/pack/pup)。”
pup 调用规则:
- 通过 Bash 调用。pup 始终输出 JSON——直接解析。
- 传给 pup 的仓库 ID 必须全部为小写(API 不接受大小写混合的值)。
- 以
-开头的排序值必须使用=语法:--sort="-last_flaked"(不要使用--sort "-last_flaked")。 - 如果 pup 返回 401/403,请告知用户运行
pup auth refresh或pup auth login。
输入
| 参数 | 说明 |
|---|---|
| 测试名称 | 完整限定的测试名称(例如 TestMyFunc 或 com.example.MyTest) |
| 仓库 | 全小写、不带 schema 的 URL(例如 github.com/org/repo)。如果未提供,则从 git remote get-url origin 推导。 |
工作流
步骤 0 — 解析输入
如果未提供仓库,则从 git 推导仓库 ID:
git remote get-url origin
# Strip protocol and trailing .git, then lowercase the result
# e.g. https://github.com/DataDog/my-repo.git → github.com/datadog/my-repo
验证回退: 如果步骤 1 未返回结果,则不使用仓库筛选条件进行搜索,以确认正确的仓库:
Tool: search_datadog_test_events
query: @test.name:"<test-name>"
from: now-30d
test_level: test
从结果中提取 @git.repository.id_v2,并使用确认后的值重试步骤 1。
步骤 1 — 获取不稳定测试详情
首选——已知 fingerprint_fqn 时使用它(fingerprint_fqn 是有效的 CI Visibility 搜索 facet):
Tool: get_datadog_flaky_tests
query: fingerprint_fqn:<fqn>
sort_field: last_flaked
sort_order: desc
回退——使用名称 + 套件 + 仓库:
Tool: get_datadog_flaky_tests
query: @test.name:"<test-name>" @test.suite:"<suite>" @git.repository.id_v2:"<repo>"
sort_field: last_flaked
sort_order: desc
如果未知,则省略 @test.suite。不要按 flaky_test_state 筛选——无论测试处于何种状态,都要返回该测试。
注意:查询筛选 facet 是 flaky_test_state;返回的响应属性是 flaky_state——不要使用 flaky_state:active 作为查询筛选条件。
从结果中提取:
fingerprint_fqn— 唯一的测试标识符;在步骤 5 的写入调用中用作id。如果缺失,则不要继续隔离——请参阅步骤 5。flaky_state— 当前状态(active / quarantined / disabled / fixed)test_stats.failure_rate_pct— 运行失败的百分比flaky_category— 根因类别codeowners— 负责的团队pipeline_stats.total_lost_time_ms— CI 总耗时损失
步骤 2 — 获取近期失败历史
Tool: search_datadog_test_events
query: @test.name:"<test-name>" @test.suite:"<suite>" @test.status:fail @git.repository.id_v2:"<repo>"
from: now-7d
test_level: test
提取:
- 错误消息和堆栈跟踪(
@error.message、@error.stack) - 失败分支(
@git.branch)——仅特定分支还是普遍出现 - 频率模式——随机时间点还是由特定条件触发
- 用于评估影响范围的唯一
@ci.pipeline.id值(步骤 3)
步骤 3 — 检查影响范围
使用步骤 2 中的 pipeline ID 统计受影响的不同 pipeline 数量:
Tool: aggregate_datadog_ci_pipeline_events
query: @ci.status:error @ci.pipeline.id:(<id1> OR <id2> OR ...) @git.repository.id_v2:"<repo>"
ci_level: pipeline
aggregation: count
group_by: ["@ci.pipeline.name"]
from: now-7d
使用步骤 2 中最先出现的 10 个 pipeline ID(最多 10 个;如果还有更多,则运行第二批查询,并按批次对每个 @ci.pipeline.name 的数量求和后合并结果)。报告影响范围时,说明受影响的唯一 pipeline 总数,以及失败是仅发生在特定分支还是普遍出现。
注意:pipeline 失败不一定完全由此不稳定测试导致——应将影响范围视为参考信号,而非确定的计数。
步骤 4 — 建议修复或隔离
使用步骤 1 中的 flaky_category 和步骤 2 中的错误消息。
先找根本原因:
- 从底部向上阅读完整的错误跟踪信息——链式错误会掩盖真正的原因;最内层的错误才是根本原因,而不是第一行。
- 找出不确定性的确切来源(竞争、顺序、过时状态、时序)。
- 如果根本原因是 CI 基础设施问题(运行器不可用、Docker 守护进程故障、网络中断)→ 不要提出代码修复方案;将其分类为
infra,并建议重试。 - 如果根本原因不确定,且无法通过堆栈跟踪确认 → 跳过修复,转到隔离。
在正确的层级修复:
- 测试问题 → 仅在测试或测试辅助工具中修复。
- 测试暴露的生产环境 Bug → 在生产代码中修复。
- 多个测试共用的辅助工具 → 修复该辅助工具,并更新所有调用点。
禁止——不要提出以下方案:
- 时序技巧:延长超时时间、添加休眠、扩大时间窗口、添加重试。
- 掩盖问题:放宽断言(例如,将精确匹配改为至少 1 个)、删除验证。
- 局部修复:当多个调用点存在相同根本原因时,只修改其中一个。
各类别的修复模式:
| 类别 | 方法 |
|---|---|
timeout | 找出耗时操作,并使其同步或确定化——不要只提高超时常量 |
concurrency | 添加确定性同步机制(屏障、通道、锁);消除测试之间共享的可变状态 |
network | 在边界处模拟或替代网络调用;如果测试需要真实连接,则使用测试服务器隔离连接 |
time | 注入可控时钟;将墙上时钟断言替换为相对检查或事件驱动检查 |
order_dependency | 使用 setup/teardown 隔离测试状态;消除对执行顺序或全局状态的依赖 |
environment_dependency | 模拟环境变量和外部配置;使用测试专属的固定数据,而非共享目录或单例 |
resource_leak | 确保测试中打开的每个资源都在 teardown 时关闭;使用即使在失败时也会运行的清理钩子 |
randomness | 为测试运行固定随机种子;使用确定性输入,而非随机生成的数据 |
asynchronous_wait | 将固定休眠替换为条件轮询,或带硬性超时的事件/信号驱动等待 |
io | 使用在 teardown 时清理的临时文件/目录;模拟或替代文件系统交互 |
unknown | 跳过修复尝试 → 转到隔离 |
提出代码更改之前,请验证以下所有事项——任何一项未通过,都应跳过修复并建议隔离:
- 根本原因是跟踪信息中的最内层错误,而非表面症状。
- 失败属于代码问题,而非 CI 基础设施问题。
- 修复能够消除根本原因(而非仅降低出现不稳定的概率)。
- 修复位于正确的层级(测试、生产代码或共享辅助工具)。
- 所有共享代码的调用点都已更新。
- 没有引入时序技巧或放宽断言。
决策:
- 如果类别为
unknown,或上述验证未通过 → 跳过修复,建议隔离 - 如果类别已知、根本原因已确认且修复有效 → 提出具体的代码更改
第 5 步——生成分诊简报并采取行动
Flaky Test Triage Brief
=======================
Test: <fully qualified test name>
Service: <@test.service>
Category: <flaky_category>
Failure Rate: <test_stats.failure_rate_pct>%
Duration Lost: <pipeline_stats.total_lost_time_ms>ms
Codeowners: <codeowners>
Blast Radius: <N> pipelines (<branch-specific | widespread>) [approximate — other failures in the same pipeline runs may not be related]
Evidence:
<1-2 key error message lines from STEP 2>
Recommendation: <fix | quarantine | escalate>
Confidence: <high | medium | low>
Action: <specific next step>
决策阈值:
failure_rate_pct > 10或影响范围 > 5 条流水线 → 隔离failure_rate_pct ≤ 10,且类别已知并且有明确的修复方案 → 修复failure_rate_pct ≤ 10,且类别为unknown→ 将分诊简报升级给代码所有者
如果建议隔离,请先向用户说明并要求其明确批准,然后再写入:
Proposed action: quarantine "<test-name>"
id (fingerprint_fqn): <fingerprint_fqn from STEP 1>
Effect: test still runs but failures are suppressed (CI will not be blocked)
Reversible: yes — set new_state: active to restore
Approve? (yes/no)
如果步骤 1 未返回 fingerprint_fqn(测试尚未进入 FTM,或查询未返回结果):不要尝试写入。请显示错误,并要求用户直接打开 Flaky Test Management UI 手动隔离。
只有在获得明确批准且确认了 fingerprint_fqn 后:
MCP 模式:
Tool: update_datadog_flaky_test_states
test_ids: ["<fingerprint_fqn>"]
new_state: quarantined
pup 模式:
cat > /tmp/flaky-update.json <<'EOF'
{
"data": {
"type": "UpdateFlakyTestsRequest",
"attributes": {
"tests": [{"id": "<fingerprint_fqn>", "new_state": "quarantined"}]
}
}
}
EOF
pup test-optimization flaky-tests update --file /tmp/flaky-update.json
撤销操作:使用 new_state: active / "new_state": "active" 重复上述操作。
工具参考
本附录仅适用于 pup 模式。在 MCP 模式下,请直接使用工作流各部分中的工具名称。
| MCP 工具 | pup 命令 |
|---|---|
get_datadog_flaky_tests(按 fingerprint_fqn 查询) | pup cicd flaky-tests search --query "fingerprint_fqn:<fqn>" --sort="-last_flaked" --limit 5 |
get_datadog_flaky_tests(按名称 + 套件 + 仓库查询) | pup cicd flaky-tests search --query "@test.name:\"...\" @test.suite:\"...\" @git.repository.id_v2:\"...\"" --sort="-last_flaked" --limit 10 |
search_datadog_test_events(验证备用方案) | pup cicd tests search --query "@test.name:\"<test-name>\"" --from 30d --limit 5 |
search_datadog_test_events(失败历史) | pup cicd tests search --query "@test.name:\"...\" @test.suite:\"...\" @test.status:fail @git.repository.id_v2:\"...\"" --from 7d --limit 20 |
aggregate_datadog_ci_pipeline_events(影响范围) | pup cicd events aggregate --query "@ci.status:error @ci.pipeline.id:(...) @git.repository.id_v2:\"...\"" --compute count --group-by "@ci.pipeline.name" --from 7d |
update_datadog_flaky_test_states | 将请求正文写入 /tmp/flaky-update.json,然后执行 pup test-optimization flaky-tests update --file /tmp/flaky-update.json |