Metabase CI 失败报告实战:使用mage ci-report生成、分类并修复 PR 检查失败
【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabase
本指南针对 Metabase 开源仓库(当前为仓库根目录)内的 Claude Code 命令 .claude/commands/ci-report.md 及其底层实现 mage/src/mage/ci_report.clj(约 780 行 Clojure 任务),系统讲解如何为一个 PR(或分支、提交 SHA)一键生成 CI 失败报告,并给出后续的失败分类与处置工作流。读完本文,你将掌握./bin/mage ci-report的完整用法、参数与报告结构,理解其底层如何抓取 GitHub Checks/日志并解析 Trunk 测试报告,以及如何区分“真实失败 / 偶发(flaky)/ 基础设施问题”并采取正确的下一步动作。
1. 一条命令与一份“人类可读的失败清单”
Metabase 的 CI 由大量 GitHub Actions 工作流组成,一个 PR 动辄挂起几十上百个 check(后端 Clojure 测试、前端 Jest、Cypress E2E、Trunk.io 静态分析等)。直接逐个点击失败 check 的日志链接效率很低。仓库为此在mage任务体系中实现了ci-report,而 Claude Code 命令ci-report.md则把它与 Agent 的分析工作流绑定起来:
- 人类(或 Agent)执行
./bin/mage ci-report $PR_NUM_OR_URL生成报告; - 随后按固定三段流程处理:总结失败 → 归类失败 → 给出建议下一步。
从源码看,该任务命名空间为mage.ci-report(mage/src/mage/ci_report.clj#L1-L8),其硬编码的远程仓库固定为metabase/metabase:
(def ^:private repo "metabase/metabase")也就是说,该命令面向 Metabase 上游仓库的 CI 数据查询,所有底层调用都经由 GitHub 官方ghCLI 完成(gh pr view、gh pr checks、gh api)。
1.1 前置条件
- 已安装并完成认证的 GitHub CLI(即
gh),且当前凭据能访问metabase/metabase的 checks 与 Actions 日志接口; - 本地已可运行 mage 任务(仓库使用 babashka + Clojure 实现 mage 命令,入口脚本位于 bin/mage 与 mage/);
- 若目标 PR 尚未有可用 check 数据,报告会提示 “No checks found… Try again in a minute”。
2. 命令语法与三类入参解析
完整用法(来自任务报错与帮助文本,mage/src/mage/ci_report.clj#L763):
./bin/mage ci-report [--detailed] [--attempt N] <pr-number|branch|sha>入参可选。当不带任何参数时,任务先尝试用gh pr view --json number反查“当前分支对应的 PR”(get-current-branch-pr);如果当前分支没有 PR,则回退为按分支名解析其最近一次 CI 提交(git rev-parse --abbrev-ref HEAD拿到分支名)。
当带参数时,参数会被classify-arg按顺序判定为三类之一(classify-arg):
| 判定优先级 | 参数形态 | 示例 | 解析结果 |
|---|---|---|---|
| 1 | 形如github.com/.../pull/<数字>的 PR 链接 | https://github.com/metabase/metabase/pull/12345 | :pr,提取其中数字 |
| 2 | 纯数字 | 41234 | :pr |
| 3 | 7–40 位十六进制字符 | a1b2c3d(提交 SHA) | :sha |
| 4 | 其余一切 | my-feature-branch | :branch,通过 Actions runs API 解析为最新 CI 提交 |
三种类型最终汇入同一条流水线:PR 路径走gh pr view+gh pr checks(run-pr-report!);分支/提交路径走 GitHub REST API 的check-runs、actions/runs接口(run-commit-report!)。注意gh pr checks在失败时返回码非 0,因此实现用sh-nil包装这类“预期会失败但输出仍有效”的命令(sh-nil)。
3. 两个关键选项:--detailed与--attempt N
任务入口generate-report!读取options中的:detailed与:attempt(generate-report!):
3.1--detailed:带 expected/actual 的完整失败块
默认(Summary 模式)只提取日志中Trunk Test Report摘要段;--detailed则拉取失败 job 的全量日志,并按两类格式还原完整失败上下文:
- Clojure 后端测试:
extract-failure-blocks以FAIL in、ERROR in开行,遇到LONG TEST、Ran N tests in ...结束,输出整块堆栈/断言信息(mage/src/mage/ci_report.clj#L251-L311); - Cypress E2E 测试:
extract-cypress-failures按N) suite > nested > title编号失败块切分,到(Results)、(Screenshots)、(Video)、passing 汇总或长分隔线处收尾(mage/src/mage/ci_report.clj#L313-L361)。
报告中对应标注Mode: Detailed (with expected/actual)或Mode: Summary(generate-report)。
3.2--attempt N:回溯某次重跑记录
GitHub Actions 允许对失败的 workflow run 重跑(rerun),每次重跑会递增run_attempt。--attempt让报告定位到指定 attempt 的 job 状态。其解析逻辑非常实用(resolve-attempt):
- 正数 N:绝对 attempt 序号;
- 0:等于该提交的最大 attempt(最新一次重跑);
- 负数 N:
max_attempt + N,因此-1表示“最新一次重跑之前的那一次”。
attempt-checks会先把 commit 关联的所有 workflow run 聚合,再按 attempt 过滤,并跳过总 attempt 数不足的 run(mage/src/mage/ci_report.clj#L632-L659);越界时会直接报错退出。
4. 报告长什么样:结构与判定逻辑
generate-report(mage/src/mage/ci_report.clj#L409-L521)最终打印一份可直接粘贴到 PR 评论的 Markdown,段落固定为:
- 标题:
# CI Report for PR #<number>: <title>(分支/SHA 模式则用# CI Report for <branch|sha>); - Metadata:PR 链接、Branch、SHA、Mode、Attempt;
- Loading Data:用
→/✓记录的命令执行轨迹(便于审计各步骤耗时与结果); - Summary 汇总表:
| Status | Count | |--------|-------| | ✅ Passed | N | | ❌ Failed | N | | ⏳ Pending | N | | **Total** | **N** |- 状态消息(
categorize-checks把每个 check 归一化为FAILURE / SUCCESS / PENDING / IN_PROGRESS / QUEUED等,categorize-checks),共四种结论:⚠️ No checks found.——CI 可能尚未启动或数据未就绪;✅ All checks passing!;⏳ CI is still running... (N checks pending);⚠️ CI has failures and is still running (N failed, N pending);
- ❌ Failed Checks:按名称排序逐个列出失败的 job,附原始日志链接,然后在 Summary 模式下粘贴解析出的 Trunk 摘要,
--detailed模式下粘贴完整失败块;没有可解析内容则输出_No test failures found in logs._; - ⏳ Pending Checks:尚未结束的 check 列表;
- 结尾附生成时间:
_Generated by mage ci-report at ... UTC_。
4.1 失败日志如何被“清洗”出来
从原始 job 日志到可读文本经历了多层处理,这是报告可信度的关键:
- ANSI 清理:剥掉颜色转义序列(
strip-ansi,mage/src/mage/ci_report.clj#L34-L41); - 回车覆盖还原:终端进度动画用
\r覆盖行,解析时对每行只保留最后一个\r之后的内容(resolve-carriage-returns,mage/src/mage/ci_report.clj#L43-L53); - 时间戳剥离:去掉 GitHub Actions 日志行首的
2026-02-06T02:38:25.1443042Z前缀(strip-timestamp,mage/src/mage/ci_report.clj#L166-L171); - 定位测试报告段:Summary 模式下以
📚(Trunk Test Report 标题)、Total: N Pass:汇总行或trunk.io链接三种标记寻找报告起点,找不到则回退取末尾 2000 行(find-test-report-start); - Trunk 摘要结构还原:
parse-trunk-report把📦 <package>、失败测试名、⤷ <trunk.io链接>、…and N more failures等碎片拼回缩进清晰的分组失败清单(mage/src/mage/ci_report.clj#L173-L249)。
日志抓取本身带**最多 3 次指数退避重试(1s→2s)**与单请求 60 秒超时(job-logs-raw,mage/src/mage/ci_report.clj#L129-L150);多个失败 job 的日志用 Clojurefuture并行抓取,每个 job 同样有 60 秒上限,个别超时不会拖垮整个报告(fetch-failed-logs-parallel,mage/src/mage/ci_report.clj#L381-L407)。
5. 拿到报告后的三步工作流(命令核心)
命令正文规定了拿到报告后必须执行的三个动作,这正是把“机器生成的报告”升级为“可执行的结论”的关键一环:
5.1 Summarize the failures(总结失败)
以报告中的Failed Checks与Summary表为基础,说明:哪些测试失败了?在哪些 job 中失败?涉及 Clojure 单元/集成测试、前端测试还是 Cypress E2E?失败是否集中在某个包(📦 metabase.foo-test)或某条 spec 文件?
5.2 Categorize(归类:真实失败 / flaky / 基础设施)
| 类别 | 特征信号 | 处置方向 |
|---|---|---|
| 真实失败(real) | 断言错误、堆栈来自被测代码、与 PR 改动明显相关 | 定位根因并提出修复 |
| 偶发(flaky) | 与改动无关的随机失败、超时类、或换一次重跑即通过 | 建议重跑验证 |
| 基础设施(infrastructure) | 超时(timeout)、内存溢出(OOM)、网络错误、runner 故障 | 记录问题类型并在报告中注明,通常不是代码缺陷 |
可以用--attempt N/--attempt -1对比历次重跑结果来辅助判断 flaky 与否——若某测试上一次 attempt 通过、本次失败,flaky 概率显著上升。
5.3 Recommend next steps(给出建议下一步)
判为 flaky:建议执行 GitHub CLI 的失败项重跑:
gh run rerun <run-id> --failed -R metabase/metabase其中
<run-id>可在失败 check 的 Actions run 页面或gh run list中获取;判为真实失败:结合
--detailed模式输出的完整FAIL in/ERROR in块或 Cypress 编号失败块定位根因,提出针对该测试或源码的修复建议;判为基础设施问题:明确标注是 timeout、OOM 还是 network,避免误当成代码问题处理。
5.4 全部通过时
命令明确要求:如果所有 check 都通过,简短确认即可(例如“CI 全部通过 ✅”),无需展开冗长分析。这与报告内部逻辑一致——All checks passing!时不会再有 Failed Checks 段落。
6. 如何查看帮助与完整任务列表
mage 任务基于 babashka + Clojure,入口为 mage/(含 mage/src/mage/cli.clj 的命令行解析与 malli schema 参数校验)。查看任务帮助可直接运行:
./bin/mage ci-report --help帮助会打印 Task Name、Usages、Arguments、Options 与 Examples(mage/src/mage/cli.clj#L45-L80);参数不合法时也会自动打印帮助并退出。若希望了解该命令在 Agent 工作流中的定位,可对照阅读 .claude/commands/ci-report.md 及其它相关 bot/命令文档(如 .claude/commands/fix-pr.md、.claude/commands/qabot-report.md)。
7. 实践建议与注意事项
- 先无参跑一次:在功能分支上直接执行
./bin/mage ci-report即可得到当前分支所属 PR 的报告,比手输 PR 号更省事;它会自动走“当前分支 PR → 分支最新 CI 提交”的回退链。 - 失败很多时优先用 Summary 模式:它只解析 Trunk 摘要,输出精炼;需要深入某一具体失败时再针对该 job 用
--detailed。 - 重跑后对比 attempt:
gh run rerun ... --failed重跑完成后,用./bin/mage ci-report <pr> --attempt -1回溯上一轮,可快速确认某失败是否为 flaky。 - 报告是只读的:
mage ci-report只查询 GitHub API 并输出 Markdown,不会改动任何仓库文件或 CI 配置;请放心在 CI 报错时反复调用。
【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabase
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考