首页
/ ansible-core 变更日志(Changelog)片段机制:从 fragments 目录到 CHANGELOG-vX.Y.rst 的完整流程

ansible-core 变更日志(Changelog)片段机制:从 fragments 目录到 CHANGELOG-vX.Y.rst 的完整流程

2026-09-04 11:03:17作者:管翌锬

本文以 changelogs/README.md 为核心,讲解 ansible-core 项目如何基于 changelogs/fragments/ 目录下的 YAML 变更片段(changelog fragments)在发布时自动生成版本级变更日志文件 CHANGELOG-vX.Y.rst。读完后,你将理解 devel 分支与发布分支在 changelog 上的差异、changelogs/config.yaml 中各配置项与分节规则的含义,以及发布脚本 packaging/release.py 中 changelog 生成的真实调用链,从而能在向 ansible-core 贡献代码时正确编写变更片段。

核心机制:片段驱动的版本级变更日志

changelogs/README.md 给出的核心说明可以归纳为三点:

  1. 发布流程的一部分:作为发布流程的一环,版本专属的 CHANGELOG-vX.Y.rst 文件由 fragments 目录下的片段聚合生成;
  2. 发布分支看版本文件:在发布分支上,一旦某个版本已经创建,应查阅该分支上版本专属的 changelog 文件,来了解该分支上已经发生的变更;
  3. devel 分支只有片段devel 分支上不存在已生成的 changelog,只有 changelog 片段。

也就是说,ansible-core 采用"片段累积、发布时聚合"的变更日志模型:日常开发中,每个 PR 往 changelogs/fragments/ 提交一个小的 YAML 片段;只有执行发布动作时才把所有片段合并进 RST 格式的正式 changelog,并同步到 changelogs/changelog.yaml 中。

目录结构与文件角色

changelogs/ 目录下的关键文件各司其职:

路径 作用
changelogs/README.md 说明 changelog 生成规则(本文主体)
changelogs/config.yaml 定义 changelog 的标题、版本正则、分节顺序与生成行为
changelogs/changelog.yaml 记录已发布版本的累积变更(机器可读的发布状态文件)
changelogs/fragments/ 存放所有待发布的变更片段(YAML 文件)

当前 changelogs/changelog.yaml 的内容为:

ancestor: 2.21.0
releases: {}

这表示 devel 分支的"变更基线"是 2.21.0:所有 2.21.0 之后合入、尚未发布进版本文件的变更,都以片段形式积累在 fragments/ 中。releases: {} 印证了 README 的说明——devel 分支没有已生成的版本条目。

changelog 生成配置逐项解读

changelogs/config.yaml 是生成器的行为定义,当前仓库中的完整配置为:

---
title: ansible-core
release_tag_re: '(v(?:[\d.ab\-]|rc)+)'
pre_release_tag_re: '(?P<pre_release>(?:[ab]|rc)+\d*)$'
changes_file: changelog.yaml
changes_format: combined
keep_fragments: true
always_refresh: true
ignore_other_fragment_extensions: true
mention_ancestor: false
notesdir: fragments
prelude_section_name: release_summary
new_plugins_after_name: removed_features
sections:
- ['major_changes', 'Major Changes']
- ['minor_changes', 'Minor Changes']
- ['breaking_changes', 'Breaking Changes / Porting Guide']
- ['deprecated_features', 'Deprecated Features']
- ['removed_features', 'Removed Features (previously deprecated)']
- ['security_fixes', 'Security Fixes']
- ['bugfixes', 'Bugfixes']
- ['known_issues', 'Known Issues']

结合 packaging/release.py 中实际使用的生成工具(antsibull-changelog)与各字段的语义,可以逐项理解:

  • title: ansible-core:生成 changelog 的文档标题;
  • release_tag_re / pre_release_tag_re:识别正式版本 tag(如 v2.22.0)与预发布 tag(如 rc1a1b2)的正则,决定哪些 git tag 会被视为发布节点;
  • changes_file: changelog.yamlchanges_format: combined:累积的变更历史写入 changelogs/changelog.yaml,且历史以"combined"(合并式)格式组织;
  • keep_fragments: true:发布生成后保留片段文件,不自动清理,便于回溯每个变更对应的原始提交;
  • always_refresh: true:生成时刷新既有内容,保证 changelog.yaml 与片段保持一致;
  • ignore_other_fragment_extensions: true:只处理约定扩展名的片段文件,忽略其他无关文件;
  • notesdir: fragments:片段目录即 changelogs/fragments/
  • prelude_section_name: release_summary:每个版本的"引言"取自片段中的 release_summary 字段(见下文发布脚本部分);
  • new_plugins_after_name: removed_features:插件增删记录紧跟在"已移除特性"分节之后;
  • sections:定义 changelog 正文的八个分节及其显示顺序,从 Major Changes 到 Known Issues。这也是每个片段文件必须使用的合法 key 集合。

变更片段(Fragments)的格式与真实示例

