Notes for release
2026/9/18 10:02:09 网站建设 项目流程

Notes for release

【免费下载链接】sanitySanity Studio – Rapidly configure content workspaces powered by structured content项目地址: https://gitcode.com/GitHub_Trending/sa/sanity


Release Notes

sanity-io/cli (@​sanity/cli)

v6.1.3

Bug Fixes
  • use non-deprecated--project-idflag for dataset import during init (#661) (0b660b9)

...

sanity-io/some-other-repo (some-other-package)

v1.0.0

Bug Fixes
  • some unrelated fix (#1) (abc1234)
```

逐层拆解这份骨架:

  • ### Notes for release+ 分隔线:这是 Sanity PR 模板要求的发布说明章节头。夹具中紧随其后的---横向分隔线也是extractReleaseNotes(普通路径)判定章节结束的标记。
  • ### Release Notes:Renovate 自带的总标题,与<details>块共同构成 changelog 摘要。
  • <details>/<summary>:每个依赖包一个折叠块,<summary>采用仓库 (包名)格式,例如sanity-io/cli (@sanity/cli)。注意包名中的@被写成了&#8203;实体——这是 Renovate 插入的零宽空格,用于防止触发 GitHub 的 @ 提及通知。
  • 版本标题(h3)### \v6.1.3``,每个版本一段。
  • 章节标题(h5)##### Bug Fixes##### Features##### Dependencies等。
  • 列表项:形如- 描述 (#661) (0b660b9),同时携带 PR/issue 引用与提交哈希。
  • <!--renovate-debug:...-->:Renovate 的调试注释,内容是 base64 编码的 JSON(本例解码后为{"createdInVer":"43.66.4"},即生成该 PR 的 Renovate 版本)。

夹具中三个版本的@sanity/cli变更内容是理解解析行为的关键素材:

版本章节变更内容
v6.1.3Bug Fixes在 init 期间的数据集导入中使用非弃用的--project-id标志(#661,commit0b660b9
v6.1.2Bug Fixes新安装时升级 react + react-dom 到最新版本;从 studio workDir 解析react-dom/server@sanity/uideps:更新 oclif-tooling(需剔除)
v6.1.2Dependencies@sanity/cli-core提升到 1.1.1,@sanity/cli-test提升到 0.2.3(需剔除)
v6.1.1Bug Fixes懒加载 icon resolver,避免在 import 时引入@sanity/ui
v6.1.1Featuressanity init新增--template标志
(其他仓库)Bug Fixessome unrelated fix(非白名单,整体剔除)

解析管线:parseRenovateReleaseNotes 的四阶段处理

核心实现位于 parseRenovateReleaseNotes.ts,入口函数parseRenovateReleaseNotes(prBody)将原始 PR 描述转换为可写入 Sanity 的 Portable Text 块。它刻意在原始 Markdown/HTML 字符串上操作,因为源码注释明确说明:<details>块在 Portable Text 转换后无法存活(见函数上方的 JSDoc)。

export function parseRenovateReleaseNotes(prBody: string): NormalizedMarkdownBlock[] { const blocks = extractDetailsBlocks(prBody) const allowed = blocks.filter((b) => RENOVATE_RELEASE_NOTES_PACKAGES.has(b.packageName)) if (allowed.length === 0) return [] const combined = allowed.map((b) => b.content).join('\n\n') const filtered = filterVisibleSections(combined) const cleaned = cleanChangelogItems(filtered) if (!cleaned.trim()) return [] return markdownToPortableText(cleaned) }

阶段一:提取<details>块并解析包名

extractDetailsBlocks用正则匹配<details>\s*<summary>...</summary>...</details>,从<summary>的括号部分提取包名,核心是cleaned.match(/\(([^)]+)\)\s*$/)。提取前先执行summaryText.replace(/&#8203;/g, '')去除零宽空格实体,这正是夹具中@&#8203;sanity/cli能正确解析为@sanity/cli的原因。没有任何<details>块或块内无内容时返回空数组。

阶段二:白名单过滤

export const RENOVATE_RELEASE_NOTES_PACKAGES: ReadonlySet<string> = new Set(['@sanity/cli'])

只有包名命中白名单的块才被保留。因此夹具中sanity-io/some-other-repo (some-other-package)块的some unrelated fix会整体丢弃。若过滤后没有白名单包,函数直接返回[]。源码注释还说明:往白名单添加包的前提是该包在renovate.json中配置了带 changelog 的prBodyTemplate

阶段三:筛选可见章节,跨版本合并

filterVisibleSections逐行扫描,维护一个"可见章节"状态机:

  • 跳过版本标题:匹配/^###\s+\/的行(如### [\v6.1.3``)被完全忽略,同时重置当前章节状态;
  • 识别章节标题:匹配/^#{5}\s+(.+)/的 h5 行,章节名转小写后查表VISIBLE_CHANGELOG_SECTIONS
    const VISIBLE_CHANGELOG_SECTIONS: ReadonlySet<string> = new Set([ 'features', 'bug fixes', 'performance improvements', 'reverts', 'documentation', ])

    可见章节的内容被收集,不可见章节(如Dependencies)的内容被丢弃;

  • 输出时不带标题:收集的内容仅含列表项行,章节标题本身不进入输出,最终按首次出现的顺序拼接。

这一设计的两个关键行为:一是夹具中 v6.1.2 的##### Dependencies@sanity/cli-core等版本提升)被排除——依赖版本变动对用户没有发布价值;二是同类型章节跨版本合并——v6.1.3、v6.1.2、v6.1.1 三个版本的Bug Fixes内容会合并成一组输出,且不出现任何版本号标题,测试用例"merges same-type sections across multiple versions"明确验证了这一点。

阶段四:清洗列表项

cleanChangelogItems用三个正则完成清洗,夹具中的每一项变更都能对应到具体规则:

markdown // ① 删除依赖作用域条目:- **deps:** ... .replace(/^\s*-\s+\*\*deps:\*\*.*$/gm, '') // ② 剥离尾部提交哈希链接:(0b660b9) .replace(/\s*\(\[[0-9a-f]+]\([^)]*\)\)/gm, '') // ③ 展开 PR/issue 引用:(#661) → #661 .replace(/\(\[#(\d+)]\(([^)]*)\)\)/gm, '#$1')
  • 规则①:删除- **deps:** update oclif-tooling这类依赖作用域条目——它们混在Bug Fixes里但不是面向用户的修复;
  • 规则②:删除(0b660b9)格式的提交哈希引用(7 位十六进制),因为发布说明不需要 commit 级细节;
  • 规则③:将(#661)外层的括号去掉,保留#661链接——这是唯一"保住链接"的规则,测试用expect(markdown).toMatch(/\[#\d+]\(/)not.toMatch(/\(\[#\d+]\(/)双向断言。

清洗后为空则返回[],否则交给markdownToPortableText转成 Portable Text 块。转换包装位于 markdownToPortableText.ts,它基于@portabletext/markdown,并额外用 TurndownService 把html类型的块先转回 Markdown 再递归解析,保证<details>等 HTML 结构不会泄漏进最终文档。

在 changelog 生成流程中的接入点

解析器并非独立运行,而是深度嵌入 changelog 文档生成命令 createOrUpdateChangelogDocs.ts。关键逻辑是按 PR 作者类型分流:

const isBot = userType === 'bot' const releaseNoteBlocks = flattenCallouts( pr?.body ? isBot ? parseRenovateReleaseNotes(pr.body) : await extractReleaseNotesFromPrBody(pr.body) : [], )

【免费下载链接】sanitySanity Studio – Rapidly configure content workspaces powered by structured content项目地址: https://gitcode.com/GitHub_Trending/sa/sanity

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询