Mastra 仓库 PR 工作流实战:用 changeset 生成变更集并用 gh CLI 提交 PR
【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra
本指南以 Mastra 仓库内
.opencode/command/pr.md中的自动化开发指令为骨架,完整讲解 Mastra monorepo 的提交流程:如何用 changeset CLI 为每个发生变更的包生成独立变更集文件,以及如何用 GitHub CLI 在当前分支上打开 PR。读完本文,你将掌握pnpm changeset的参数语义、版本升级规则(major/minor/patch)、面向开发者的 changelog 文案写作规范、多包变更的拆分原则,以及gh命令打开 PR 的完整套路,并能在源码层面理解这套流程背后的实现原理。
一、背景:Mastra monorepo 的版本管理与 PR 流程
Mastra 是一个基于 pnpm + turbo 的 monorepo(见根目录 package.json),包含@mastra/core、@mastra/memory、mastra、create-mastra等大量 npm 包。在发布时,仓库需要为每个发生变更的包生成独立的 changelog,并最终合并为随每个版本发布的单一 changelog。这正是 changesets 工具链的职责。
.opencode/command/pr.md定义了一条完整的「改完代码 → 打变更集 → 开 PR」的自动化工作流,共分两步:
- 使用 changeset CLI 创建变更集(changeset);
- 使用 GitHub CLI(
gh)打开 PR。
整个流程面向 AI Agent 自动化执行,但也同样适用于人类开发者手动提 PR。下文按原文档的骨架逐步展开,并补充仓库源码层面的实现细节。
二、第一步:使用 CLI 创建 changeset
2.1 基本命令
pnpm changeset -s -m "your changeset message" (--major | --minor | --patch) pkg-name该命令通过根目录package.json中的脚本"changeset": "pnpm --filter @internal/changeset-cli start"指向仓库自研的变更集 CLI(内部包 @internal/changeset-cli,位于packages/_changeset-cli),并非直接调用上游@changesets/cli(虽然changeset-cli脚本仍保留了对原生changeset的直连入口)。
每个发生变更的包都要运行一次 CLI,并指定该包对应的版本升级类型(--major、--minor或--patch)和消息。每次运行会为每个包生成一个独立的 changeset 文件,这对于生成准确的 changelog 至关重要。
2.2 参数说明
| 参数 | 含义 | 说明 |
|---|---|---|
-s/--skipPrompt | 非交互式运行 | 用于自动化;使用该参数时必须同时提供--major、--minor或--patch中的至少一个 |
-m "message"/--message "message" | changeset 消息 | 必填 |
--major pkg-name | 需要进行 major 版本升级的包 | 可重复指定多个包 |
--minor pkg-name | 需要进行 minor 版本升级的包 | 可重复指定多个包 |
--patch pkg-name | 需要进行 patch 版本升级的包 | 可重复指定多个包 |
从源码看,参数解析由packages/_changeset-cli/src/index.ts中的parseArguments完成,它使用mri解析--message(别名-m)、--skipPrompt(别名-s)、--major/--minor/--patch,其中major/minor/patch会被统一规整为字符串数组,从而支持「重复标志指定多个包」的用法。
2.3 使用要点
- 升级类型必须显式指定:每个包都需要明确的升级类型;非 patch 升级必须使用
--major或--minor。 - 多包可通过重复标志指定:例如
--minor @mastra/core --minor mastra。 - 自动化场景下
-s的约束:当使用--skipPrompt时,如果未提供任何--major/--minor/--patch,CLI 会直接报错退出。这一校验同样体现在 index.ts 中:--skipPrompt模式下检查major/minor/patch三个数组是否至少有一个非空,否则输出Please provide at least one of --major, --minor, or --patch flags when using --skipPrompt.并退出。
2.4 版本升级类型(Version Bump Types)
| 类型 | 适用场景 |
|---|---|
patch | 向后兼容的 bug 修复(bugfixes with backward-compatible changes) |
minor | 向后兼容的新功能(new features with backward-compatible changes) |
major | 不向后兼容的破坏性变更(breaking changes that are not backward-compatible) |
2.5 源码级运行流程
packages/_changeset-cli/src/index.ts中main()的完整执行链依次为:
- 检测变更包:
detectChangedPackages()调用 getChangedPackages,底层使用@changesets/git的getChangedPackagesSinceRef对比origin/main(失败时回退到main)找出有改动的包目录,再与「公开包列表」(package.json中private不为 true 的包,见 getPublicPackages)做交集匹配,返回包名、路径与当前版本。 - 无变更则提前退出:没有检测到变更包时,输出
No changed packages detected. Exiting.并正常退出。 - 准备升级输入:
prepareVersionBumpInputs会把命令行传入的major/minor/patch与自动检测到的变更包合并去重(自动检测的包默认归入patch,除非被显式指定为major/minor)。 - 交互式确认(非
-s模式):getVersionBumps 基于@clack/prompts提供三步交互:选择要纳入的包 → 选择 major 升级的包 → 选择 minor 升级的包(剩下的自动归入 patch)。每个包最终只能属于一种升级类型。 - 收集消息:getChangesetMessage 会在编辑器中打开一个带注释的模板(模板中预先列出「将应用的版本升级」清单,例如
# @mastra/core: patch),以#开头的行会被忽略,空消息会中止流程。 - 写入 changeset 文件:createCustomChangeset 调用
@changesets/write的writeChangeset,把{ releases, summary }写入.changeset/目录,生成带唯一 ID 的 Markdown 文件(如.changeset/agent-entry-structured-output-guard.md),并返回该 changeset 的 ID。消息为空或未指定任何版本升级时,函数会直接抛出错误。 - 同步 peerDependencies:
updatePeerDependencies会按版本升级结果更新受影响包的 peer 依赖(见 versions/updatePeerDependencies.ts),并最终通过getSummary打印汇总信息。
三、变更集消息(Changeset Message)写作规范
变更集消息的最终消费者是开发者,它会被写进 changelog。因此消息写作有一套明确的准则:
- 面向开发者,写简短、直接的句子,任何人都能看懂;避免 commit message 风格、技术黑话和缩写。
- 使用动作导向动词:
Added(新增)、Fixed(修复)、Improved(改进)、Deprecated(弃用)、Removed(移除)。 - 避免空泛短语:不要写 "Update code"(更新代码)、"Miscellaneous improvements"(杂项改进)、"Bug fixes"(修复 bug)这类没有信息量的内容。
- 突出结果:要说明对最终用户来说发生了什么变化,而不是聚焦内部实现细节。
- 补充上下文:相关时添加指向 issue 或 PR 的链接。
- 破坏性变更或新功能必须附代码示例:示例应展示公共 API 的前后用法对比(before / after),不要展示内部实现细节。
- 排版易读可扫读:必要时使用要点列表或多段落;小节标题用加粗文本,不要使用 Markdown 标题。
- 对更重大的变更,还需要回答变更背后的「为什么」(Why)。
仓库中真实的 changeset 文件是很好的范例,例如.changeset/agent-entry-structured-output-guard.md:
--- '@mastra/core': patch --- A workflow `.agent()` step that declares `structuredOutput.schema` now fails when the agent finishes without producing an object, instead of silently reporting `success` and returning `{ text }`. The step throws a `MastraError` (`STRUCTURED_OUTPUT_OBJECT_UNDEFINED`) carrying the `finishReason`, matching how the rest of the agent stack guards missing structured output. A validly-parsed falsy object (e.g. `0`) is still treated as produced, and steps without a declared schema are unaffected. Fixes #23403.该文件展示了完整结构:frontmatter 中声明变更包与升级类型('@mastra/core': patch),正文描述行为变化、影响范围与对应的 issue 编号,既面向最终用户又提供了可追溯的上下文。
四、多包变更:必须拆分多个 changeset 文件
如果一次改动横跨多个包(例如@mastra/core、@mastra/memory、mastra共 3 个包),且每个包的改动内容不同,必须创建多个 changeset 文件,否则会把互不相关的变更混入同一个文件中。做法是:
- 先判断哪些「逻辑分组」存在;
- 多次运行 CLI,为每个分组分别选择相应的包。
原文档给出的典型场景:主要功能改动集中在@mastra/memory,而@mastra/core与mastra只有配套的支撑性改动,那么@mastra/memory需要独立成单独的 changeset,与另外两个包分开。
重要原则:单文件里塞多个包的超长 changeset 是一种反模式(anti-pattern)。这会导致多个包出现非常臃肿的 changelog 条目,应当避免。如果确实涉及多个包,通常存在一两个承载了绝大部分改动的主包。
这一原则在仓库的.changeset/config.json中也有呼应:"fixed": [["@mastra/core", "@mastra/server", "@mastra/deployer", "@mastra/deployer-cloud"], ["mastra", "create-mastra", "@internal/playground"]]定义了固定版本联动组,同组包会一同发布,而"ignore"列表(如"@internal/*"等私有/内部包)则被排除在发布之外,只有mastra、create-mastra、create-factory、mastracode、@mastra/*、@internal/playground、@internal/core等显式!取反的包才参与变更集处理。
五、第二步:使用 GitHub CLI 打开 PR
变更集创建完成后,第二步是用ghCLI 为当前分支打开 PR。关键约束是:不要直接打开 PR,而是使用能在浏览器中打开 PR 的 web 选项,让用户可以在必要时编辑标题和描述。
5.1 PR 标题
标题要简洁且具有描述性,并遵循 Conventional Commits 规范,例如:
fix: title here(修复类)feat(pkg-name): title here(功能类,可带包名作用域)
5.2 PR 描述
PR 描述应遵循以下风格:
- 简洁、谦逊,避免华丽或冗长的语言;
- 语气随意友好,但要直击要点(keep it casual/friendly but get to the point);
- 修复类变更展示修改前后的简单代码示例(before/after);新功能类变更只需展示「之后」的示例;
- 不要使用列表或标题,保持简单直接。
六、完整工作流与自查清单
把两步串起来,Mastra 仓库一次标准 PR 提交流程如下:
- 在功能分支上完成代码修改;
- 对每个发生变更的包运行
pnpm changeset -s -m "..." --patch pkg-name(非破坏性修复场景)或对应--minor/--major变体;多包且改动不同时,分组多次运行以生成多个 changeset 文件; - 检查
.changeset/下生成的 Markdown 文件,确认 frontmatter 的包名与升级类型正确、正文符合开发者向的 changelog 写作规范; - 使用
gh命令以 web 方式打开 PR(gh pr create --web一类浏览器打开方式),填写 Conventional Commits 风格的标题与简洁描述,附上必要的 before/after 代码示例; - 在浏览器中最终确认标题与描述后提交。
提交前自查:
- 每个发生变更的包都有对应的 changeset 文件,且没有多个不相关变更混入同一个文件;
- 版本升级类型与变更性质匹配(修复 →
patch,新功能 →minor,破坏性 →major); - 消息面向开发者、动词导向(Added/Fixed/Improved/Deprecated/Removed)、突出用户可感知的结果,破坏性变更或新功能附公共 API 的 before/after 示例;
- PR 标题符合 Conventional Commits,描述简洁、无列表无标题、含必要的代码示例。
七、相关资源导航
- 指令文档原文:.opencode/command/pr.md
- 自定义 changeset CLI 入口与流程编排:packages/_changeset-cli/src/index.ts
- 变更包自动检测:packages/_changeset-cli/src/git/getChangedPackages.ts
- 版本升级类型选择(含交互式流程):packages/_changeset-cli/src/changeset/getVersionBumps.ts
- 变更集消息收集与模板:packages/_changeset-cli/src/changeset/getChangesetMessage.ts
- changeset 文件写入:packages/_changeset-cli/src/changeset/createCustomChangeset.ts
- changesets 全局配置(fixed 组、ignore 列表、changelog 生成器):.changeset/config.json
- 真实 changeset 示例:.changeset/agent-entry-structured-output-guard.md
- 根目录脚本入口(
changeset/changeset-cli):package.json
【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考