mcpField
R
release-notes-generator

release-notes-generator

github.com/datex开发100 次安装
代码仓库

关于 release-notes-generator

release-notes-generator 是用于 Datex Studio 的技能,可为两个应用分支生成技术版和客户版发布说明。它结合提交、关联工作项与配置差异,并追踪依赖项及未能分析的缺口。

主要功能

  1. 01比较两个发布分支
  2. 02枚举变更的依赖项
  3. 03结合提交、工作项和配置差异
  4. 04生成技术版与客户版说明
  5. 05跟踪未解析依赖项及跳过的子树

适用场景

  1. 01起草 Datex Studio 版本说明
  2. 02汇总客户应用及其依赖项的变更
  3. 03找出无法分析的程序包
  4. 04准备工程版和客户版摘要

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/datex/skills --skill release-notes-generator

安装后在 Claude Code 中输入/release-notes-generator确认已加载。

详细介绍

发布说明生成器

通过合并三种来源,生成两个 Datex Studio 分支之间的发布说明:提交(合并了什么)、工作项(原因)和配置差异(实际更改)。生成技术版和客户版两种版本。

参考资料

前置条件

  • --from 分支 ID — 根应用的较旧版本(基线)
  • --to 分支 ID — 根应用的较新版本(目标)
  • dxs ≥ 0.4.9 — 需要 source release-tree 和跨组织依赖解析。较旧版本的 deps-diff/compare 会静默报告依赖更改为零(它们比较的字段已从 AppConfig 负载中移除),且无法解析客户应用自身组织中的软件包。dxs source release-notes 在 0.5.5 之前,其依赖部分也有相同的盲点;source deps --tree 和 source graph 也一样,会返回空树。如果 dxs source release-tree --help 执行失败,请停止并说明情况——不要退回使用有盲点的路径。
  • 强烈建议使用 dxs ≥ 0.4.24。 从此版本起,release-tree 会自行解析由 Service-Pack 固定版本的依赖,报告被跳过的子树(subtree_skipped / summary.subtrees_skipped),而不是静默丢弃;指出哪一侧解析失败(resolve_failed_sides);并接受用于索引其他组织代码仓库的 --extra-org。使用较旧版本时,这些工作都必须手动完成——参见阶段 1b。
  • 如果任何操作会直接调用 dxs source release-notes,则需要 dxs ≥ 0.5.4(本技能自身使用的是 release-tree 路径,从未受此问题影响)。它的依赖差异比较使用两侧的 marketPlaceApplicationVersionId——这是 AppConfig 迁移时移除的字段——因此它比较的是 None 和 None,依赖升级从未被报告为已更新。从 0.5.4 起,它会通过 source compare 和 deps-diff 使用的同一辅助函数,依据解析出的 version 进行差异比较,因此三者结果一致;无法解析其分支的升级也会报告为未分类,而非直接丢弃。

必须预先提供两个分支 ID。如果用户提供的是版本名称(或日期,或只提供了一个分支 ID),请先解析——参见下文的解析根应用和版本。必须遵守分支 ID 政策:绝不要猜测 ID。

解析根应用与版本

“根应用”指用户要发布的应用,不一定是 Datex 产品。客户部署的应用(例如 Tobin 的 Footprint、tob-footprint)通常只是一个轻量聚合器:它自身几乎没有或完全没有直接提交,其发布内容就是依赖项的版本升级。这是正常情况——实质内容都在依赖项中,release-tree 会枚举这些依赖项。

进入阶段 1 前,需要处理两个解析问题:

  • 跨组织包。 客户应用会同时引用共享的 Datex 目录(组织 1)和其所属组织中的包(例如 tob-*)。release-tree 会自动检测根应用的组织(通过 applicationDefinitionId → repo → organization),并同时为两者建立索引,因此可以解析客户自己的包。旧版 dxs 不具备此功能,这些包会悄然消失。查找客户应用:dxs source repo list --org-name <CODE>。

  • 版本名称,包括 Service Pack。 如果给定的是版本名称,需要将其解析为分支 ID。默认组列表不包含 Service Pack,因此像 20260423.145611.SP.20260604.154933 这样的 versionName 不会出现在其中:

    • 默认发布:dxs source branch list --repo <id> --default-group --status published -n 0 → 匹配 versionName
    • Service Pack:运行 dxs source servicepack list --repo <id> 查找 SP 组,然后运行 dxs source branch list --repo <id> --group-id <sp_group> --status published -n 0
    • (branch search 匹配的是分支名称,而不是 versionName——不要使用它。)

    这是手动解析根应用自身版本名称的方法。对于依赖项,dxs ≥ 0.4.24 时,release-tree 会自行处理 SP 回退查找——见阶段 1b。

