Mastra 发布前变更范围探查(Release Scope Discovery)实战指南:从合并 PR 到针对性 Smoke 测试计划
【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra
本文基于 Mastra 仓库
.claude/skills/mastra-smoke-test技能体系中的发布范围探查文档(release-scope-discovery.md)撰写,完整介绍如何在 Mastra 版本发布前,通过基线定位、PR 采集、分类归组与测试计划推导,确定哪些变更需要针对性冒烟(smoke)验证,从而证明"本次实际改动的功能在发布包中可用",而非仅仅验证默认生成的示例项目还能跑通。
为什么发布冒烟测试不能只跑默认清单
Mastra 是一个以 TypeScript 为核心的现代 AI 应用与 Agent 框架,核心包 packages/core 涵盖了 Agent 循环、工具(tools)、工作流(workflows)、记忆(memory)、MCP、A2A 等大量运行时面。当仓库通过 monorepo 发布新版本(例如@mastra/core@<version>)时,两次发布之间往往合并了几十到上百个 PR,其中既有默认模板项目天然覆盖的"天气工具"这类路径,也有大量默认项目完全触及不到的改动——比如resume-stream流恢复行为、工具审批(requireApproval)、Agent Builder 持久化、Postgres 观测记忆迁移列等。
发布范围探查(Release Scope Discovery)的核心主张非常明确:不要只依赖默认的冒烟测试清单,而要用发布差异(release diff)来决定是否需要针对性检查。换言之,目标不是证明"附近的快乐路径还能跑",而是证明本次真正改动的特性或修复的 bug 在已发布包中确实生效。
在 SKILL.md 的发布冒烟工作流中,范围探查位于"发布包已发布、正式冒烟测试开始之前"的必经环节:先读本文档识别变更特性,再用默认生成项目跑基线清单,最后对默认项目覆盖不到的改动补充针对性检查。整条链路可以概括为:探查范围 → 生成计划 → 执行清单 → 补充针对性检查 → 产出报告。
第 0 步:创建带日期的冒烟测试工作区
正式采集发布产物之前,先建立一个按日期命名的工作区,把生成的 Mastra 项目、PR 列表、日志和冒烟报告放在一起,避免跨日发布时产物互相污染。
SMOKE_DATE=$(date +%F) SMOKE_DIR="$HOME/mastra-smoke-tests/$SMOKE_DATE" mkdir -p "$SMOKE_DIR/logs"如果$HOME/mastra-smoke-tests位于仓库沙箱之外,写入前需要先申请文件系统访问权限。期望的目录布局如下:
~/mastra-smoke-tests/YYYY-MM-DD/ merged-prs.tsv smoke-scope.md smoke-report.md logs/ smoke-project/ stable-smoke-project/注意布局中的两个项目目录:smoke-project用于常规(含 alpha)冒烟,stable-smoke-project则是稳定版发布专用的独立项目。如 stable-release-smoke.md 所强调,稳定版发布路径、npm dist-tags、生成项目安装路径和包版本都是独立的发布面,不能用 alpha 冒烟结果作为稳定版发布的最终签收依据,因此稳定版必须重新创建独立项目并追加单独的测试结果段落。
优先使用辅助脚本
仓库提供了现成的辅助脚本 discover-release-scope.sh,它会自动完成工作区创建、发布基线推断、PR 导出,并生成merged-prs.tsv和smoke-scope.md草稿:
.claude/skills/mastra-smoke-test/scripts/discover-release-scope.sh --release-tag '@mastra/core@1.28.0'脚本会在工作区写入merged-prs.tsv和一份带分类提示的smoke-scope.md起始文件(其内容生成逻辑见脚本第 148-170 行,包含 Workspace、Release tag、Cutoff、非 Dependabot PR 数量等元信息,以及按类别预设的待办清单)。如果工作区已存在merged-prs.tsv,脚本会先将其备份为merged-prs.previous.tsv(第 97-99 行),便于跨日对比。
第 1 步:定位上一个发布基线
首先要找到上一个稳定发布标签及其时间戳。对于 monorepo 发布,优先选择与待发布包对应的标签,通常形如@mastra/core@<version>:
gh release list --limit 20 gh release view '@mastra/core@<version>' --json tagName,publishedAt,createdAt,targetCommitish,url git show -s --format='%H %cI %s' '@mastra/core@<version>'用标签提交日期或 release 的createdAt作为合并 PR 发现的截止时间点(cutoff),并在后续的smoke-scope.md中明确记录你究竟采用了哪一个时间戳。脚本在未显式传入--release-tag时,会通过gh release list自动筛选出非草稿、非预发布且以@mastra/core@开头的最近标签作为基线(见脚本第 101-107 行),找不到时才会报错要求手动传入--release-tag或--cutoff。
第 2 步:导出截止时间以来的合并 PR
将基线以来的合并 PR 导出到带日期的工作区,默认排除 Dependabot——除非本次发布确实需要依赖相关的冒烟覆盖:
gh pr list \ --state merged \ --search 'merged:>=YYYY-MM-DDTHH:MM:SSZ -author:app/dependabot' \ --limit 200 \ --json number,title,author,mergedAt,labels,url \ --jq '.[] | [.number, .mergedAt, .author.login, .title, .url] | @tsv' \ > "$SMOKE_DIR/merged-prs.tsv"两个需要警惕的场景:
- 超过 200 条 PR:要么分页,要么按日期范围收窄,直到捕获完整集合。脚本实现中会在 PR 数量达到
--limit时向 stderr 输出警告:"Page or narrow by date range; do not silently truncate scope"(见脚本第 180-182 行),并支持用--limit参数调整上限。 - 数据交叉校验:用 first-parent 合并提交做交叉检查,防止直接推送(non-PR commit)或扁平合并造成遗漏:
git log --first-parent --oneline '@mastra/core@<previous>'..origin/main第 3 步:按运行时面分类 PR
将所有 PR 按运行时表面(runtime surface area)和冒烟含义归组。原始文档给出的分类表如下,这是整个范围探查的核心决策表:
| Category(类别) | 匹配标准 | 冒烟含义 |
|---|---|---|
| Core agent loop/streaming | packages/core/src/agent、stream/resume、消息转换、循环控制 | Agent generate + stream/resume + memory/thread 检查 |
| Tools/processors | 工具执行、动态工具、审批、processors | 工具列表/执行 + agent tool-call 路径 + 变更后的 processor 行为 |
| Workflows | workflows、suspend/resume、start-async、工作流输出 | Workflow API + Studio workflow 运行 + traces |
| Memory/observability | memory、threads、traces、scorers、logs、metrics | 记忆持久化 + trace/span/scores 验证 |
| Server/adapters/API | server、路由注册、Express/Fastify/Hono/Koa 适配器 | /health、/api/*、自定义路由、非法路由检查 |
| CLI/create-mastra | create-mastra、模板、生成依赖 | 从目标 tag/version 全新安装项目 |
| Studio/Playground UI | packages/playground-ui、packages/playground | 受影响页面的浏览器冒烟 |
| Agent Builder/auth/stored entities | 存储的 agents/skills、auth、visibility、starring、avatar、权限 | 本地无法覆盖时走带认证的 staging/cloud 检查 |
| MCP/A2A | MCP server/client/schema、A2A 协议 | MCP 端点 + 变更时配置 server/client |
| Storage/providers | Postgres、LibSQL、Redis、S3、Azure、向量存储 | 提供商安装/导入 + 可行时的定向后端冒烟 |
| Mastra Code/TUI | mastracode、subagents、slash 命令 | 独立的 Mastra Code 冒烟;默认 create-mastra 不覆盖 |
| Docs/examples only | docs、examples | 文档/示例校验;示例可执行时才做运行时冒烟 |
这些类别在仓库源码中有清晰的对应物。例如"Core agent loop/streaming"对应的正是 packages/core/src/agent 目录下的 agent.ts、stream-until-idle.ts 与 thread-stream-runtime.ts 等实现;"Tools/processors"对应同目录下的 tool-approval.ts(工具审批逻辑);"Mastra Code/TUI"则对应 mastracode 目录。测试层面,stream-until-idle.test.ts 等测试文件正是判断变更是否触及流式路径时的源码级参照——分类时可以结合 PR 改动的文件路径落在上述哪些目录/模块,快速推断其类别。
第 4 步:把分类转化为冒烟计划
以完整冒烟为基线,但不要停留在默认生成项目的快乐路径上。对每一个实质性 PR,都要追问四个问题:
- 本次改变了哪些用户可见行为、API 行为、持久化行为或集成路径?
- 生成的冒烟项目是否会执行这条精确路径?
- 如果不会,能够证明该变更行为的最小针对性检查是什么?
- 哪些证据能证明"修复生效了",而不仅仅是"应用没有崩溃"?
如果默认项目无法覆盖变更特性,要么补充针对性检查,要么明确记录"该环境为何无法测试"。
针对性检查模式
对于常规变更特性,文档指向 targeted-feature-smoke.md;对于存储/提供商 schema 或迁移变更,指向 storage-provider-migration-smoke.md。二者的共同心法是:冒烟最小真实场景,避免用"Agent 聊天正常"来替代流式修复、用"工具列表能加载"来替代工具审批修复、用"Studio 能打开"来替代持久化修复。比如:
- 流式修复 → 调用
/stream或resume-stream,检查事件块(chunks)与最终响应结构; - 工具审批/动态工具修复 → 配置对应工具模式,触发一次 agent 调用,验证批准/拒绝或动态解析行为;
- 工作流修复 → 运行被改动的具体模式(suspend/resume、后台进度、长时运行输出形状);
- Studio 持久化修复 → 修改受影响表单字段、保存、重载/重新拉取,验证字段值确实持久化;
- 观测性修复 → 生成受影响运行类型,验证 trace/span/scores/logs 包含修正后的数据;
- CLI/create 修复 → 用已发布 CLI 创建全新项目,验证生成文件/依赖/脚本符合预期。
存储迁移类检查则要"起真实后端、造旧 schema、重启验证修复":用 Docker 起 Postgres,安装@mastra/pg@alpha(或稳定版@mastra/pg@latest)到冒烟项目,模拟修复前的缺失列/表/索引,重启 dev server 让 provider init/migration 从发布包运行,再验证缺失结构被恢复,并跑一条真实的读写 API/UI 流程。smoke-report.md中要记录后端镜像与版本、包版本、schema 变更、验证查询与 API 结果。
Coverage vs Changes 表
在测试开始前,先把下述对照表写进$SMOKE_DIR/smoke-scope.md:
| Feature / PRs | 生成项目覆盖? | 需要执行的针对性检查 | 结果/省略原因 |
|---|---|---|---|
示例:resume-stream | 否 | 启动 stream 后调用 resume-stream,验证恢复的 chunks/最终响应 | PASS/FAIL 或受阻原因 |
| 示例:工具审批变更 | 否 | 配置带requireApproval的工具,从 agent 触发,批准/拒绝,验证变更后的审批行为 | PASS/FAIL 或受阻原因 |
| 示例:Playground 保存持久化 | 否 | 编辑受影响的 Studio/Agent Builder 表单,保存,重载/重新拉取,验证变更字段已持久化 | PASS/FAIL 或受阻原因 |
| 示例:PG OM 迁移列 | 否 | Docker 起 Postgres,冒烟项目配置@mastra/pg,删掉旧/缺失列,重启验证迁移恢复且 memory/OM 写入成功 | PASS/FAIL 或受阻原因 |
| 示例:默认天气工具 | 是 | Agent/工具冒烟 | PASS |
把范围分析落盘:smoke-scope.md 的必备内容
在运行任何测试之前,必须把范围分析写入$SMOKE_DIR/smoke-scope.md,避免分析结果只存在于终端输出里。文档要求至少包含:
- 发布基线标签与截止时间戳(cutoff timestamp);
- 采集 PR 所用的命令;
- 分类后的 PR 表(含 PR 号、标题、作者、合并时间、类别);
- 由分类推导出的针对性冒烟计划;
- 覆盖 vs 变更对照表:哪些被生成项目天然覆盖、哪些需要针对性检查;
- 被省略的 PR/提交及原因:包括 Dependabot、直接非 PR 提交、纯云功能、缺少凭证、以及 create-mastra 之外的产品域。
在跑测试之前,先把类别摘要与覆盖 vs 变更摘要报告出来,让用户清楚每个针对性检查为什么被纳入、默认冒烟项目在哪里力不能及。这与 SKILL.md 中的强制测试清单(setup、agents、tools、workflows、traces、scorers、memory、MCP、errors 为必跑项)形成配合:清单保证基线完整,范围探查保证变更特性不被遗漏。
实战要点与常见误区
- 基线选错是最大的隐性风险:cutoff 若晚于实际变更提交,PR 采集就会漏掉本次发布的核心改动;务必用
git show交叉确认标签提交,并在 smoke-scope.md 里写明所用时间戳。 - Dependabot 默认排除:除非本次发布明确需要依赖冒烟覆盖,否则默认排除
author:app/dependabot,避免噪声淹没实质变更。 - 不要静默截断:PR 达到 200 上限时,脚本会显式告警。分页或按日期收窄后补全,绝不能"假装采集完整"。
- 默认项目覆盖不等于变更覆盖:天气工具跑通只能证明模板路径健康;
resume-stream、工具审批、Agent Builder 持久化、存储迁移这些默认模板触碰不到的面,必须靠针对性检查补位。 - 稳定版要独立成段:稳定版发布后需在同一个带日期工作区内另建
stable-smoke-project,追加独立的测试结果段落,并明确记录被测包版本,不能与 alpha 结果混在一起。 - 先落盘再执行:scope 分析先写入
smoke-scope.md,测试前的类别摘要与覆盖摘要先同步给用户,再开始跑测试。
总结
发布范围探查解决的是发布冒烟测试中最关键的信息差问题:这次发布到底改了什么,默认项目又覆盖了什么。通过带日期工作区、release 基线与 cutoff、gh pr list采集、按运行时面分类、四问转化、Coverage vs Changes 对照表这一完整闭环,Mastra 的发布冒烟从"机械地跑一遍默认清单"升级为"围绕真实变更设计证据链"。结合仓库中的 discover-release-scope.sh 辅助脚本、targeted-feature-smoke.md 与 storage-provider-migration-smoke.md 两个分支模式,这套方法论可以直接复用于任何基于 GitHub Releases + npm 发布流程的 TypeScript monorepo 项目。
【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考