片段就是 fragments/ 目录下的一个小 YAML 文件,文件内容是一个以分节名为 key 的映射,value 为该分节下的条目列表。当前 changelogs/fragments/ 中存在数十个真实片段,例如:

命名上可见两种惯例:<issue号>-<简述>.yml 与纯主题名 <简述>.yml。片段内容的合法 key 只能是 config.yamlsections 中列出的分节名,例如一个典型的 bugfix 片段形如:

bugfixes:
  - rpm_key - fix handling of trailing newline in armored keys (https://github.com/ansible/ansible/issues/87304).

另有一个特殊的发布占位片段 v2.22.0-initial-commit.yaml,其内容为空映射 {},用于标记版本线起点而不携带任何变更条目。

项目对片段的格式约束在 context/documentation-standards.md 中被进一步明确:变更需要在 changelogs/fragments/ 下提供 YAML 条目;片段结构遵循 changelogs/config.yamlsections 定义的分节;提交前应验证片段使用的分节是合法分节。此外 context/coding-style.md 建议 changelog 片段中的文本保持"每行一句话"的风格,便于生成 RST 时排版整齐。

发布时如何生成:release 脚本中的调用链

README 所说的"release process"在仓库中由 packaging/release.py 实现。该脚本的 prepare 命令按固定顺序执行五个步骤(见 packaging/release.py):

@command
def prepare(final: bool = False, pre: str | None = None, version: str | None = None, setuptools: bool | None = None) -> None:
    """Prepare a release."""
    command.run(
        update_version,
        update_setuptools,
        check_state,
        generate_summary,
        generate_changelog,
        create_release_pr,
    )

其中与 changelog 直接相关的两个步骤值得展开:

1. generate_summary——生成版本摘要片段

generate_summary 会向 changelogs/fragments/ 写入一个 {version}_summary.yaml 文件,内容为 release_summary 字段的表格,包含 Release Date 与 Porting Guide 链接:

content = f"""
release_summary: |
   | Release Date: {release_date}
   | `Porting Guide <...porting_guide_core_{major_minor}.html>`__
"""
summary_path.write_text(content.lstrip())

这正是 config.yamlprelude_section_name: release_summary 的消费端——每个版本的 changelog 开头的表格就是由这个片段渲染出来的。

2. generate_changelog——调用 antsibull-changelog 聚合并校验

generate_changelog 先基于 test/lib/ansible_test/_data/requirements/sanity.changelog.txt 与主 requirements 构建独立 venv,然后依次执行:

run("antsibull-changelog", "release", "-vv", "--use-ansible-doc", env=env, cwd=CHECKOUT_DIR)
run("antsibull-changelog", "generate", "-vv", "--use-ansible-doc", env=env, cwd=CHECKOUT_DIR)
run("ansible-test", "sanity", CHANGELOGS_DIR, ANSIBLE_RELEASE_FILE, env=env, cwd=CHECKOUT_DIR)

即先以 release 动作把累积片段归并进版本化 changelog,再 generate 渲染最终内容,最后用 ansible-test sanitychangelogs/ 目录做一致性校验。源码中还留有一行注释表明当前从原内置生成器切换到了 antsibull-changelog# TODO: consider switching back to the original changelog generator...)。

生成完成后,create_release_pr 会提交 changelogs/ 目录、lib/ansible/release.pypyproject.toml 的变更并发起发布 PR(见 packaging/release.py)——这也解释了为什么 README 说发布分支上"已创建的版本"才有版本专属文件:这些文件正是在该 PR 合入后才出现在对应发布分支中。

devel 与发布分支的差异及实用建议

对照 README 的结论,可以形成如下实操对照:

场景 应查看的内容
devel 分支上了解"即将发生的变更" changelogs/fragments/ 下的所有 YAML 片段(devel 没有已生成的 changelog)
在发布分支上核对某版本包含的变更 该分支上已生成的版本级 CHANGELOG-vX.Y.rst 与更新后的 changelogs/changelog.yaml
为自身 PR 记录变更 changelogs/config.yamlsections 选用合法分节,在 changelogs/fragments/ 新增一个 YAML 片段

编写片段时的几条要点(均有仓库依据):分节 key 必须取自 sections 列表;文件放在 changelogs/fragments/;文本一行一句;生成阶段由 antsibull-changelog 统一聚合,因此片段保持小粒度、单主题即可。

小结

ansible-core 的变更日志机制是"片段优先、发布聚合":changelogs/README.md 界定了 devel 分支只存片段、发布分支才有版本文件的基本原则;changelogs/config.yaml 定义了八大分节与生成行为;packaging/release.pyprepare 流程负责在发布时生成 release_summary 摘要片段、调用 antsibull-changelog 完成聚合渲染并通过 ansible-test sanity 校验。理解了这条链路,你在阅读任何 ansible-core 发布分支的 changelog、或为自己的修改补充变更片段时,都能准确判断内容从何而来、应放到何处。

登录后查看全文
热门项目推荐
相关项目推荐