工作流

[Phase 1: Enumerate]
dxs source release-tree --from <root_old> --to <root_to>   (--recursive if nested)
  → root + every changed dependency, each resolved to from/to branch IDs
    (cross-org), plus added / removed packages
        |
[Phase 1b: Recover unresolved deps]   summary.resolve_failed must reach 0
Usually empty on dxs >= 0.4.24 (SP groups resolved automatically). If not:
  no repository for uniqueIdentifier -> re-run with --extra-org <orgId>
  still unresolved                   -> manual lookup (see Phase 1b)
  (with --recursive: re-walk each recovered dep — its sub-tree was skipped too)
        |
[Phase 2: Commits per package]
For root + each changed dependency (parallel):
  dxs source compare --from <pkg_old> --to <pkg_new> --exclude-sync
  → committed_branches (id, title, author, date, changes), workitem_ids
        |
[Phase 3: Work Items per commit]
  dxs source workitems --branch <commit_branch_id> --description
        |
[Phase 4: Source Diffs]
For each created/meaningfully-modified/bug-fix config:
  dxs source diff --from <pkg_old> --to <pkg_new> --config <ref_name>
        |
[Phase 5: Write Notes]
Compose two variants per the Output Formats below:
  • Technical — for developers/support
  • Customer — for end users / operations
Deduplicate work items that appear in multiple dependencies. Note added/removed
packages (a newly-included package is a feature; a removed one, a flag).

阶段详情

阶段 1:枚举(release-tree)
dxs source release-tree --from <root_old_branch_id> --to <root_to_branch_id>
# add --recursive only if dependencies have their own changed sub-dependencies;
# a flat aggregator (the common case) is complete in one pass.

此调用取代了旧流程:“比较主应用,再递归地对每个依赖项逐个执行 compare”。它会返回:

  • root — 正在发布的应用(reference_name、分支 ID)。通常是一个自身没有直接提交的轻量包装器。
  • dependencies — 每个发生变更的依赖项,均已解析出 repo_id、from_branch_id、to_branch_id(用于深入分析这些依赖项的 ID),以及 from_version / to_version。支持跨组织解析,因此客户应用所属组织的包(例如 tob-reports)也会包含在内,而不只是 Datex 目录中的包。任何无法解析的依赖项都会带有 resolve_error,并且(dxs ≥ 0.4.24)带有 resolve_failed_sides: ["from"|"to"] —— 应从该字段读取未解析的一侧,不要解析以 ; 连接的 resolve_error 字符串,其中是无法解析的说明性文本。若无法继续向下遍历,未解析的条目还会在 --recursive 时带有 subtree_skipped: true。
  • added / removed — 新纳入发布的包,以及从发布中移除的包。这些包没有可供挖掘的提交差异;在阶段 5 中直接记录即可(新纳入的包是一项功能;移除的包则可能需要标记)。
  • summary — 计数(dependencies_total、resolved_ok、resolve_failed、added_count、removed_count,以及 dxs ≥ 0.4.24 时的 subtrees_skipped),还有 max_depth_reached 和 recursive。使用 --recursive 时,将 max_depth_reached 与 --max-depth(默认值为 10)进行比较——如果两者相等,遍历可能已被截断。subtrees_skipped > 0 与 resolve_failed > 0 同样严重:它表示由于无法继续遍历,某些依赖项的整个变更子树都未被枚举。

为什么不用 compare/deps-diff 来枚举? 对于已解析版本的差异,只有 dxs ≥ 0.4.9 时它们才是正确的;旧版本会报告变更依赖项为 0(它们比较的是 marketPlaceApplicationVersionId,该字段已从 AppConfig 负载中移除)——因此运行后会得出“没有变化”的结论,并漏掉依赖项中 80% 以上的实质内容。release-tree 是权威的枚举工具,也会提供用于深入分析的分支 ID。

