发布指南#

本文档仅适用于 Matplotlib 发布管理者.

一份为进行 Matplotlib 发布的开发者准备的指南.

版本控制方案#

Matplotlib 遵循 Intended Effort Versioning (EffVer) 版本控制方案:主版本号.中期版本号.次要版本号.

主版本号

一个我们期望用户花费大量精力来升级的版本.从 v1 到 v2 的过渡包括对默认样式的全面修改,而从 v2 到 v3 的过渡涉及放弃对 Python 2 的支持.

未来的主版本更新将包括规模相当的更改,这些更改无法在中期版本中逐步完成.

中期版本号

一个我们期望用户花费一些精力来升级的版本.我们的目标是每 6 个月发布一个中期版本.这些版本的目的主要是向用户发布新功能,但也包含根据 our policy 有意的功能弃用和删除.

次要版本号

一个我们期望用户几乎不需要任何精力即可升级的版本.根据我们的 反向移植策略 ,我们只将错误修复反向移植到维护分支.我们期望对用户的影响最小,只是可能会破坏对已修复错误的解决方法或"bugs being used as features ".

这些版本会根据需要发布,但通常在中期版本之间每 1-2 个月发布一次.

创建发布分支#

备注

这假设规范仓库的只读远程仓库是"remote",读/写远程仓库是"DANGER"

当新的中期版本(vX.Y.0)即将发布时,必须创建一个新的发布分支.具体何时发生取决于发布管理者,但此时是大多数针对中期版本的新功能合并的地方,并且您正在进入功能冻结期(即,新实现的功能将进入 vX.Y+1).这并不一定意味着在发布之前不会进行任何进一步的更改,只是这些更改将使用反向移植系统进行.

对于即将发布的 v3.7.0 版本,首先创建分支:

git switch main
git pull
git switch -c v3.7.x
git push DANGER v3.7.x

更新 v3.7.0 里程碑,以便描述如下:

New features and API changes

on-merge: backport to v3.7.x

次要版本应改为:

Bugfixes and docstring changes

on-merge: backport to v3.7.x

检查所有活动里程碑的一致性.较旧的里程碑也应反向移植到更高的中期版本(例如,一旦 v3.7.x 分支存在并且 PR 反向移植仍然以 v3.6.x 为目标,则 v3.6.3v3.6-doc 应反向移植到 v3.6.xv3.7.x ).

为下一个中期版本创建里程碑(即 v3.9.0 ,因为 v3.8.0 应该已经存在).虽然大多数活动项目应该进入下一个中期版本,但此里程碑可以帮助进行长期规划,尤其是在弃用周期方面.

测试#

我们使用 GitHub Actions 进行持续集成.在准备发布时,最终标记的提交应在上传之前在本地进行测试:

pytest -n 8 .

此外,应运行以下测试并手动检查:

python tools/memleak.py agg 1000 agg.pdf

运行 NBAgg 和 ipympl 后端的用户接受测试:

jupyter notebook lib/matplotlib/backends/web_backend/nbagg_uat.ipynb

对于 ipympl,重新启动内核,添加一个单元格 %matplotlib widget ,不要运行带有 matplotlib.use('nbagg') 的单元格. 检查 connection_info ,使用 reshow 或测试 OO 接口的测试预计不适用于 ipympl .

GitHub 统计信息#

我们通过 API 从 GitHub 自动提取 GitHub issue,PR 和作者.准备此列表:

  1. 存档现有的 GitHub 统计信息页面.

    1. 将当前的 doc/users/github_stats.rst 复制到 doc/users/prev_whats_new/github_stats_X.Y.Z.rst .

    2. 更改文件顶部的链接目标.

    3. 删除末尾的"之前的 GitHub 统计信息"部分.

    例如,当从 v3.7.0 更新到 v3.7.1 时:

    cp doc/users/github_stats.rst doc/users/prev_whats_new/github_stats_3.7.0.rst
    $EDITOR doc/users/prev_whats_new/github_stats_3.7.0.rst
    # Change contents as noted above.
    git add doc/users/prev_whats_new/github_stats_3.7.0.rst
    
  2. 重新生成更新后的统计信息:

    python tools/github_stats.py --since-tag v3.7.0 --milestone=v3.7.1 \
        --project 'matplotlib/matplotlib' --links > doc/users/github_stats.rst
    
  3. 查看并提交更改.某些 issue/PR 标题可能不是有效的 reST(最常见的问题是 * ,它被解释为未闭合的标记). 另请确认 codespell 没有发现任何问题.

备注

确保您已通过 GitHub API 进行身份验证. 如果不这样做,您将因超出 API 速率限制而被 GitHub 阻止.您可以通过以下两种方式之一进行身份验证:

  • 使用 keyring 包; pip install keyring ,然后在运行统计脚本时,系统会提示您输入用户名和密码,这些信息将存储在您的系统密钥环中,或者,

  • 使用个人访问令牌;在 on this GitHub page 上生成一个新令牌,范围为 repo:public_repo ,并将令牌放在 ~/.ghoauth 中.

