关于 ci-debugging
ci-debugging 是用于诊断 CI 故障的技能,通过运行证据、可验证假设及与本地和最近成功运行的对比来定位问题。它指导开发者从调查到验证,并区分故障诊断与获授权的更改。
主要功能
- 01收集特定 CI 提供方的日志与产物
- 02对比失败运行与最近成功运行
- 03检验排序后的可证伪假设
- 04分析 CI 与本地环境差异
- 05用原始失败命令验证修复
适用场景
- 01调查 GitHub Actions 作业失败
- 02追查 CI 与本地测试的差异
- 03判断多次运行结果是否证明存在不稳定性
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ citypaul/ .dotfiles --skill ci-debugging安装后在 Claude Code 中输入/ci-debugging确认已加载。
详细介绍
CI 调试
所有 CI 失败都应视为真实问题,直到证明并非如此。切勿假定是偶发故障。
此技能负责处理流水线专属证据和环境差异。对于 CI 之外的本地或运行时故障,请使用 debugging。
获取数据
先根据仓库配置确定 CI 提供商,然后使用该提供商已连接的工具、CLI 或 UI 拉取实际失败输出,再提出假设。保留运行、作业、尝试次数、提交 SHA 和时间戳,以便后续比较指向同一次执行。
对于 GitHub Actions:
gh run list --branch <branch> --limit 5 # find the failing run
gh run view <run-id> --log-failed # only the failed steps' logs
gh run view <run-id> --job <job-id> --log # one job's full log
gh run download <run-id> # artifacts (coverage, reports, screenshots)
重新运行工作流或更改 CI 变量会修改外部状态,并可能再次触发部署、迁移、通知或其他操作。只有在检查工作流和失败作业的副作用并获得明确授权后,才能执行这些操作。获得授权后,仅重新运行失败的作业,使用 gh run rerun <run-id> --failed;或者使用 gh run rerun <run-id> --debug 启用步骤级日志记录;之后移除任何临时调试变量。对于其他提供商,请使用其对应的控制方式,不要凭猜测翻译命令。将失败运行与同一分支上最近一次通过的运行进行比较——这两次运行之间的提交、依赖锁文件和流水线文件差异,是首要的可疑项列表。
如果被测系统会生成结构化遥测数据(规范事件、跟踪记录、测试运行产生的内存中导出器输出),请将其与日志一并作为证据拉取——参见 observability 技能。
假设优先的诊断
编辑前,列出可能的原因,按证据强弱排序,并一次只检验一个可证伪的假设。不要为了凑数而虚构最低数量。
测试超时的假设示例:
- 测试依赖 CI 中不可用的网络访问
- 并行执行测试导致资源争用
- CI 运行器的内存/CPU 少于本地机器
本地复现
如果有可忠实复现的环境,请先在本地复现,再推送修复。
- 运行失败的准确命令,而不是近似命令
- 尽可能匹配 CI 环境(Node 版本、环境变量)
- 如果本地运行通过,请将环境差异视为定位问题的证据;原因仍可能与时序、状态或外部依赖有关
环境差异分析
比较 CI 与本地环境:
| 因素 | 检查项 |
|---|---|
| Node/运行时版本 | CI 配置与本地的 node -v |
| OS | Linux CI 与 macOS 本地环境 |
| 依赖解析 | 仓库锁定的干净安装命令和包缓存(对于 npm,比较 npm ci 与缓存的 node_modules) |
| 环境变量 | CI 密钥/配置与本地 .env |
| 并行度 | CI 可能以不同方式并行运行测试 |
| 内存/CPU | CI 运行器通常资源较少 |
| 网络 | CI 可能会阻止外部网络访问 |
| 文件系统 | 区分大小写(Linux)与不区分大小写(macOS) |
阅读完整错误信息
- 阅读完整错误输出,而不只是最后一行
- 检查前面的日志行和警告——其中往往包含真正的原因
- 查看堆栈跟踪,确定实际故障点
- 检查是否有更早发生、可能级联导致当前可见错误的故障
修复验证
如果请求仅限于诊断,请报告有证据支持的根本原因、受影响的作业、不确定性和建议的修复方案,然后停止。诊断并不授权修改工作流、生产环境、依赖、测试或配置。
如果用户要求修复,在确定问题后:
- 说明修复为何能解决根本原因,而不只是表面症状
- 在本地运行失败的准确命令
- 确认修复不会掩盖真正的问题(例如,添加重试会掩盖竞态条件)
反模式
| 反模式 | 为什么不对 | 应改为 |
|---|---|---|
| “它不稳定,再运行一次” | 掩盖真实问题 | 调查失败原因 |
| 盲目添加重试或休眠 | 可能掩盖时序错误 | 找出原因;仅在外部契约要求时添加有界重试 |
| 推送未经验证的修复 | 浪费 CI 周期 | 在本地复现并验证 |
| 只看最后一行错误信息 | 会遗漏根本原因 | 从头阅读完整输出 |
| 只修复症状 | 问题会再次出现 | 追查根本原因 |
证明不稳定性
在受控输入相同的情况下,多次独立运行得出不同结果,说明结果具有非确定性。即使尚未查明原因,这也足以证明存在不稳定性。记录实际受控的输入和环境因素,然后定位原因:竞争条件、时间、共享状态、资源压力或外部依赖。一次无法解释的失败仍然是真实失败,不能因此反复运行直到通过。
交接
确定根本原因后,仅提供诊断的交接应以证据和建议的防护措施收尾。对于获准修复的问题,应留下与之匹配的最小且持久的回归防护措施。对于生产行为,应在修复前使用 tdd 编写失败行为测试(若需先记录旧有行为,则使用 characterisation-tests)。对于提供方配置、权限或外部服务中断,应酌情使用配置断言、试运行、契约检查或受监控的恢复证明。如果无法实现可执行的防护措施,应记录证据和剩余的检测途径,而不是编造测试。