Install
npx skillscat add penkzhou/swiss-army-knife-plugin/ci-job-analysis Install via the SkillsCat registry.
We need to produce a 2-3 sentence plain-text summary in English, objective, factual, no marketing language, no superlatives, no calls to action. Must be at most 60 words. No quotes, no bullet points, no headings, no markdown. Just plain text. Summarize: skill is CI Job failure analysis knowledge base, includes failure type classification, confidence assessment, tech stack identification, common error patterns. It solves problem of diagnosing CI failures quickly, provides guidance on root causes and fixes. Use when CI job fails and need to analyze cause, especially for GitHub Actions jobs.
CI Job 分析知识库
本知识库提供 GitHub Actions Job 失败分析和修复的专业知识。
失败类型分类体系
1. 测试失败 (test_failure)
| 子类型 | 频率 | 关键信号 | 可自动修复 |
|---|---|---|---|
| unit_test | 45% | pytest FAILED, jest FAIL, vitest | 是 |
| integration_test | 30% | integration, api test, mock server | 是 |
| snapshot_test | 15% | snapshot, toMatchSnapshot | 是 |
| other_test | 10% | 其他测试框架 | 部分 |
注意:频率数据基于历史统计,总和为 100%。
常见根因:
- Mock 数据不完整:测试 mock 缺少新增字段
- API 契约变更:接口返回格式改变
- 异步时序问题:await 缺失或时序错误
- 环境差异:CI 环境与本地环境不一致
修复策略:
1. 定位失败测试和断言
2. 比较期望值 vs 实际值
3. 追踪数据流到源头
4. 更新 mock 或修复断言
5. 验证修复2. E2E 失败 (e2e_failure)
| 子类型 | 频率 | 关键信号 | 可自动修复 |
|---|---|---|---|
| timeout | 35% | Timeout, 30000ms, waiting for | 是 |
| selector | 30% | strict mode, not found, resolved to | 是 |
| assertion | 20% | expect().toHave, toBeVisible | 是 |
| network | 15% | Route handler, net::ERR | 部分 |
常见根因:
- 选择器过时:UI 变更导致选择器失效
- 加载时序:页面加载慢导致超时
- 网络拦截失效:API mock 未正确配置
- 状态污染:测试之间状态未隔离
修复策略:
1. 分析超时/选择器错误的具体位置
2. 检查 UI 是否变更
3. 添加适当的等待策略
4. 更新选择器或断言3. 构建失败 (build_failure)
| 子类型 | 频率 | 关键信号 | 可自动修复 |
|---|---|---|---|
| typescript | 45% | tsc, error TS, compile | 部分 |
| webpack | 20% | webpack, Module not found | 部分 |
| python | 20% | SyntaxError, ModuleNotFound | 部分 |
| other | 15% | build failed, make error | 否 |
常见根因:
- 类型不匹配:TypeScript 类型错误
- 缺失依赖:import 的模块不存在
- 语法错误:代码语法问题
- 配置错误:构建配置不正确
4. Lint 失败 (lint_failure)
| 子类型 | 频率 | 关键信号 | 可自动修复 |
|---|---|---|---|
| eslint | 50% | eslint, @typescript-eslint | 是 |
| ruff | 25% | ruff, E501, W503 | 是 |
| prettier | 20% | prettier, formatting | 是 |
| other | 5% | mypy, pylint | 部分 |
快速修复路径:
# ESLint
npx eslint --fix {files}
# Ruff
ruff check --fix {files}
# Prettier
npx prettier --write {files}5. 类型检查失败 (type_check_failure)
| 子类型 | 频率 | 关键信号 | 可自动修复 |
|---|---|---|---|
| typescript | 70% | tsc --noEmit, error TS | 部分 |
| mypy | 30% | mypy, type: ignore | 部分 |
常见错误类型:
| 错误码 | 描述 | 自动修复 |
|---|---|---|
| TS2345 | 参数类型不匹配 | 否 |
| TS2322 | 类型赋值错误 | 否 |
| TS2339 | 属性不存在 | 否 |
| TS7006 | 隐式 any | 是 |
6. 依赖失败 (dependency_failure)
| 子类型 | 频率 | 关键信号 | 可自动修复 |
|---|---|---|---|
| npm | 40% | npm install, ERESOLVE | 否 |
| pip | 35% | pip install, requirement | 否 |
| yarn | 15% | yarn, resolution | 否 |
| other | 10% | pnpm, poetry | 否 |
常见问题:
- 版本冲突
- 私有包认证失败
- 网络问题
- 锁文件过时
建议:依赖问题通常需要手动处理,因为涉及版本策略决策。
7. 配置失败 (config_failure)
| 子类型 | 频率 | 关键信号 | 可自动修复 |
|---|---|---|---|
| env | 50% | env, secret, KEY_ERROR | 否 |
| permission | 30% | permission denied, 403 | 否 |
| config_file | 20% | config, settings | 否 |
不可自动修复原因:涉及敏感信息和权限配置,需要人工处理。
8. 基础设施失败 (infrastructure_failure)
| 子类型 | 频率 | 关键信号 | 可自动修复 |
|---|---|---|---|
| runner | 40% | runner, self-hosted | 否 |
| resource | 35% | OOM, killed, disk | 否 |
| network | 25% | network, timeout | 否 |
不可自动修复原因:涉及 CI 基础设施,需要运维处理。
置信度评估体系
评分因素
| 因素 | 权重 | 描述 |
|---|---|---|
| 信号明确性 | 40% | 错误信号是否清晰明确 |
| 文件定位 | 30% | 是否能定位到具体文件和行号 |
| 模式匹配 | 20% | 是否匹配已知错误模式 |
| 上下文完整 | 10% | 是否有完整的堆栈追踪 |
置信度阈值
| 分数 | 级别 | 行为 |
|---|---|---|
| >= 80 | 高 | 自动修复 |
| 60-79 | 中 | 询问用户后修复 |
| 40-59 | 低 | 展示分析,建议手动 |
| < 40 | 极低 | 跳过 |
置信度调整规则
提升条件:
- 找到高相似度历史案例:+10
- 完整的堆栈追踪:+5
- 明确的代码变更点:+5
- 匹配已知错误模式:+5
降低条件:
- 涉及多个不相关文件:-10
- 错误消息模糊:-10
- 无法定位具体原因:-15
- 可能涉及配置/权限:-20
技术栈识别
基于文件路径
backend:
patterns:
- "**/*.py"
- "tests/backend/**"
- "tests/unit/**"
- "src/api/**"
- "app/**"
signals:
- "pytest"
- "FastAPI"
- "Django"
- "Python"
frontend:
patterns:
- "**/*.tsx"
- "**/*.jsx"
- "**/*.ts"
- "tests/frontend/**"
- "src/components/**"
signals:
- "jest"
- "vitest"
- "React"
- "Vue"
e2e:
patterns:
- "e2e/**"
- "tests/e2e/**"
- "playwright/**"
- "cypress/**"
signals:
- "playwright"
- "cypress"
- "puppeteer"混合技术栈处理
当检测到多个技术栈时:
- 按错误数量确定主要技术栈
- 次要技术栈作为
secondary_stack - 优先处理主要技术栈的错误
常见错误模式库
pytest 错误模式
# 断言失败
FAILED tests/test_xxx.py::test_name - AssertionError: assert X == Y
# 异常未捕获
FAILED tests/test_xxx.py::test_name - ExceptionType: message
# fixture 错误
ERROR tests/test_xxx.py::test_name - fixture 'xxx' not found
# 导入错误
ERROR tests/test_xxx.py - ModuleNotFoundError: No module named 'xxx'jest/vitest 错误模式
# 断言失败
FAIL src/xxx.test.ts
✕ test name (123ms)
expect(received).toBe(expected)
# 超时
FAIL src/xxx.test.ts
✕ test name (5001ms)
Timeout - Async callback was not invoked within 5000ms
# 快照失败
FAIL src/xxx.test.ts
✕ test name
expect(received).toMatchSnapshot()playwright 错误模式
# 超时
Error: locator.click: Timeout 30000ms exceeded.
waiting for locator('selector')
# 选择器问题
Error: locator.click: Error: strict mode violation:
locator('selector') resolved to 2 elements
# 断言失败
Error: expect(locator).toBeVisible()
Locator expected to be visibleTypeScript 错误模式
# 类型不匹配
error TS2345: Argument of type 'X' is not assignable to parameter of type 'Y'
# 属性不存在
error TS2339: Property 'xxx' does not exist on type 'Y'
# 隐式 any
error TS7006: Parameter 'xxx' implicitly has an 'any' type修复工作流映射
| 失败类型 | 修复方式 | 关联工作流 |
|---|---|---|
| test_failure (backend) | bugfix_workflow | /fix-backend |
| test_failure (frontend) | bugfix_workflow | /fix-frontend |
| e2e_failure | bugfix_workflow | /fix-e2e |
| lint_failure | quick_fix | 直接运行 lint --fix |
| type_check_failure | bugfix_workflow | 对应栈工作流 |
| build_failure | bugfix_workflow | 对应栈工作流 |
| dependency_failure | manual | 无 |
| config_failure | manual | 无 |
| infrastructure_failure | manual | 无 |
历史案例匹配
相似度计算
def calculate_similarity(current, historical):
score = 0
# 错误类型匹配 (30%)
if current.failure_type == historical.failure_type:
score += 30
# 文件路径匹配 (25%)
file_overlap = len(set(current.files) & set(historical.files))
score += min(25, file_overlap * 5)
# 错误消息相似 (25%)
message_similarity = text_similarity(current.error, historical.error)
score += message_similarity * 25
# 修复模式相似 (20%)
if current.suggested_fix_type == historical.fix_type:
score += 20
return score高价值案例特征
值得记录为历史案例的修复:
- 置信度 >= 80
- 修复成功
- 有明确的根因分析
- 包含可复用的修复方法
- 涉及常见错误模式