news 2026/9/25 4:24:09

Hypothesis 发布说明写作指南:从 RELEASE.rst 模板到自动化发布管线

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Hypothesis 发布说明写作指南:从 RELEASE.rst 模板到自动化发布管线
  • 测试
  • 开发工具

【免费下载链接】hypothesis

The property-based testing library for Python

项目地址:https://gitcode.com/gh_mirrors/hy/hypothesis
点击查看免费下载

导读

Hypothesis 是一个基于属性的 Python 测试库,其持续交付依赖一套严格的"单文件驱动发布"机制:每一次代码变更都必须伴随一份由贡献者撰写的RELEASE.rst,描述该变更对公共 API 的影响,随后由 CI 工具链自动完成版本递增、changelog 生成与 PyPI 发布。本文以仓库中的模板文件 RELEASE-sample.rst 为骨架,完整解析该模板的每一行语义、SemVer 版本判定规则、Sphinx 交叉引用指令的用法,并结合 release.py 源码与配套测试,带你从"照着填模板"进阶到"理解整条发布流水线",从而为 Hypothesis 贡献代码时一次通过发布检查。

一、RELEASE-sample.rst 在仓库中的定位

在 Hypothesis 仓库中,贡献者提交 PR 时并不直接编辑docs/changelog.rst,而是写入位于hypothesis/目录下的RELEASE.rst。为了让贡献者知道该写什么、怎么写,仓库提供了模板文件RELEASE-sample.rst。两者关系如下:

文件作用
RELEASE-sample.rst只读模板/样例,永远保留在仓库中供参考
RELEASE.rst实际发布描述文件,由贡献者按模板复制创建
changelog.rst官方 changelog,PR 合并后自动吸收RELEASE.rst的内容

这一点在工具源码中有硬性保证:release.py 分别将RELEASE.rst、RELEASE-sample.rst、docs/changelog.rst定义为三个关键路径常量,而配套测试 test_release_files.py 明确要求:RELEASE-sample.rst 必须存在且只能被复制(copy)而不能被移动(move)到 RELEASE.rst,否则直接判为测试失败。

二、第一行:RELEASE_TYPE 与语义化版本判定

模板第一行是发布类型的声明:

RELEASE_TYPE: patch

模板正文随后解释:当变更对公共 API 可见时,将patch替换为minor;当存在破坏性变更时替换为major;并且major 版本只能由维护者(maintainers)发布,普通贡献者不应发起 major 发布。

源码中的解析与校验

从源码看,第一行并非自由文本,而是被严格校验的:

  • release.py 定义了正则^RELEASE_TYPE: +(major|minor|patch)与合法取值集合("major", "minor", "patch");
  • parse_release_file_contents() 会读取文件首行并匹配该正则,若首行缺失或类型不在集合内,直接抛出ValueError并给出明确提示(应如何书写第一行);
  • 解析成功后,第一行会被从正文中剔除,剩余内容即 changelog 正文。

测试 test_release_management.py 专门验证了非法输入(如RELEASE_TYPE: wrong、空文件)会抛出ValueError,合法输入(patch/minor/major及各种空白布局)则被正确解析。

版本号如何被递增

bump_version_info() 实现了语义化版本递增逻辑:

  • patch:第三位 +1(如6.168.0→6.168.1);
  • minor:第二位 +1,后续位清零(如6.167.1→6.168.0);
  • major:第一位 +1,后续位清零。

测试 test_bump_minor_version() 验证了(1, 1, 1)在minor下得到1.2.0,与语义化版本约定完全一致。注意当前版本号并非维护在version.py中,而是由 Rust 原生模块提供(见 version.py),发布时通过 cargo.write_version() 同步更新 Cargo.toml 与锁文件。

三、changelog 正文的写作规范

模板中第一行之后的所有内容,就是本次发布的 changelog 文本。模板给出了三条硬性规范:

  1. 聚焦公共 API:简洁描述"公共 API 发生了什么变化、为什么"。内部实现的变化可以写成类似 "This release improves an internal invariant."(该写法取自 6.99.11 版本的完整 changelog)。
  2. verbatim 代码用双反引号:例如from_type、hypothesis.extra.*,以便 Sphinx 正确渲染成行内代码。
  3. 涉及函数或类必须使用 Sphinx 交叉引用,而非裸写名称或外部链接。