阶段 1b:恢复所有 resolve_failed 依赖(不可跳过)

在继续阶段 2 之前,summary.resolve_failed 必须降至 0——否则必须在备注中列出每个剩余故障,说明它们是尚未分析的缺口(见本节末尾)。 未解析的依赖至少缺少一个分支 ID,因此无法比较或生成差异——它会悄无声息地从备注中消失,而这正是此技能要防止的问题。请将非零计数视为阻塞项,而非警告。

在 dxs ≥ 0.4.24 上,本阶段通常无需执行任何操作——检查 summary.resolve_failed 和 summary.subtrees_skipped,如果两者均为 0,则直接进入阶段 2。release-tree 会自行解析固定到 Service Pack 的依赖:_published_version_map 会先合并仓库的 Default 应用组,然后为仍然缺失的版本回退到 Service Pack 组(仅对需要的仓库多列出一次)。包含 .SP. 的 versionName,例如 20260423.145611.SP.20260604.154933,现在可以正常解析。在 dxs < 0.4.24 上则始终无法解析,因为查找只会看到 Default 组——如果使用的是较旧版本,请升级(dxs update),不要手动处理下表。

如果确实发生失败,请按原因恢复:

信号原因恢复方法
resolve_failed_sides: ["to"](或 ["from"])只有一侧缺失——另一侧的分支 ID 有效仅恢复指定的一侧;切勿丢弃已有的 ID。请从此字段读取对应侧,而不要解析由 ; 连接的 resolve_error 文本。
no repository for uniqueIdentifier …软件包所属组织不在仓库索引中(缺少 repo_id)。release-tree 只会自动检测根应用所属的组织。使用 --extra-org <orgId> 重新运行(可重复指定,并在自动检测到的组织基础上追加)——这是带内修复方式,CLI 自身的帮助也明确说明了此情况。只有在不知道组织 ID 时:从依赖项的 reference_name 前缀推导组织代码(tob-reports → TOB),使用 dxs source repo list --org-name <CODE> 查找该组织,然后使用 --extra-org 重新运行。
在 dxs ≥ 0.4.24 上出现 … not found in published releases确实未发布,或回退逻辑不支持该组类型dxs source servicepack list --repo <repo_id> → 对每个 SP 组 ID 执行:dxs source branch list --repo <repo_id> --group-id <gid> --status published -n 0 → 将 versionName 与条目的 from_version / to_version 匹配。如果这里也找不到,则该版本从未发布——将其记录为尚未分析的缺口。
subtree_skipped: true--recursive 无法继续遍历此条目,因此整个已更改的子树都未加入工作列表根据上面的行恢复其分支 ID,然后重新遍历(见下文)。summary.subtrees_skipped 会统计这类条目。

将恢复的分支 ID 输入阶段 2,处理方式与 release-tree 返回这些 ID 完全相同。

如果阶段 1 使用了 --recursive,还必须重新遍历每个恢复的依赖项。 未解析的依赖项不会加入下一深度级别的队列——遍历会跳过任何缺少分支 ID 的条目,因此也不会枚举其自身已更改的子依赖项。恢复分支 ID 可以修复该软件包本身,但其下的所有内容仍不可见,这只是同一种静默遗漏的缩小版:

dxs source release-tree --from <recovered_from> --to <recovered_to> --recursive

将该输出合并到工作列表中——按 unique_identifier + from_version + to_version 去重(与遍历内部使用的键相同),并将其 added / removed 一并带入阶段 5。然后再次检查其 summary.resolve_failed 和 summary.subtrees_skipped,执行阶段 1b:恢复的子树自身也可能包含无法解析的依赖项。

如果依赖项经过这两种途径仍无法解析,请在备注中明确说明(“无法分析 <package> <from> → <to>”),不要将其省略——尚未分析的软件包是已知缺口,不代表没有变化。

服务包是客户应用的常见形式。这类应用通常会基于已发布版本进行热修复,而不是跟踪默认分支。对于客户应用,请预期 resolve_failed > 0,并为此步骤预留预算。

Phase 2:每个包的提交

列出根包 和 Phase 1 中每个已更改依赖项的提交(并行执行,即按包展开):

dxs source compare --from <pkg_from_branch_id> --to <pkg_to_branch_id> --exclude-sync