更新并验证文档#

合并 *-doc 分支#

将最新的 'doc' 分支(例如 v3.7.0-doc )合并到您要标记的分支中,并删除 GitHub 上的 doc 分支.

更新安全策略中支持的版本#

在进行宏版本或中版本发布时,请更新 SECURITY.md 中安全策略中支持的版本.

对于中版本发布,请更新 SECURITY.md 中的表格,以指定当前宏版本系列中最新的两个中版本发布受到支持.

对于宏版本发布,请更新 SECURITY.md 中的表格,以指定之前的宏版本系列中的最后一个中版本仍然受到支持. 放弃对宏版本系列的最后一个版本的支持将以特别处理的方式进行.

更新发行说明#

新功能#

仅宏版本和中版本发布需要.Bugfix 版本不应包含新功能.

doc/users/next_whats_new/ 中所有文件的内容合并到单个文件 doc/users/prev_whats_new/whats_new_X.Y.0.rst 中,并删除各个文件.

API 更改#

主要用于宏版本和中版本发布. 我们有时会在微版本发布中进行 API 更改.

doc/api/next_api_changes/ 中所有文件的内容合并到单个文件 doc/api/prev_api_changes/api_changes_X.Y.Z.rst 中,并删除各个文件.

发行说明 TOC#

更新 doc/users/release_notes.rst :

  • 对于宏版本和中版本发布,添加一个新部分

    X.Y
    ===
    .. toctree::
        :maxdepth: 1
    
        prev_whats_new/whats_new_X.Y.0.rst
        ../api/prev_api_changes/api_changes_X.Y.0.rst
        prev_whats_new/github_stats_X.Y.0.rst
    
  • 对于微版本发布,将 GitHub 统计信息和(如果存在)API 更改添加到现有的 X.Y 部分

    ../api/prev_api_changes/api_changes_X.Y.Z.rst
    prev_whats_new/github_stats_X.Y.Z.rst
    

更新版本切换器#

更新 doc/_static/switcher.json :

  • 如果是微版本发布 X.Y.Z ,则无需更改.

  • 如果是中版本发布 X.Y.0 ,则更改 name: X.Y+1 (dev)name: X.Y (stable) 的名称,并为之前的稳定版本添加一个新版本 ( name: X.Y-1 ).

验证文档是否构建成功#

最后,请确保文档构建顺利:

make -Cdoc O=-j$(nproc) html latexpdf

构建文档后,检查所有链接(内部和外部)是否仍然有效. 我们为此使用 linkchecker

pip install linkchecker
pushd doc/build/html
linkchecker index.html --check-extern
popd

解决可能出现的任何问题. 内部链接在 Circle CI 上进行检查,因此这只会标记失败的外部链接.

创建发布提交和标签#

要创建标签,首先创建一个空提交,并在提交消息中使用非常简洁的发行说明集:

git commit --allow-empty

然后使用正文消息中的相同文本创建一个带签名的带注释的标签:

git tag -a -s v3.7.0

这将提示您输入 GPG 密钥密码和注释. 对于预发布版本,按照 PEP 440 进行操作非常重要,以便构建工件在 PyPI 中正确排序.

为了防止任何下游构建器从 GitHub 下载 tarball 时出现问题,重要的是将所有分支从带有标签的提交中移开 [1]

git commit --allow-empty

最后,将标签推送到 GitHub:

git push DANGER v3.7.x v3.7.0

恭喜,最可怕的部分已经完成! 这假定已创建发布分支. 通常,这是在中版本版本的功能冻结时完成的(通常与之前的中间版本的最后一个微版本同时发生)

如果这是一个最终版本,还要创建一个 'doc' 分支 (预发布版本不执行此操作):

git branch v3.7.0-doc
git push DANGER v3.7.0-doc

更新 (或创建) v3.7-doc 里程碑.描述应包含 meeseeksmachine 指令,将带有 v3.7-doc 里程碑的更改向后移植到 v3.7.x 分支和 v3.7.0-doc 分支:

Documentation changes (.rst files and examples)

on-merge: backport to v3.7.x
on-merge: backport to v3.7.0-doc

检查所有活跃的里程碑,确保一致性.较旧的 doc 里程碑也应向后移植到更高的 meso 版本 (例如,如果 v3.7.x 分支存在,则 v3.6-doc 应向后移植到 v3.6.xv3.7.x )

发布管理 / DOI#

通过 GitHub UI ,将新推送的标签转换为发布版本.如果这是一个预发布版本,请记住将其标记为预发布版本.

对于最终版本,还要从 Zenodo 获取 DOI (一旦标签被推送,它将自动生成一个 DOI).将 DOI 后缀和版本添加到 tools/cache_zenodo_svg.py 中的字典中,并运行脚本.

