mcpField
C
ci-debug

ci-debug

github.com/yonatangross云与 DevOps29947 次安装今天更新
代码仓库

关于 ci-debug

ci-debug 是用于诊断特定 CI 运行、任务或 PR 检查的 Claude Code 技能。它根据获取的日志和状态元数据匹配 11 种已记录模式,并提出修复建议,但不会自动应用。

主要功能

  1. 01按 11 种模式分类故障
  2. 02获取任务日志和状态元数据
  3. 03选择最早失败的任务
  4. 04报告未匹配的故障
  5. 05提出修复建议但不执行

适用场景

  1. 01诊断失败的 PR 检查
  2. 02区分卡住的状态与故障
  3. 03分类 CI 基础设施错误

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/yonatangross/orchestkit --skill ci-debug

安装后在 Claude Code 中输入/ci-debug确认已加载。

详细介绍

/ci-debug — 分类诊断失败的 CI 运行

直接应对 /insights 中发现的反复出现的 CI 调试模式:3 周内约有 12 个会话都在重复进行同样的分类流程。本技能将这 11 种模式固化下来,让分类流程变成查表。

输入

用户通过以下任一方式调用:

  • PR 编号:/ci-debug 822(默认使用上下文中的仓库;如有歧义则询问)
  • 运行 URL:/ci-debug https://github.com/owner/repo/actions/runs/12345
  • 作业 URL:/ci-debug https://github.com/owner/repo/actions/runs/X/job/Y

执行

1. 找到失败的作业
# From PR number:
gh pr checks <n> --repo <owner>/<repo> --json bucket,link,name \
  --jq '.[] | select(.bucket=="fail") | "\(.name)|\(.link)"'

# From run URL:
gh api repos/<owner>/<repo>/actions/runs/<run-id>/jobs \
  --jq '.jobs[] | select(.conclusion=="failure")
                | {id, name, runner_name, started_at, completed_at,
                   steps: [.steps[] | select(.conclusion=="failure") | {name, number}]}'

如果有多个作业失败,选择持续时间最短的作业——根本原因通常出现在首次失败中;后续作业会连带失败。

没有作业位于 fail 类别中,但某项检查一直没有结果? 如果 gh pr checks 显示 fail 类别中没有任何条目,但某个状态一直处于 pending 且始终没有结果(同时 gh pr view --json mergeStateStatus 返回 UNSTABLE,而 mergeable=MERGEABLE),则这是卡住的外部状态,而非失败——直接跳到模式 #11。没有可获取的失败日志;请根据提交状态元数据进行分类(gh api repos/<o>/<r>/commits/<sha>/status)。

2. 获取失败日志
gh api repos/<owner>/<repo>/actions/jobs/<job_id>/logs 2>&1 \
  | grep -iE '(error|fail|ERR_|CONFLICT|Process completed with exit code)' \
  | head -30

记录第一个独立的错误消息(后续行通常只是重复显示)。

3. 根据排查手册分类

按顺序检查这些模式。以第一个匹配项为准。

#模式日志特征记忆参考建议修复
1账单拦截runner_name 为空 + steps[] 为空 + 耗时约 3 秒 + 注释:“近期账户付款失败,或需要提高支出限额”billing-surface-hosted-vs-self-hosted.md组织管理员 → Settings → Billing & plans → 提高限额 / 更新银行卡。无需更改代码。
2根锁文件漂移ERR_PNPM_OUTDATED_LOCKFILE 提及 <ROOT>/typescript/<pkg>/package.jsonpnpm-lock-root-vs-workspace-duality.mdpnpm install --lockfile-only && git add pnpm-lock.yaml && git commit && git push。
3uv.lock 漂移error: The lockfile at uv.lock needs to be updatedchangeset-release-uv-lock-drift.md执行 cd python && uv lock,然后提交。
4ci-shared.yml 缺少权限startup_failure 模式(runner_name 为空 + steps[]=[] + 约 3 秒),但已排除账单问题ci-shared-permissions-block-required.md在调用方工作流中添加 permissions: { contents: read, packages: read }。
5YAML 内嵌 PythonYAML 解析错误指向包含 python -c 的多行块标量yaml-python-embed.md将 python -c 改写为单独调用 shell 脚本;切勿在 YAML 中内嵌多行 Python。
6actionlint shellcheck 误报audit/actionlint 作业因你未修改的工作流 YAML 中出现 SC2086/SC2046 而失败audit-actionlint-triggers-on-workflow-edit.md这不是必需检查;如果这些警告在你进行更改前就已存在,可以安全地忽略并合并。可选:添加 shellcheck 禁用注释。
7macOS BSD date 不支持 %3NCI 输出中原样打印 %3N / 算术运算失败macos-bsd-date-no-percent-3N.md将 date +%s%3N 替换为 node -e 'console.log(Date.now())' 或 python3 -c 'import time; print(int(time.time()*1000))'。
8Runner pnpm Rosetta 架构漂移可自托管的 runner 上 pnpm install 因“wrong-arch native bin”/dlopen 错误而失败runner-pnpm-rosetta-arch-drift.md重启受影响的 runner 池;根本原因是 node 在 x64↔arm64 间切换,导致共享缓存中存储了架构错误的原生二进制文件。
9浅克隆造成的假性分歧git status 报告存在分歧,但 PR 实际上已合并shallow-clone-false-divergence.md执行 git fetch origin <branch> --unshallow,然后运行 gh pr view --merge-commit 进行验证。
10发布运行已取消Publish-tag 工作流运行显示 conclusion=cancelled;构建产物从未生成publish-runs-cancelled-need-redrive.md通过 gh workflow run publish-python.yml -f tag=<tag> 重新触发(根据你的发布工作流进行调整)。
11Vercel 状态孤立(路径跳过)fail 分类中没有作业,但 Vercel 作为提交状态(而非检查运行)显示为卡在 state=pending,且 created_at == updated_at,没有后续终态更新;所有 GitHub Actions 检查均为绿色;非受保护基础分支上的 mergeStateStatus=UNSTABLE + mergeable=MERGEABLEvercel-pending-orphaned-on-path-skip.md这不是故障,只是外观问题。Vercel 发布了 pending 状态,随后跳过构建(项目根目录路径过滤器,例如仅修改文档且未改动 apps/web),导致状态孤立。可以安全合并:gh pr merge <n> --repo <owner>/<repo> --squash。永久修复:Vercel 项目的Ignored Build Step必须以 0 退出,并在跳过路径时报告成功,以便状态更新,而不是一直悬挂。

