ARTICLE DETAIL

资讯详情

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

Metabase QABot 合并前自动 QA 工作流解析:`/qabot` 命令编排、独立运行目录与六阶段缺陷复现体系

Metabase QABot 合并前自动 QA 工作流解析:`/qabot` 命令编排、独立运行目录与六阶段缺陷复现体系 Metabase QABot 合并前自动 QA 工作流解析/qabot命令编排、独立运行目录与六阶段缺陷复现体系【免费下载链接】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/metabaseQABot 是 Metabase 仓库中一套用于合并前pre-merge质量把关的自动化 QA 工作流它以 Claude Code 自定义命令/qabot为入口让 AI Agent 直接在本仓库、对着本地正在运行的 Metabase 实例分析当前分支先于合并找出 bug、边界问题、安全缺陷与 UX 问题。读完本文你将掌握这条工作流从“时间戳运行目录生成”到“分严重度缺陷报告与修复计划产出”的完整编排链路理解其输出目录隔离、模板化 Prompt 生成、静态审查与动态复现相结合的分级方法并能在自己项目中复刻这套“AI 合并前审查”的工程模式。QABot 是什么合并前的只读守门人在 Metabase 的日常研发中一个分支在合并进master之前QABot 会被触发对分支改动做一轮完整的 QA 分析。其定位明确写在其 Agent 提示词 dev/bot/qabot-agent.md 中You are a pre-merge QA bot. Your job is to find bugs, edge cases, security issues, and UX problems in the changes on this branchbefore they are merged. You do NOT fix anything — you find and report.核心设计原则有三只读守门而非修复QABot 只负责发现并报告问题绝不修改任何源码修复由后续的 fixbot 工作流承担。直接跑在真实实例上它直接运行在当前项目里对着本地已启动的 Metabase 服务后端 前端做动态验证而不是纯静态推理。隔离运行每次/qabot调用都必须落在独立的运行目录.bot/qabot/TIMESTAMP/中同一仓库可同时存在多次互不冲突的调用。如果想针对某个指定分支在隔离的 worktree 独立后端/前端中跑同样分析/qabot文档还提示使用/autobot branch /qabot其调度入口定义在 .claude/commands/autobot.md见下文“与 autobot / 远程 PR 环境的协同”。一次/qabot调用的整体编排.claude/commands/qabot.md 本身是一个编排器orchestrator命令它把整个流程拆成 4 个显式步骤生成每次运行的独立目录—— 用YYYYMMDD-HHMMSS时间戳建出唯一的OUTPUT_DIR收集上下文—— 先跑 discover 生成config.env再读取 Linear issue / PR 描述等背景生成 Agent 提示词—— 调用mage -bot-generate-prompt用模板填充本次运行的变量执行—— Agent 读取生成的prompt.md按其中的 Phases 1–6 顺序执行完所有阶段。其中第 4 步的“Phases 1–6”实际由模板文件 dev/bot/qabot-agent.md 承载——它是一份 600 多行的“Agent 任务书”定义了六个阶段的完整方法论。因此整套工作流本质是薄编排层命令文件 厚方法论文档模板 Clojure 工具支撑mage bot 系列命令的三层结构。第一步为每次运行生成独立的输出目录/qabot首先要求生成一个YYYYMMDD-HHMMSS格式的时间戳如果 Agent 知道当前墙钟时间直接构造否则运行./bin/mage -bot-timestamp明确禁止直接调用date命令保持所有时间来源统一、可审计。随后设置两个环境变量作为本次运行的主干TIMESTAMPYYYYMMDD-HHMMSS OUTPUT_DIR.bot/qabot/TIMESTAMP硬性约束本次运行写入的所有文件——包括 discover 阶段的产物——都必须位于OUTPUT_DIR/之下且不同运行之间不得共享任何路径There must beno shared paths across runs。这意味着多人在同一仓库先后调用/qabot不会互相覆盖证据文件目录名自带时间戳天然成为审计/追溯依据运行结束后的产物截图、API 响应、报告可以整体拷贝或归档。这个“per-run 隔离目录”思想在整套 bot 体系里被反复强调discover 文档 .claude/commands/qabot-discover.md 同样规定“Discover never picks a directory itself, so nothing is ever written to a shared.bot/qabot/...location”——路径永远由调用方/qabot或/autobot传入--output-dir。第二步discover 收集上下文并落盘config.env如果OUTPUT_DIR/config.env不存在编排器先调用 discover 阶段/qabot-discover $ARGUMENTS --output-dir OUTPUT_DIRdiscover 会把产物直接写进OUTPUT_DIR/绝不写共享位置。随后读取三个文件文件内容可能缺失的情况OUTPUT_DIR/config.env提取LINEAR_ISSUE_ID、TIMESTAMP等键值不应缺失OUTPUT_DIR/linear-context.txtLinear issue 的完整内容未解析到 issue 时不存在OUTPUT_DIR/pr-context.txtPR 标题与正文当前分支没有 PR 时不存在根据 .claude/commands/qabot-discover.mddiscover 内部还完成了几项关键工作解析/检测 Linear issue若调用参数带了MB-12345这类 ID按[A-Z]-[0-9]校验否则从当前分支名按*/prefix-NNNNN-*不区分大小写提取前缀是 2–4 字母的团队代号MB、BOT、UXW、EMB、QB、DEV、GHY、GDGT……再退而通过gh pr view --json title,url,body从 PR body 里找 Linear 链接仍找不到则置空——不询问用户因为这是非交互式发现步骤。拉取上下文issue 命中后运行./bin/mage -bot-fetch-issue ISSUE_IDPR 存在则gh pr view --json title,body。校验分支是否偏离 mastergit log --oneline origin/master..HEAD为空时在config.env追加BRANCH_WARNINGno-local-commits。写结果QABot 一律固定使用 postgres 应用库它测试的是分支改动本身而非数据库专属 bug最终写出的config.env形如APP_DBpostgres LINEAR_ISSUE_IDresolved-id-or-empty TIMESTAMPTIMESTAMP OUTPUT_DIROUTPUT_DIR第三步用 mage 模板引擎生成 Agent Prompt编排器不把上下文直接粘贴进对话而是引用 discover 目录里的文件通过mage的一条命令完成“模板 变量 文件内联”./bin/mage -bot-generate-prompt \ --template dev/bot/qabot-agent.md \ --output OUTPUT_DIR/prompt.md \ --set TIMESTAMPTIMESTAMP \ --set OUTPUT_DIROUTPUT_DIR \ --set LINEAR_ISSUE_IDresolved-id-or-empty \ --set-from-file LINEAR_CONTEXTOUTPUT_DIR/linear-context.txt \ --set-from-file PR_CONTEXTOUTPUT_DIR/pr-context.txt关键参数语义--template模板路径这里是 dev/bot/qabot-agent.md--output生成的 prompt 落点。--set KEYVALUE做纯文本替换。若 VALUE 含 shell 特殊字符parse-set-args会先检查是否含缺的条目会被警告并忽略见 mage/src/mage/bot/prompt.clj。--set-from-file KEYPATH读取该文件并把全文内联为模板变量值实现见 prompt.clj。若文件不存在——比如 discover 没找到 Linear issue 或 PR——变量会退化为空字符串这正是期望行为无需报错。这样既避免了把多行文本 shell 转义进命令行也天然处理了“可选上下文缺失”的情形。模板的两种占位符prompt.clj 的实现揭示了模板引擎的两个机制{{KEY}}值替换先用--set-from-file/--set构造 replacements 映射再按 key 逐一替换{{FILE:path}}文件内联以仓库根为基准解析路径并 slurp 进模板。模板 agent 文件里就大量使用了这一机制例如{{FILE:dev/bot/common/environment-discovery.md}}把 environment-discovery.md环境/实例/REPL/日志访问手册、reproduction-strategies.md、metabase-patterns.md、ux-evaluation-criteria.md等公共章节按需注入。实现中只做单遍扫描——被 include 的内容不会再递归解析其中的{{FILE:...}}标记避免了循环引用风险路径缺失时替换为!-- FILE NOT FOUND: ... --注释并告警。generate-prompt!还会在写盘前自动mkdirs父目录并打印Wrote prompt: pathprompt.clj因此--output指向尚不存在的OUTPUT_DIR时也无需手工建目录。第四步执行 Phases 1–6 的完整 QA 方法论生成的prompt.md就是 Agent 本次运行的任务书。六个阶段的方法论全部来自模板 dev/bot/qabot-agent.md要求 Agent在单次对话内顺序跑完所有阶段除非命中 STOP 条件。值得一提的是Agent 被要求用“醒目横幅”与用户交互获取输入、报告阻塞、呈现最终报告时横幅如╔══════════════════════════════════════════════════════════════╗ ║ QABOT — STATUS ║ ╠══════════════════════════════════════════════════════════════╣ ║ your message here ║ ╚══════════════════════════════════════════════════════════════╝Phase 1Git Diff 上下文确认分支确实含改动先git log --oneline origin/master..HEAD为空则查远端分支git log --oneline HEAD..origin/branch-name必要时git merge --ff-only origin/branch-name本地与远端发散时需在报告中注明“动态测试可能不反映 PR 改动”。收集全部改动三条 diff 必须全跑互相不可替代git diff origin/master...HEAD—— 已提交改动git diff—— 未提交改动可用git status确认git diff --cached—— 已暂存改动git log --oneline origin/master..HEAD—— 提交历史。按领域分组文件BackendClojuresrc/、enterprise/backend// Frontendfrontend/src// API routesdefendpoint与api/路径/ Migrationsresources/migrations// Teststest/、frontend/test/、e2e// Config 及其他。结合 Linear/PR 上下文理解“本意”通常 PR 描述是最佳的行为预期来源。分析测试覆盖对每个改动区域记录“测了什么 / 没测什么 / 代码与测试之间的缺口”驱动后续阶段把精力集中在未覆盖路径上。同时警惕形如(with-redefs [foo (fn [ _] (throw ...))] ...)的“禁令测试”断言某函数不被调用、某路径不被走通——它锁定了一条新的“禁止”要在 Phase 2 一并分析。从 E2E 测试学习 UI 交互模式e2e/目录下的*.cy.spec.ts是“如何操作 UI”的现成范例点击顺序、输入文本、等待条件但只是出发点真正的 bug 往往藏在用户偏离 happy path 的地方。将 diff 摘要写入OUTPUT_DIR/diff-summary.md。Phase 2静态代码审查Code AnalysisPhase 2 的核心方法论可以浓缩为几个“审查透镜”Anti-anchor反锚定动手前先在initial-review.md写下“这个 patch 可能错的三条理由”而不是“它看起来对的三条理由”。想不出三条合理失败模式 还没看懂 patch。小、测试全、风格干净的代码只证明“用心”不证明“正确”。“每条新禁止都是一条新需求”这是整个审查中最重要的透镜。任何收窄原先允许范围的改动新 guard、新 early-return、新when、新if条件、新前置校验、cond 新增过滤分支、收紧 spec、禁令测试、移除调用点都必须回答 5 个问题旧规则一句话是什么新规则一句话是什么逐条列出落入旧且不满足新的具体记录/用户/流程/调用方/部署状态每个被排除案例是有意为之吗PR 描述/Linear issue 是否提及它是否可被合法用户旅程触达是 → 即使 diff 很小、测试全绿也要按 SEVERE 报输入分支粒度分析而非只遍历调用方类似(or discovery-path manual-path)的输入分支可能身处相反的授权上下文一端是攻击者可控制的远端 OIDC discovery 文档另一端是管理员在设置页录入的 URL对同一函数正确的 guard 对另一端可能是回归。要求把每个输入分支写成字面量 bulleted list 记入initial-review.mdcond/case/解构 shape/变参 arity 一视同仁。寻找可触发的具体 bug围绕逻辑与正确性off-by-one、nil 处理、竞态、错误被吞、隐式类型转换、边界空集合、缺失/多余字段、Unicode 与超长串、并发重复请求展开并建立“困惑用户输入数字字段填banana/1e999、全空白串、粘贴隐藏字符如零宽空格/智能引号、Integer.MAX_VALUE/NaN、重复提交、endstart与恶意输入SQL 注入、XSS、路径穿越、SSRF 指向169.254.169.254/file://、命令注入、模板注入{{7*7}}、同形字/RTLO、超大输入、CRLF 注入、跨租户 IDOR两大类词典。规则是每个用户可达输入至少各挑一类尝试发现“前端校验了但后端没校验”即使当前无 UI 路径也要按API_ROBUSTNESS上报。针对 Clojure 后端的健壮性清单并发与线程安全atom/agent/ref、资源生命周期、依赖失败时的恢复、无界增长队列/缓冲/重试、事务语义嵌套事务、savepoint、after-commit 回调、大表上的迁移锁问题。安全观测性对每个新安全 guard 追问“它触发时在服务器日志里长什么样”——若被阻断的攻击与普通网络抖动产生同一行日志按GOOD_TO_FIX上报并建议区分化的 WARN/ERROR 日志含被阻断 URL或独立 metric 计数器。状态机回归的真值表穷举相关状态组合对比新旧行为且必须包含迁移行“记录处于 A → 执行动作 X → 到 B”不只列状态行。对“首次登录/首次 SSO 握手/首次同步”这类翻转 bit 的事件尤其警惕。Flag-writer census新逻辑若以某字段值作为门控如sso_source :ldap必须用 Grep 枚举该字段的所有写入方t2/update!、t2/insert!、裸 SQL、resources/migrations/下的迁移。若唯一写入方正是被门控的流程本身该门控会制造bootstrap deadlock存量记录永远无法进入“被放行”桶——这按 SEVERE 上报。每个 finding 都要记录文件与行区间、类别、UI reachable 与否、描述、复现假设、置信度写入initial-review.md。若没发现任何潜在 bug则写入一句结论并直接跳到 Phase 4。缺陷分级体系贯穿 Phase 2 的关键规则类别判定标准SECURITY认证绕过、数据泄露、注入等安全问题即使只能走 API也算 SECURITYSEVERE影响真实用户、能通过 UI 触发的回归——判定标准是“有没有一条改动前合法、改动后失效的legitimate user journey”会随升级破坏存量客户既有工作流GOOD_TO_FIX挡住了坏路径但错误处理难看堆栈代替干净的 401、误导性错误信息、响应泄漏内部 URL、500 代替结构化错误攻击者场景下的干净 500 不是用户回归API_ROBUSTNESS只有直接调 API 才能触发当前 UI 无路径的崩溃/错误结果/未处理输入对 SDK 用户、集成方与未来 UI 有价值TRIVIAL一句话即可描述的小问题非 finding缺测试、缺文档、缺注释、“应该重构”、建议加日志、泛泛的“这模块很复杂”——只报 bug不报流程缺口Phase 3动态复现问题对 Phase 2 中置信度MEDIUM 及以上的每条 finding 做动态验证同时把精力多花在 Phase 1 标记的未测试路径上。当改动用户可达时优先通过 UI 复现——因为真实用户流程能告诉你用户会不会撞上、看到什么错误、UI 其他状态是否被破坏REPL/API 复现最快但只是辅助证据。常用工具链UI 问题用 Playwright MCP 导航、操作、截图关键节点分别存 baseline / after / error 三张图到{{OUTPUT_DIR}}/output/文件名形如issue-01-before.png每张截图前用browser_evaluate执行window.location.href记录当前 URL含 query 参数并写入文件名或作为附图说明。后端/API 问题一律走./bin/mage -bot-api-call禁止裸curl它会触发权限提示且需手工拼 URL支持--api-key、--method、--body、--raw等参数响应重定向到 stdout 存证./bin/mage -bot-api-call /api/user/current --api-key $ADMIN_API_KEY ./bin/mage -bot-api-call /api/endpoint --method POST --api-key $ADMIN_API_KEY --body {key: value} ./bin/mage -bot-api-call /api/endpoint --api-key $ADMIN_API_KEY {{OUTPUT_DIR}}/output/api-name.json-bot-api-call把诊断前缀打到stderrGET /api/... (port 3000)、Status: 200JSON 主体打到stdout因此... | jq .email直接可用不需要任何 stderr 输出时加--raw。后端逻辑问题用./bin/mage -bot-repl-eval form直接调函数、测边界nil/空集合/类型强转、验证 DB 状态如(t2/select-one :model/Setting :key some-key)。wrapper 会自动发现后端本地 nREPL、PR-env 下 socket REPL并缓存到.bot/repl.env不要直接调clj-nrepl-eval它在 PR-env 模式会静默失败。每条调用发一个顶层 form多 form 用(do ...)包裹。复现中建议对相关 namespace 提日志级别(logger/set-ns-log-level! metabase.some-ns :debug)→ 复现 → 捕获日志 → 复位。需要测启动行为或不同设置时用(dev/restart!)并等待健康检查通过。每条 finding 最后要落一个动态状态并写入initial-review-results.md状态含义CONFIRMED已动态复现REPL/API/浏览器触发并观察到错误行为是金标准CONFIRMED_STATIC读源码确认 bug 存在但未动态复现需说明原因SUSPECTED无法触发但代码分析强烈暗示是 bug说明尝试过程与触发条件NOT_REPRODUCED实测发现代码处理正确说明原担忧为何不成立BLOCKED缺少数据/环境无法测试说明需要什么Phase 4UX / 可用性评审纯后端 diff 也必须做完整 UX 评审——后端改动可能透过 API 响应形状、错误流、权限、认证、查询变慢引发前端异常行为。评审路线从 diff 定位受影响的 UI 页面/组件直接前端改动或经由 API 间接影响的与行为发生变化的 API endpoint复用 Phase 1 的测试覆盖分析把 UX 实测火力集中在弱覆盖区域按共享的 UX 评估清单见 dev/bot/common/ux-evaluation-criteria.md在浏览器中逐项核对加载/错误态、表单校验提示、可访问性aria、键盘导航等顺带记录做得好的部分——报告应保持平衡每轮显著交互后用(logger/messages)或/api/logger/logs检查服务器日志里的意外报错、N1 查询、被吞异常与可能引起 UI 卡顿的慢操作证据截图/API 响应/日志摘录统一进{{OUTPUT_DIR}}/output/评审结论写ux-review.md。Phase 5最终报告写报告前先做一轮自我审计即使当前 finding 列表为空也不能跳过空列表恰恰是自我审计价值最高的时候Bootstrap checkPR 读的每个状态是否存在不经过被门控路径的写入方没有则可能死锁。Transition checkPR 保留不变的“before”状态是否只能作为通往被阻断状态的过渡点被触达Prohibition test check对 PR 新增的“X 必须不发生”测试重新推导它为何正确是否误伤了合法用户旅程。Rollout check管理员把这个 PR 部署到有真实用户的存量实例后会不会有某类用户立刻失去昨天还能做的事说出具体用户类别。Writer census check对新代码读取的每个字段列出全部写入方列表短于预期就重新审视门控。随后读取initial-review-results.md与ux-review.md产出report.md结构模板见 dev/bot/qabot-agent.md 的 Phase 5 章节先写 Summary含分支/commit/Linear issue/PR 信息与 2–3 段分支行为描述若没有任何 actionable findingsSummary 要真诚地肯定代码质量再按SECURITYSEVEREGOOD TO FIXAPI ROBUSTNESSSUSPECTED BUT UNCONFIRMEDTRIVIAL分组给出每条 finding 的复现步骤、代码引用file:line、截图/API 响应与影响评估最后是 What Works Well。某分组无 finding 就整体省略该节不写 None found。超过 100 行的 API 响应不内联改为引用output/下的文件。报告生成后转 PDF./bin/mage -bot-md-to-pdf {{OUTPUT_DIR}}/report.md最终向用户展示report.pdf、report.md的绝对路径若有 Phase 6 产物则还有fix-plan.md并按“有无 actionable findings”二选一展示完成横幅与按类别的 finding 统计。Phase 6修复计划只有报告存在SECURITY/SEVERE/GOOD_TO_FIX时才生成fix-plan.mdTRIVIAL不值得专项修复全空则整阶段跳过。计划按严重度排序每条必须可执行点名具体文件与函数、说明建议改什么、给出验证途径并自包含到“只看本文件加代码库即可实施修复”的程度报告末尾再引用fix-plan.md后重新生成 PDF。输出目录与证据规范整套工作流对“证据”的要求贯穿始终所有截图、API 响应 JSON、日志摘录、中间产物统一落在{{OUTPUT_DIR}}/output/与{{OUTPUT_DIR}}/tmp/后者仅放 prompt 片段等中间文件无证据不上报——每条 finding 必须有截图、API 响应或具体代码引用报告内嵌图片一律用相对路径且图注必须带完整 URL含 query 参数例如/question/42?filterstatus — filter dropdown broken环境信息不硬编码端口、凭据、API key 一律从./bin/mage -bot-server-info现场发现实例首次启动时会经由配置文件自动建用户与 API key无需手工/api/setup。与 autobot / 远程 PR 环境的协同/qabot的另一种形态是把它作为“内部命令”挂进 autobot 会话.claude/commands/autobot.md/autobot branch /qabot会为分支创建独立 worktree、起好本地 dev 环境tmux 面板跑后端 前端再把/qabot当作会话提示词交给 Claude。autobot 会先为分支解析 PR 环境并做基础设施预检然后同样以时间戳生成.bot/qabot/TIMESTAMP运行目录并调用 discover。若目标是PR 预览环境https://prNUMBER.coredev.metabase.com形态则进入 remote 模式没有本地数据库与前端API 经-bot-api-call透明转发并自动刷新会话REPL 走远程 socket REPL重启后端不可能破坏性测试改site-url、删连接、清缓存等需遵守“快照 → 变更 → 还原 → 确认”的模式无法还原就不做动态复现、改记CONFIRMED_STATIC。这类预览环境仅限 Metabase Tailscale 网络可达且通常与 PR 作者及其他 bot 会话共享因此只读验证优先。可复用的工程模式小结从整套 QABot 工作流中可以提炼出几条放之四海皆准的“AI 合并前审查”模式编排与执行分层薄薄的 orchestrator 命令只负责建目录、收集上下文、渲染 prompt厚重的评审方法论放在模板文件中按需{{FILE:}}注入避免每个命令文件臃肿。运行隔离是底线时间戳目录 “一切产物必须落在本次目录 禁止共享路径”让并发运行、审计归档都变得安全廉价。静态审查要“攻击优先”anti-anchor先写三条它为什么错、把每条新禁止当作新需求并要求枚举被排除对象、区分输入分支而非只查调用方——这三招把审查重心从“确认作者没写错”扭转到“证明它没错”。分级避免信号淹没SEVERE 只留给“升级会破坏真实用户既有流程”的回归攻击者场景的难看错误归GOOD_TO_FIX只有 API 可达的归API_ROBUSTNESS——让真正的严重问题不被卫生问题淹没。动态状态机让证据可比较CONFIRMED / CONFIRMED_STATIC / SUSPECTED / NOT_REPRODUCED / BLOCKED让“试过、看到什么、差在哪”全程可追溯。报告与修复分离且各自自包含只读守门人产出带完整复现步骤的分级报告再生成另一 Agent 可直接执行的fix-plan.md恰好呼应本仓库 fixbot/reprobot/uxbot 的分工体系——同一套.claude/commands/与dev/bot/家族还管理着/fixbot修复已报告问题、/reprobot复现 issue、/uxbotUX 聚合等相邻工作流方法论同源、命令格式统一。【免费下载链接】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),仅供参考
返回列表