ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

PostHog CI 失败排查方法论:从 hogli ci:insights 跨运行洞察到最小化本地复现

PostHog CI 失败排查方法论:从 hogli ci:insights 跨运行洞察到最小化本地复现 PostHog CI 失败排查方法论从 hogli ci:insights 跨运行洞察到最小化本地复现【免费下载链接】posthog:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.项目地址: https://gitcode.com/GitHub_Trending/po/posthogPostHog 仓库的 CI 由多套并行 workflow、Depot 自托管 runner 和分片测试矩阵组成单看某一次 GitHub Actions 运行的日志往往无法判断是谁、在什么范围内出了问题。本文基于仓库中的 debugging-ci-failures 技能文档 展开讲清 PostHog 内部定位 CI 失败的完整工作流先用hogli ci:insights的跨运行摘要做分诊再用gh只读命令确认归属与细节配合固定的失败分类表、基础设施失败基线率查询和最小复现命令最终产出一份标准化的排查报告。读完本文你可以独立完成CI 红了到给出可执行结论的全过程而不盲目重跑或误判。两个数据源各司其职技能文档开篇就明确了数据源分工这是整个方法论的地基hogli ci:insights摘要优先。它聚合跨运行、跨分支的失败历史来自 PostHog 自身的工程分析数据而gh无法廉价地完成这种聚合。它回答该去查什么——失败更可能源自 trunk、只卡在合并队列门禁还是只出现在少数分支上。gh是单次运行当前状态与归属的权威。用摘要决定检查方向后再用gh确认这是谁的失败、某次具体运行里到底哪一步挂了。摘要负责分诊排名gh负责事实确认两者顺序不能颠倒——先读原始日志做考古是明确反对的做法。先排除平台故障再读任何日志GitHub Actions 与 Depot runner 的可用性故障足够常见因此它排在所有日志阅读之前平台级事故会让其他一切信号都退化成症状。技能文档要求在任何一次失败范围较广时多个 workflow 同时失败、一批运行集中挂掉、任务在Checkout之前死亡、不相干的多个 PR 同时变红先检查 GitHub 与 Depot 的官方状态页。一旦确认是平台故障按故障如实上报、点名组件并停止建议重跑。这是后文安全规则的第一条应用。安全红线哪些动作必须先获得明确批准技能文档列出了一组没有当前对话中的明确批准就绝不做的操作重跑或取消 GitHub Actions 运行通过任何 CLI、MCP 或 API 工具发布 GitHub 评论、PR review 或 issue 评论推送提交、force-push、重命名或删除分支编辑.github/workflows/下的文件CI 基础设施变更需要人工评审合并、关闭或重新打开 PR接受或更新快照snapshot。只读的gh调用和只读的 GitHub 工具随时可用。若必须改动本地 Git 状态先确认它对任务必要且不会覆盖无关工作。这套红线在无人值守场景下会被进一步收紧配套的 master-red-incident 参考文档 指出没有对话就没有明确批准于是上述所有动作一律禁止——尤其重跑会销毁你被派去阅读的证据。工作流第一步永远从 CI insights 摘要开始hogli ci:insights # 当前仓库 分支的摘要 hogli ci:insights search error or test name # 按错误文本或测试名匹配 hogli ci:insights view ref # 完整查看某一个失败 hogli ci:insights view ref --logs # 附带该失败的日志行按问题粒度选择入口宽泛问题CI 红了吗master 今天绿吗现在什么坏了无参摘要直接回答。它给出默认分支裁定最新一次运行中有多少 workflow 失败、分别是哪些、按状态分组的存活失败、当前在 trunk 上为红的具体 job、默认分支失败的分组 feed以及你的分支所属的 PR。多数宽泛问题不需要指定目标 PR 或运行直接依据摘要汇报即可。具体失败先search error匹配再对摘要或搜索结果中打印出的行执行view ref。--logs会打印该失败最新一次运行中被裁剪后的失败行通常足够分类无需再碰gh。用state做分诊排名摘要中每一行失败都带一个state字段其含义构成一张分诊排名表顺序即优先级最紧急在前状态含义breaking_master在默认分支上失败且该 job 的最新一次运行仍为红blocking_merge_queue时间窗口内仅在合并队列门禁分支上失败novel_burst一天内新出现、已在多分支扩散、尚未打到 trunkpotentially_resolved曾打到 trunk但该 job 的最新运行已恢复绿色flaky跨两个以上分支、跨越一天以上的零散发布pr_only分支扩散有限job 状态可能缺失或落后于失败行两个状态要特别谨慎potentially_resolved只是提示而非结论报告已修复前必须用运行数据确认blocking_merge_queue只能证明窗口内发生过门禁失败不能证明现在仍在阻塞合并报告前要用gh查看当前队列运行。同理pr_only在归因到某个 PR 之前也要用当前运行确认——它同时也是 job 状态缺失或陈旧时的兜底状态。这些状态定义并非只存在于技能文档中。ci_insights.py 中的_STATE_MEANINGS字典与上表逐条对应且源码注释明确说明端点返回的行已按紧急度排序客户端只做计数汇总、不做二次排序把分类器的判断权交给第二处被视为错误做法。汇报时必须携带的注意事项源码中的_CAVEATS与技能文档一致三条注意事项应随结论一起传达失败分组仅覆盖 pytest。Jest、Playwright、cargo 的失败只会出现在摘要的master 失败分组区不会成为带ref的独立行所有计数都是绝对值不是比率。测试级数据不含通过的运行没有可引用的分母job 结论里记录了绿色运行基线率一节就是拿真实比率的方法运行的结论可能有滞后要等 GitHub 的workflow_runwebhook 落定。事故进行中时具体运行要对照gh确认。未登录时退出码 78 即降级信号若本机没有登录 PostHoghogli ci:insights以退出码78结束。源码 注释说明这是刻意为之78sysexits 的EX_CONFIG让 debugging-ci-failures 技能可以基于退出码而非报错文本分支到gh只读回退路径诊断信息走 stderr 以保持 stdout 可解析。遇到78的处理方式是视为CI insights 不可用直接转入下文的gh排查并告诉用户可自行运行一次hogli posthog:login打开浏览器、无需 API key。不要替用户运行它——它会卡在一个你看不到的授权页上。发现问题后按安全规则如实汇报不要自动应用修复。从源码结构看该命令还做了两件对 Agent 友好的事stdout 非终端时自动输出 JSON--json可在 tty 中强制且输出是命令自有的摘要形状而非端点透传——因为裸的broken_tests端点返回 200 行、字节数大部分是小时级 sparkline以及它只申请engineering_analytics:read这一个 scope见_SCOPES使 CI 分诊凭据在任何地方都没有写权限。工作流第二步找到失败的运行针对具体失败确定排查目标按以下顺序用户给了 PR 号、运行 ID、check 名或分支名就直接用否则用当前分支推断gh pr view --json number,headRefName,statusCheckRollup两者都不行就向用户要 PR URL 或运行 ID。不要猜。特例从合并队列被踢出的 PR被合并队列踢出的 PR其自身 check 是错误的排查目标。原因是队列的运行模型trunk 把每个排队 PR 放到一个trunk-merge/pr-n/uuid分支上测试该分支包含 master 加上队内所有受影响目标与其重叠的、排在它前面的 PR。队列的车道脚本有意多报受影响目标所以实践中该分支携带了队列里的大多数 PR。由此推出四条排查纪律失败的运行在trunk-merge/pr-n/uuid分支上绝不在 PR 的 head SHA 上。从Trunk Merge Queuecheck 运行/merging-prs第 4 步获取而不是gh pr checks。分支是临时的但运行和日志留在 GitHub 上仓库侧的 job 历史也按这个head_branch保留investigation-queries.md 的 query 8 可直接查询PR 自身 check 可能全绿但失败的 job 是skipped 或被裁剪的PR 上路径过滤器只看该 diff、Django 套件只跑选中子集队列分支上的 diff 是所有携带 PR 的并集完整矩阵永远跑。一个纯文档 PR 也可能被一个它自己 CI 从未运行过的 job 踢出分支名只标注一个 PR却携带很多 PR。在它上面的失败在找到致因变更之前不构成对该 PR 的证据——分支上其他合并提交才是第一嫌疑人在摘要中这类失败对应blocking_merge_queue状态。只读检查命令gh pr checks pr gh pr view pr --json statusCheckRollup gh run view run-id --json jobs,conclusion,name,workflowName,url gh run view run-id --log-failed仅当--log-failed缺少失败命令或上下文输出不够时再拉全量 job 日志gh run view run-id --log --job job-id如果手上有运行 IDengineering-analytics-run-failure-logsMCP 工具可以一次返回所有失败 job 的错误区域带原始行号、已裁剪——省去了列 job 下载日志两步且在 job 死于任何测试运行之前时也有效。它受 Logs 保留期限制老运行要回退到gh。如果手上是 PR 号而非运行 IDengineering-analytics-ci-failure-logs会跨该 PR 推送过的所有运行做同样的事早先 push 的失败仍在。分类前要提取四要素workflow 名或文件如.github/workflows/ci-backend.yml、job 名如backend-tests (4/10)、step 名如Run pytest、失败命令与最小有用输出摘录。扫描日志时依次搜索FAIL、Error、error:、assert、Traceback、exit code、##[error]。停在第一个能解释整个运行结论的失败 step上。摘录保持在 40 行以内。对测试类 job 的失败trunkMCP 服务器的investigate-ci-failure工具可以跳过日志扫描给它运行 URL它会从 CI 上传的 Trunk Flaky Tests 结果返回结构化失败测试详情名称、错误消息、stdout/stderr且已过滤掉被隔离的已知 flaky 测试。它只覆盖跑了并上传了的部分死于测试之前的 jobbuild、setup、lint仍要用engineering-analytics-run-failure-logs或gh run view --log。trunk 的认证是一次性浏览器 OAuth无头环境则在.mcp.json的 server 配置中加Authorization: Bearer头并使用TRUNK_API_TOKEN组织 token。要深挖某个测试的 flaky 历史则交给下文的fixing-flaky-tests技能。失败分类表信号到类别类别到首个动作技能文档的核心是一张信号→类别→首动表这是排查动作的决策中枢日志中的信号类别首个动作已提交的测试文件中出现AssertionError、测试 diff、FAILED test_...代码回归用hogli test path::test复现同一测试此处失败、在master或同一 PR 的重跑中通过flaky 测试对照master历史确认修复走fixing-flaky-testsruff、oxlint、stylelint、markdownlint、prettier报错lint对涉及文件跑hogli lint:python:fix或hogli formatmypy、pyright、tsc、typescript:check报错typecheck本地运行同一检查器而非全套Chromatic / Storybook / Playwright 视觉 diff、快照不匹配快照 / 视觉给出 diff URL绝不自动接受快照manage.py migrate报错、migrations:check失败、缺失迁移迁移 / schema本地跑hogli migrations:checkOpenAPI schema diff、生成的 API 类型不同步代码生成漂移hogli build:openapiCannot connect、ECONNREFUSED、address already in use、OOM、runner 被杀、setup 超时基础设施 / runner先取基线率再断言瞬时见下文startup_failure结论、零步骤记录的 job、日志 blob 返回 404基础设施 / runner无日志可读查 GitHub 状态页与周边运行apt-get、uv sync、pnpm install、docker pull、setup action 失败环境 / setup对比.nvmrc、pyproject.toml、package.json、Dockerfilehogli lint:skills、hogli build:skills失败skills 构建本地运行同一条hogli命令SDK 兼容性检查、ci-survey-sdk-check、跨版本失败SDK 兼容性检查受影响包的 SDK 版本矩阵多个信号同时命中时选最具体的类别codegen 漂移优先于 lint迁移优先于 typecheck快照/视觉优先于泛化的 Playwright 测试失败。基础设施与 setup 失败的基线率瞬时是对一个 job 失败频率的断言不能由单次运行推出。一个在测试运行前死掉的 job 不留测试级证据没有FAILED行因此没有指纹、没有 span永远不会出现在broken_tests或 flaky 测试工具的行列中。它仍然可见为job 结论——这正是摘要 master-failures 分区的分组维度而engineering-analytics-run-failure-logs按运行而非按测试读取所以仍会返回其失败行。排查起点是 job 结论不是测试。与 span 派生的测试读取不同job 结论包含绿色因此分母是诚实的能算出真实比率。investigation-queries.md 中的 query 7 可直接复制使用其 HogQL 按 repo workflow job 三重限定job 名在多个 workflow 中重复仅按 job 过滤会把无关尝试混入分母并把failure、timed_out、startup_failure、stale计为决定性失败刻意排除cancelled/skipped等未达判定的结论SELECT countIf(conclusion success) AS ok, countIf(conclusion IN (failure, timed_out, startup_failure, stale)) AS fail, round(100.0 * fail / nullIf(ok fail, 0), 2) AS fail_pct FROM engineering_analytics_ci_job_history WHERE repo_name repo AND workflow_name failing workflow name AND job_name failing job name AND created_at now() - INTERVAL 7 DAY AND created_at_raw 8 days ago, YYYY-MM-DD比率之外还要按小时切分同一窗口同文件的第二段查询把陈年 flake与正在发生的事故分开。结果按四种模式解读占比低、最近几小时基本全绿—— 瞬时。报告后继续。对排队中的 PR建议重新入队而非改代码代为发/trunk merge需要按安全规则先获批。最近几小时全红—— 这是事故而非 flake。如实说明停止劝人重试在归因到本仓库之前先查 GitHub 状态页平台事故会让一切其他信号退化为症状。几分钟内一批运行集中失败—— 一个共同原因不是多个 bug。去找那个被多次合并继承的坏提交或 GitHub dispatch 溢出它在运行开始前就以startup_failure失败因此完全不产生日志。数天持续稳定—— 一个有人负责的稳定缺陷即使每次出现都看起来像噪声也值得开一个 ticket。本地复现只跑最窄的命令只运行能触达该失败的最窄命令。命令形态不确定时读 hogli 技能文档 和hogli command --help。各类别的复现指引类别复现指引代码回归hogli test path/to/test.py::TestClass::test_method或hogli test file.test.tsflaky 测试移交给fixing-flaky-tests技能lint对涉及文件跑失败的 formatter/linter如hogli format:pythontypecheck跑失败的检查器如pnpm --filterposthog/frontend typescript:check快照 / 视觉跑具体的 Playwright 或 Storybook workflow必要时读playwright-test技能迁移 / schemahogli migrations:check仅当用户同意时才跑迁移代码生成漂移hogli build:openapi基础设施 / runner无本地复现。取基线率、报告、停止环境 / setup仅当廉价且与改动文件相关时复现 setup 步骤skills 构建先hogli lint:skills通过了再hogli build:skills三条硬性禁令不要无参运行hogli test不要把hogli nuke或hogli dev:reset当快捷方式不要用--no-verify绕过 hooks。PostHog CI 的四个本地化要点runner 平台大多数 PostHog job 跑在depot-ubuntu-latest或depot-ubuntu-latest-16上。Depot 运行和标准 GitHub-hosted runner 一样通过 GitHub Actions UI /gh run view出日志所以先在那里读。runner 中途死亡时无日志可读job 显示零步骤、日志 blob 404。Depot 自己的 dashboard 保留了该 job 的页面和 GitHub 丢失的判决OOM kill、runner 失联需要用浏览器打开。Depot 自身是事故源的情况由 Depot 状态页覆盖runner 层面的深度排障由depot-github-runners技能负责。Checkout之前失败即基础设施没有跑任何应用代码分类为infra / runner不要提议代码修复。分片语义PostHog CI 常把同一测试类并行到 N 个分片backend-tests (3/10)风格。复现要基于具体失败的测试路径而不是分片下标。报告格式一份可复用的汇报模板回答保持简短包含一句最可能原因避免更深的推测。技能文档给出的固定模板Target: PR #num - run run-id (workflow file) Failing job: job name Failing step: step name Command: failing command Excerpt: up to 40 lines, trimmed around the failure Classification: class from the table Shadow run: yes | no Likely cause: one sentence Local repro: exact command, or none Next action (needs your approval): - push fix | rerun job | update snapshot | none收尾纪律分类为infra / runner或 shadow run 时说明后停止不提议代码变更infra / runner还要附上基线率和是否值得重试的判断。无人值守场景master-red 事故应答把分类进一步压缩为三种可行动结论——基础设施、flaky 测试、真实回归——并以不超过约 80 词的四行回复发出一句判决点名失败 job、一行证据附运行链接、下一步该做什么或无需动作、以及你无法核实的部分。原则是错误判决的成本高于没有判决因为它会在 master 坏着的时候把人引向错误路径flaky 判决必须对照 master 历史确认回归判决必须钉到引入它的提交不推荐重跑真实回归不推荐为基础设施失败改代码。该应答由 PostHog WorkflowSlack 消息触发 一个 Create AI task 步骤驱动其搭建细节与告警方DevEx alerter之间的字符串契约见 master-red-workflow-setup.md。技能协作网络与先查已尝试清单这个技能定位为分诊与分类三个相邻领域各有归属确认 flaky 之后移交 fixing-flaky-tests它负责本地复现、根因修复与 N 次运行验证谁弄坏了 master肇事提交 修复提交移交 investigating-ci-failures产品技能位于products/engineering_analytics/skills/下直接阅读其SKILL.md即可它拥有绿/红边界分析其 investigation-queries.md 提供可复制的 HogQL指纹索引、边界查询、freshness 检查、队列运行等流水线整体健康CI 是否变慢、哪个 workflow 是长板、PR 合并要多久读 diagnosing-ci-and-merge-bottlenecks。最后是文档第一条前置规则在提议任何 CI 变更之前先查 things already tried。这份文档记录了那些听起来正确的 CI 与开发环境改法被测量、被回滚或被否决的完整经过——例如 pytest-xdist 分片内并行墙钟快 6 分钟但 CPU 成本 2.5 倍被拒、Playwright E2E 分片每分片 7.5 分钟 setup 吞掉了收益已回滚、BuildKit 全量缓存挂载热缓存下反而慢 9–12%因为 95% 的 PR 不改依赖、Docker Hub 拉取限报真因是订阅失效导致匿名 token而非凭据错误。它的用法是用提案措辞搜索rg -i xdist|parallel docs/internal/ci-things-already-tried.md每条结论附日期与具体理由结论不是禁令若当年的理由runner 规格、价格、工具版本已失效就在 PR 里写明并重新尝试。小结PostHog 的 CI 排查方法论可以压缩为一句话链先排除平台故障 →hogli ci:insights分诊state 排名 三条注意事项→gh/MCP 只读确认归属与日志细节注意合并队列特例→ 按信号表分类多信号取最具体→ 基础设施类先取基线率再下断言 → 最窄命令本地复现 → 固定模板报告、越界动作全部待批。整套流程的每个环节都有仓库内可验证的落点ci_insights的 实现 保证了退出码、scope 与 JSON 输出契约investigation-queries.md 提供了可直接执行的 HogQLci-things-already-tried.md 则让每一次改 CI 的主意都先与历史测量对账。【免费下载链接】posthog:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.项目地址: https://gitcode.com/GitHub_Trending/po/posthog创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表