通过 branch_comparison,你可以按包获取以下信息:

  • committed_branches — 每个已合并的功能分支:
    • id — 提交的分支 ID(在 Phase 3 工作项中使用)
    • title — 简短的提交标题。仅作为标题使用,绝不能作为发布说明条目的正文;工作项(Phase 3)和差异(Phase 4)会提供这些内容。
    • author — 提交者
    • date
    • changes — 配置级别的更改(reference_name、type、modification 为 add/update/delete)
  • workitem_ids — 整个包时间范围内关联的 DevOps 工作项。
  • releases / release_count — 中间版本(用于标题)。

--exclude-sync 会排除仅用于同步的提交(这些提交只是拉取依赖项更新);这些提交中的实际工作会被记录,因为依赖项本身就是工作列表中的一个独立包。轻量级根应用可能会合理地返回 零个已提交分支——这不是错误,其版本内容就是依赖项升级。

对于每个已提交分支,如果有可用的 commitReleaseNotes,也请通过 commit-release-notes 获取。版本到版本的 source compare 和 source release-notes 不会包含重建后的 committed_branches 中的说明;请从分支详情/历史中补充每个返回的提交 ID。非版本比较可以保留 branch_comparison.commits 中由 API 提供的说明。说明缺失或为 null 均属正常,已有说明也可能只是重复了 API 回退/回填后的描述。即使已有详细文字,仍需分析工作项和差异;说明是辅助证据,而非实现内容的证明。

Phase 3:每个提交的工作项

对于 changes 数组并非无实际内容的每个提交(或在范围允许时处理所有提交),获取其关联的工作项:

dxs source workitems --branch <commit_branch_id> --description

工作项是发布说明中业务背景最有价值的输入。它们包含:

  • title — 简洁的功能名称(通常比提交标题更具描述性)
  • type — Development / Bug / Wavelength Component / 等
  • state — Done / Committed / 等
  • assigned_to — 作者归属信息
  • description — 完整的需求、复现步骤、模型图、验收标准

如果某个提交没有关联工作项,请标记为“缺少可追溯性”,并根据 Phase 4 的差异重建正文,同时将已存储的提交说明作为辅助背景。使用提交 ID 和 title 作为条目标题。 绝不要默默省略这些提交。

证据的作用:

  • 工作项(Phase 3) — 为什么。业务意图、需求、验收标准。是说明正文的主要输入。

  • 差异(Phase 4) — 如何实现。代码本身;当文字描述与实际提交内容不一致时,它是最终依据。

  • 已存储的提交说明(Phase 2) — 可用时提供工程背景;请根据差异核实其中的说法,并保留可追溯性检查。标题仍然是标题,而不是发布说明正文。

阶段 4:源代码差异

对于每个值得关注的配置,拉取统一差异(使用阶段 1 中所属软件包的 起始和目标分支 ID):

dxs source diff --from <pkg_from_branch_id> --to <pkg_to_branch_id> --config <reference_name>

响应会告诉你:

  • change_type — created / modified / deleted / unchanged
  • content — 完整配置(新建时)
  • diff — 统一差异(修改时)

何时拉取差异:

  • 始终对新建的配置执行差异比较。 content 会显示新内容的完整结构 (例如中心的选项卡、流程的逻辑、网格的列)。这有助于你在说明中撰写结构描述。
  • 对大量修改的配置执行差异比较。 当单个配置出现在许多提交中时,累积差异是了解实际变更的最佳方式。
  • 对 Bug 修复执行差异比较。 修复通常只涉及一两行;差异能告诉你修复是否符合工作项中报告的问题。

配置类型 → 查看内容说明:

类型描述内容
hub导航结构、选项卡、操作栏
flow / footprintFlow后端业务逻辑
frontendFlowUI 交互和导航
form / editor用户界面屏幕
grid数据展示、列、筛选器
selector下拉选项/选择器选项
datasource数据获取查询
storage状态管理(通常使用 MongoDB)

修改类型:

  • add — 新配置,可能是新功能。始终对其执行差异比较。
  • update — 已修改。可能影响重大,也可能无关紧要;以差异为准。
  • delete — 已移除。可能造成破坏性变更;请标记。
规模:功能位于依赖项中(并非可选项)