模板中的示例正文是:

This patch improves import-detection in the Ghostwriter (:issue:`3884`), particularly for from_type and strategies from hypothesis.extra.*.

这展示了两种典型写法:用:issue:关联 issue 编号;正文中引用 API 名称时保持与文档一致的可读描述。真实的成功案例可参考当前仓库中的 RELEASE.rst(例如We now publish abi3 wheels for Linux s390x (manylinux) and Linux i686 (musllinux).——一句话讲清发布内容,不啰嗦)。

四、Sphinx 交叉引用指令完整参考

模板后半部分集中列出了所有允许使用的 Sphinx 交叉引用指令,这是本模板最具技术含量的部分,逐条拆解如下:

指令用途示例效果
:pypi:package``链接到外部 PyPI 包链接文本为包名
:func:package.function``链接到函数链接文本为package.function
:func:~package.function``链接到函数(缩写)链接文本仅显示function
:class:package.class``链接到类可同样用~缩写
:issue:issue-number``引用 GitHub issue渲染为 issue 链接
:pull:pr-number``引用 PR通常不首选
:v:6.98.9``引用版本号指向 changelog 对应锚点,对最终用户更有意义
:doc:link text <chapter#anchor>``引用文档章节指向文档内锚点
link text <https://...>__通用 Web 地址双层下划线结尾的显式链接

其中:v:角色并非 Sphinx 内置,而是 Hypothesis 在 conf.py 中自定义的版本引用角色,它会将版本号渲染为指向changelog.html#vX.Y.Z锚点的链接。模板特别提示:引用 PR 时优先用:v:引用版本号而非:pull:,因为版本号对最终用户更有意义。

五、致谢与首次贡献者清单

模板要求 changelog 正文以维护者的感谢语结尾,格式为:

Thanks to <contributor's name or handle> for this <contribution/fix/feature>!

同时提醒:如果是首次贡献,别忘了把自己加入 AUTHORS.rst。这是开源项目维护贡献者名单的标准做法,该文件位于仓库根目录。

六、PR 合并后的自动化发布管线

模板末尾的关键说明是:"After the PR is merged, the contents of this file (except the first line) are automatically added todocs/changelog.rst."。结合源码,这条"自动"路径实际由 do_publish() 串联完成:

  1. 解析并更新版本:update_changelog_and_version() 解析RELEASE.rst得到发布类型,调用bump_version_info计算新版本号,并写入 changelog 顶部——新条目以.. _vX.Y.Z:锚点开头,配-构成的边框线与X.Y.Z - YYYY-MM-DD标题行(格式由 CHANGELOG_ANCHOR/CHANGELOG_BORDER/CHANGELOG_HEADER 三个正则约束);
  2. 同步元数据:更新 Cargo.toml 与锁文件(cargo.write_version())、替换源码中的since="RELEASEDAY"占位日期(release.py)、重写 pyproject.toml 的allextras 与 README 内嵌内容;
  3. 提交并打 tag:commit_pending_release() 移除RELEASE.rst并提交(commit message 含[skip ci]),随后git tag vX.Y.Z并推送;
  4. 发布产物:上传 sdist/wheel 到 PyPI(upload_distribution_to_pypi(),要求ACTIONS_ID_TOKEN_REQUEST_TOKEN环境变量以启用 trusted publishing),并创建 GitHub release 触发 Zenodo DOI 生成(create_github_release(),需要GH_TOKEN)。

此外,文档构建也直接依赖RELEASE.rst:changelog.rst 通过.. only:: has_release_file指令与.. include:: ../RELEASE.rst把"当前 PR 的发布说明"实时嵌入文档,而 conf.py 的setup()会在检测到RELEASE.rst存在时向 Sphinx 添加has_release_filetag——这就是为什么模板要求"复制而非移动":文件必须常驻仓库,文档构建才能正确开关该区块。

七、发布文件的自动检查与防回归保障