这会将新的 SVG 下载到 doc/_static/zenodo_cache/postfix.svg 并编辑 doc/project/citing.rst .将新的 SVG,对 tools/cache_zenodo_svg.py 的更改以及对 doc/project/citing.rst 的更改提交到 VER-doc 分支并推送到 GitHub.

git checkout v3.7.0-doc
$EDITOR tools/cache_zenodo_svg.py
python tools/cache_zenodo_svg.py
git commit -a
git push DANGER v3.7.0-doc:v3.7.0-doc

构建二进制文件#

我们通过 PyPI 分发 macOS,Windows 和许多 Linux wheels 以及一个源代码 tarball.大多数构建器应该在标签推送到 GitHub 后自动触发:

  • Windows,macOS 和 manylinux wheels 在 GitHub Actions 上构建.构建由 .github/workflows/cibuildwheel.yml 中定义的 GitHub Action 触发,wheels 将作为构建的 artifacts 提供.一旦所有 wheels 构建完成,源代码 tarball 和 wheels 将自动上传到 PyPI.

  • auto-tick bot 应该打开一个拉取请求到 conda-forge feedstock .审查并合并 (如果你有权限的话).

警告

因为这是自动化的,所以将所有分支从标签上移开非常重要,如 创建发布提交和标签 中所讨论的.

手动上传到 PyPI#

备注

如上所述,GitHub Actions 工作流程应自动构建和上传源代码 tarball 和 wheels.如果出于某种原因,您需要手动上传这些 artifacts,请按照本节中的说明进行操作.

一旦你收集到所有的 wheels (预计需要几个小时),生成 tarball:

git checkout v3.7.0
git clean -xfd
python -m build --sdist

并将所有的 wheels 复制到 dist 目录.首先,检查 dist 文件是否正常:

twine check dist/*

然后使用 twine 将所有文件上传到 PyPI

twine upload -s dist/matplotlib*tar.gz
twine upload dist/*whl

恭喜,你现在已经完成了第二可怕的部分!

构建和部署文档#

要构建文档,您必须安装已标记的版本,但从 ver-doc 分支构建文档.一种简单的方法是:

pip install matplotlib
pip install -r requirements/doc/doc-requirements.txt
git checkout v3.7.0-doc
git clean -xfd
make -Cdoc O="-t release -j$(nproc)" html latexpdf LATEXMKOPTS="-silent -f"

这将构建 HTML 和 PDF 版本的文档.

构建的文档存在于 matplotlib.github.com 存储库中.将更改推送到 main 会自动更新网站.

文档按版本组织在子目录中.最新的稳定版本从 stable 目录进行符号链接.当前 main 的文档在 Circle CI 上构建并推送到 devdocs 存储库.这些可以在 matplotlib.org/devdocs 上找到.

假设您已在与 matplotlib 相同的目录下检出此存储库:

cd ../matplotlib.github.com
cp -a ../matplotlib/doc/build/html 3.7.0
rm 3.7.0/.buildinfo
cp ../matplotlib/doc/build/latex/Matplotlib.pdf 3.7.0

这将复制构建的文档.如果这是最终版本,请将 stable 子目录链接到最新版本:

rm stable
ln -s 3.7.0 stable

您还需要编辑 sitemap.xmlversions.html 以包含新发布的版本.现在提交并将所有内容推送到 GitHub

git add *
git commit -a -m 'Updating docs for v3.7.0'
git push DANGER main

恭喜,您现在已经完成了第三个最可怕的部分!

如果您有访问权限,请清除 CloudFlare 缓存.

网站通常需要大约 5-10 分钟来处理推送并更新实时网页(请记住清除浏览器缓存).

将更改合并到主分支#

完成发布后,应将发布分支中的更改合并到 main 分支中.这主要是为了使发布的标签位于主分支上,以便 git describe (以及 setuptools-scm )具有最新的标签.其次,在发布期间所做的更改(包括删除个性化的发行说明,修复断开的链接和更新版本切换器)会添加到 main .

很可能出现 Git 冲突,但除了直接对发布分支所做的更改(主要作为发布的一部分)之外,通过使用 main 中的版本应该可以相对容易地解决这些冲突.这不是一个普遍的规则,应注意确保正确性:

git switch main
git pull
git switch -c merge_up_v3.7.0
git merge v3.7.x
# resolve conflicts
git merge --continue

由于 main 分支的分支保护,这是通过标准拉取请求合并的,尽管预计 PR 清洁度状态检查将失败.不应压缩 PR,因为其目的是合并分支历史记录.

宣传此次发布#

在将版本发布到 PyPI 和 conda 之后,应通过我们的沟通渠道宣布它:

Conda 包#

Matplotlib 项目本身不发布 conda 包.特别是,Matplotlib 发布经理不负责 conda 打包.

有关为 conda-forge 打包 Matplotlib 的信息,请参阅 conda-forge/matplotlib-feedstock.