记忆参考指向用户整理的记忆文件(~/.claude/projects/<project>/memory/*.md)。如果你的记忆中还没有这些文件,仅凭特征列也足以分类——记忆引用是锦上添花,并非必需。

4. 报告

对于匹配的模式:

## CI Debug: <repo> · <pr-or-run-ref>

**Failing job:** `<job name>` (<duration>s) on runner `<runner_name>`
**Failing step:** <step name> (#<step number>)
**Error excerpt:**
\`\`\`
<first 3 lines of grep'd error>
\`\`\`

**Classification:** Pattern #<n> — <pattern name>
**Reference:** memory `<memory-file.md>`

**Proposed fix:**
<exact commands, one per line>

**Will I apply this?** No — awaiting your approval. Reply "go" to ship.

对于未匹配的故障:

## CI Debug: <repo> · <pr-or-run-ref> · NOVEL

**Failing step:** <step name>
**Unique log lines:**
\`\`\`
<top 10 distinct error lines>
\`\`\`

This doesn't match any of the 11 playbook patterns. Surfacing the raw
evidence for your read. Once you identify the root cause, consider
adding it to the playbook (in this SKILL.md) so the next run catches
it automatically.

无头调用(权限模式)

/ci-debug 需要 Bash 工具访问权限——它通过 gh pr checks、gh run view 和 gh api .../jobs/.../logs 获取证据。在无头 claude -p 运行(ci-sentinel、cron)中:

  • 使用 --permission-mode acceptEdits——这是无头模式下“无需提示即可使用工具”的选项。该技能在设计上是只读的,因此不会授予任何有风险的权限。
  • 绝不要使用 dontAsk——它会静默拒绝需要权限的工具(包括 Bash),导致每次分析都返回空输出且不报错(#1862 Bug C)。
  • claude -p 会将身份验证/权限失败信息作为 JSON 输出到 stdout,而不是 stderr——失败时同时捕获并记录两个流(身份验证方面请参阅 shared/rules/cc-bare-auth-gotcha.md)。

关键防护措施

  • 绝不要自动应用修复。 此技能只提出建议;由用户批准。误分类造成的无效操作,正是我们要重点防范的失效模式。
  • 绝不要跳过获取日志这一步。 没有实际错误文本,分类就只是猜测。如果日志已不存在(超过 90 天,运行记录已删除),请说明并停止。
  • 引用确切的记忆条目(相关时注明文件名和章节标题),以便用户核实类比是否恰当。
  • 每项分类都必须有可证伪的证据——特征必须吻合。不要抱着侥幸心理进行模式匹配。

何时调用

  • 某个具体的 CI 运行/作业/PR 检查失败,且用户希望了解原因。
  • 用户贴出运行 URL,或说“PR #N 失败了——为什么?”

何时不要调用

  • 对于“整个组织有哪些问题?”这类宽泛问题,请改用 /status。
  • 对于应用层面的测试失败(本手册专用于 CI 基础设施,不适用于例如 pytest 失败)。
  • 在读取实际日志之前——不要猜测。

添加模式

出现新的 CI 失败(触发 UNMATCHED 报告)时,向上方的表格中添加一行:

  1. 特征:足够独特的日志行/元数据组合。必须可证伪。
  2. 记忆引用:写有完整事件记录的记忆文件名。
  3. 建议修复:确切的命令行。不要写说明文字,也不要写“你可以考虑……”。此技能会生成供用户运行的命令;含糊其辞就失去了意义。

将 SKILL.md 更改提交为 docs(ci-debug): add pattern #N (<short-name>)。ci-sentinel 工作流会在下一次扫描时自动获取新模式——无需单独配置。

相关技能

  • 组合使用——ci-sentinel(针对开放的红色 PR,每小时自动触发此技能)。
  • 反模式——手动在 N 个仓库中重新运行 gh pr checks 并逐一查看日志。这正是此技能要消除的繁琐工作。
  • 上游——使用 /status 扫描整个组织并找出哪些 PR 标红;此技能则回答原因。

评论

支持 Markdown