整仓测试对发布文件有一套"零容忍"检查,理解这些检查能帮你一次通过 CI:

  • test_release_files.py 的test_release_file_exists_and_is_valid:只要源码(hypothesis/src)有变更,就必须存在RELEASE.rst,且其内容必须能被parse_release_file()成功解析,否则构建直接失败;
  • 同文件的test_release_file_has_no_merge_conflicts:禁止<<<合并冲突残留;发布说明不得与最近 12 个版本中的任意一条重复(防重复发布),也不得反向包含(防复制粘贴 merge 错误);自动更新消息(如升级依赖、更新 TLD 列表时由 get_autoupdate_message() 自动生成的模板文本)例外放行。

这意味着:提交 PR 前请务必检查git status中是否有hypothesis/src下的改动;若有,则必须照模板新建RELEASE.rst,否则会卡在发布检查环节。

八、从模板到实战:一份合格 RELEASE.rst 的核对清单

综合模板规范与源码约束,写一份合格发布说明可对照以下清单:

  1. 首行RELEASE_TYPE: patch(或minor;major仅限维护者);
  2. 一句话说清公共 API的变化及原因,内部改动用 "This release improves an internal invariant." 这类表述;
  3. 代码标识用双反引号包裹;
  4. 函数/类引用使用:func:/:class:(需要缩写时加~);
  5. issue 用:issue:,PR 用:pull:,版本引用优先用:v:;
  6. 外部包用:pypi:,文档章节用:doc:;
  7. 以感谢语结尾,首次贡献者加入AUTHORS.rst;
  8. 不要包含合并冲突标记,不要复制已发布版本的旧文本。

遵循这套流程写出的发布说明,会在 PR 合并后自动变成docs/changelog.rst中最顶部那条带锚点的正式记录——正如 changelog.rst 中6.168.0 - 2026-09-08条目所展示的最终形态,你在模板里写的每一行,最终都会成为数百万用户阅读的官方发布历史。

  • 测试
  • 开发工具

【免费下载链接】hypothesis

The property-based testing library for Python

项目地址:https://gitcode.com/gh_mirrors/hy/hypothesis
点击查看免费下载

相关推荐

上一篇:Reactide终极部署指南:从零开始打造专业React开发环境
下一篇:RabbitMQ 3.6.11 维护版本详解:内存计算策略变更、OTP 20 支持与关键缺陷修复

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 4:23:19

MATLAB贝叶斯分类实战:从先验设置到可部署模型

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 4:22:16

从零实现模型预测控制:QP求解器选型与轨迹跟踪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 4:21:35

西门子S7-1500与KUKA机器人PROFINET通讯配置与调试实战详解

做了几年西门子PLC和KUKA机器人联调的活计&#xff0c;说实话&#xff0c;大多数项目里真正耗时间的并不是机器人程序本身&#xff0c;反而是PLC和机器人之间那根“看不见的网线”。很多刚上手的工程师&#xff0c;设备买回来&#xff0c;S7-1500和KUKA机器人摆在面前&#xff…

作者头像 李华
网站建设 2026/9/25 4:21:33

墨水屏+NB-IoT/GPRS双模HAT:工业级低功耗远程电子标签方案

简介&#xff1a;本资源是一套面向嵌入式物联网开发者的墨水屏NB-IoT/GPRS双模通信HAT扩展板实战DEMO代码&#xff0c;适用于树莓派等微控制器平台&#xff0c;聚焦低功耗远程显示终端的快速原型开发与协议集成学习。压缩包含151个文件&#xff0c;主体为40个C源文件、34个头文…

作者头像 李华
网站建设 2026/9/25 4:21:07

渗透测试中的Fuzz技术详解:从原理到实战的完整指南

渗透测试里的"fuzz"这个词&#xff0c;几乎每个刚入门的人都会在某个阶段卡一下。我第一次听到的时候也懵——字面意思是"模糊"&#xff0c;跟测试有什么关系&#xff1f;后来在实战里被它救过几次&#xff0c;也因为它翻过车&#xff0c;才慢慢摸清楚这东…

作者头像 李华