根应用自身的提交通常只是同步提交,或者根本没有提交。像“Wave Planning”“Cart Management”“Order Import”这样的实际功能都位于组件软件包中(Waves、Carts、Inventory、FootprintManager 等)。release-tree 已在阶段 1 中枚举并解析这些软件包;接下来要做的是对每一个软件包执行阶段 2–4,而不只是根应用。跳过依赖项分析意味着会漏掉 80% 以上的实际变更。

使用子 Agent 来应对规模。 FootprintManager 级别的发布涉及 20–60 个软件包和数百次提交,单个上下文难以处理。启动并行 Agent(每个软件包一个,或每批约 5 次提交一个)来执行阶段 2–4,然后在编写说明时汇总它们的发现。对于这种繁重且确定性的扇出任务(对预先整理好的工作清单使用低成本模型执行叶节点/归并),请参阅 datex/skills#16 中跟踪的 v2 架构。

阶段 5:撰写说明

同时生成技术版和客户版。

强制要求(两个版本均适用)

每个功能和 Bug 修复条目都必须包含:

  1. 工作项链接 — 指向 DevOps 的可点击 URL,由工作项的 external_id(而非其内部 ID)构建: [#XXXXXX](https://dev.azure.com/DatexCorporation/_workitems/edit/XXXXXX) (使用 _workitems/edit/ 浏览器路径,而非 _apis/wit/workItems/ API 端点)。如果不存在工作项,请标记“缺少可追溯信息”,并使用提交 ID。
  2. 业务背景 — 工作项描述中的原因。
  3. 作者署名 — 实现者(来自工作项或提交)。
  4. 技术细节 — 新增/修改的配置(仅限技术版)。

未附工作项链接的发行说明并不完整。它们缺少可追溯性,也无法让读者获取更多背景信息。

去重

同一个工作项可能出现在多个依赖项中(例如,某个功能同时涉及 Waves 和 FootprintManager)。编写最终说明时,请按工作项 ID 去重——只列出一次该功能,并注明其涉及多个模块,而不是在每个依赖项下重复列出。

输出格式

技术版发行说明
# Release Notes — <app>  (<from_version> → <to_version>)

## Summary
- Date range: <from_date> → <to_date>
- Intermediate releases: <count>
- Dependencies updated: <count>

## New Features

### <Feature Title from Work Item>
**Work Item:** [#NNNNNN](…/_workitems/edit/NNNNNN)
**Author:** <Name>

<Description from the work item requirements.>

**Structure / Technical Details:**
- <What was created — new configs, tabs, flows>
- <Key structural notes from the diff>

**New configurations:** <count> configs including <brief list>.

---

## Improvements
<same shape as Features, for enhancements to existing functionality>

---

## Bug Fixes

### <Bug Title from Work Item>
**Work Item:** [#NNNNNN](…/_workitems/edit/NNNNNN)
**Author:** <Name>

**Problem:** <What users experienced — from work item description.>
**Fix:** <What was actually changed — from the source diff.>

---

## Dependencies Updated

| Dependency | From | To | Significant Changes |
|---|---|---|---|
| Waves | <ver> | <ver> | Wave planning feature, N bug fixes |
| …      | …    | …  | …                                 |
客户发布说明
  • **受众:**最终用户、仓库经理、运营人员。
  • **语气:**文字清晰、专业。提供信息,而非营销话术。
  • **聚焦“这对你意味着什么”:**说明实际影响。
  • **省略:**配置名称、分支 ID、内部技术细节。
# What's New — <app>  <from_version> → <to_version>

## New Capabilities

### <Feature Title>
<Two to four sentences in plain language explaining what the user can now do
and why it matters. No config names, no branch IDs.>

---

## Improvements

- <Short sentence per improvement, focused on user-visible impact.>
- <…>

---

## Fixes

- <Short sentence per fix describing the user-visible problem that is no
  longer happening.>
- <…>

客户说明中的反面示例——请避免:

  • 大量使用表情符号(不适合商业软件)
  • 营销话术(“我们很高兴地宣布……”)
  • 技术术语(配置名称、分支 ID、流程名称)
  • 含糊的描述(“各种改进”“错误修复”)

提示

  1. **代码才是事实依据。**提交标题和工作项只是线索——代码才包含真实上下文。因此,Phase 4 的差异对比是必需的。
  2. **每个功能分支都应有一个工作项。**如果没有,请标记为“缺少可追溯性”;不要掩盖这一问题。
  3. **对比新增配置以了解结构。**中心的选项卡、流程的逻辑、网格的列,都能在 add 配置的差异对比中看到。
  4. **差异对比能揭示错误修复的具体内容。**听起来复杂的错误,修复可能只有一行。在技术说明中展示实际改动。
  5. **功能往往在依赖项中。**对发布树枚举出的每个包执行 Phase 2–4,往往能发现 80% 的实质内容——对于自身应用没有提交记录的轻量级客户封装尤其如此。
  6. **使用子 Agent 提高处理规模。**对 60 多个包依次进行依赖项分析会受到时间和上下文限制。并行 Agent 可以解决这个问题。
  7. **谨慎汇总。**对多个依赖项中出现的工作项进行去重——它们是同一项功能,只是在两个地方有所改动。

示例会话

# Step 1 (Phase 1): Enumerate the worklist — root + every changed dependency,
# each resolved to from/to branch IDs, cross-org.
dxs source release-tree --from 64920 --to 67162
# root + 19 changed deps (e.g. Waves 64876→67102), 0 resolve_failed, 1 added

# Step 2 (Phase 2): Commits for the Waves dependency
dxs source compare --from 64876 --to 67102 --exclude-sync
# 12 committed_branches with wave planning work

# Step 3 (Phase 3): Why — the work item behind a commit
dxs source workitems --branch 67099 --description
# Work item #180436 — wave creation requirements

# Step 4 (Phase 4): How — the new flow's code
dxs source diff --from 64876 --to 67102 --config create_annotation_task_action

# Bug fix: why then how
dxs source workitems --branch 66852 --description        # Bug #238852
dxs source diff --from 64919 --to 67159 \
  --config outbound_orders_eligible_for_return_grid
# agGrid: null → agGrid: true

常见错误

错误修正方法
使用 compare/deps-diff 枚举依赖项dxs < 0.4.9 时存在盲区(报告变更数为 0)——使用 source release-tree
因根应用提交很少或没有提交,就得出“没有任何变更”的结论薄封装的版本发布就是其依赖项的升级——对枚举出的每个依赖项版本树运行阶段 2–4
假设 source compare 包含详细的提交说明检查其实际输出;必要时通过 commit-release-notes 获取 commitReleaseNotes,对于缺失或只有摘要的文本,则改用工作项/差异
对于客户应用,只解析 Datex-org 软件包release-tree 会解析跨组织的依赖;客户自己的 *- 软件包也要计入
在 summary.resolve_failed > 0 时继续进入阶段 2这些软件包会悄无声息地从说明中消失——在挖掘提交前,按阶段 1b 逐个恢复
在 summary.subtrees_skipped > 0 时继续进入阶段 2整个已变更的子树都未被枚举,而不只是单个条目——按阶段 1b 恢复并重新遍历
解析以 ; 连接的 resolve_error 字符串,试图找出哪一侧失败读取 resolve_failed_sides(dxs ≥ 0.4.24);resolve_error 是描述性文本,无法解析
手动恢复由 Service-Pack 固定版本的依赖项dxs ≥ 0.4.24 时,release-tree 会自行解析 SP 组——升级(dxs update),而不是使用恢复表
将 no repository for uniqueIdentifier 视为只能手动查找的情况使用 --extra-org <orgId> 重新运行(dxs ≥ 0.4.24)——此标志正是为此而设
使用 --recursive 运行时,恢复了某个依赖项的分支 ID,却没有重新遍历它解析失败时,遍历过程就跳过了该子树——对恢复后的 ID 重新运行 release-tree --recursive(阶段 1b)
将提交标题用作功能标题使用关联工作项的标题;提交标题往往比较仓促
使用内部 ID / _apis/ URL 构建 DevOps 链接使用 external_id 和浏览器路径 _workitems/edit/
在多个依赖项下重复列出相同功能编写时按工作项 ID 去重
为了“保持说明简洁”而省略工作项链接链接是必需的;没有链接,说明就无法追溯
客户说明中包含配置名称/分支 ID删除内部术语——客户版应使用普通描述,不应堆砌配置名
按顺序分析 50 多个依赖项使用并行 Agent;顺序处理会触及上下文和时间限制

评论

支持 Markdown