发布指南#

本文档仅与 Matplotlib 发布管理员相关。

为进行 Matplotlib 发布的开发者提供的指南。

版本控制方案#

Matplotlib 遵循 Intended Effort Versioning (EffVer) 版本控制方案:macro.meso.micro

我们预计用户需要付出大量努力才能升级到的版本。v1 到 v2 的过渡包括对默认样式的全面改造,而 v2 到 v3 的过渡则涉及放弃对 Python 2 的支持。

未来的宏版本将包括规模相当的更改,这些更改无法在微发布中逐步完成。

meso

我们预计用户需要付出一些努力来升级的版本。我们每6个月发布一个 Meso 版本。这些版本主要旨在向用户发布新功能,但根据 我们的政策,它们也包含有意弃用和移除的功能。

我们期望用户能够轻松升级到此版本,几乎不需要任何努力。根据我们的 回溯策略 ,我们只将错误修复回溯到维护分支。我们预计除了可能打破对已修复错误的变通方法或 将错误用作功能 之外,对用户的影响最小。

这些是按需发布的,但通常在介观版本之间每1-2个月发布一次。

创建发布分支#

备注

这假设规范仓库的只读远程为 remote,而读写远程为 DANGER

当一个新的meso版本(vX.Y.0)即将发布时,必须创建一个新的发布分支。具体何时进行这一操作由发布经理决定,但这一时间点是大多数为meso版本设计的新功能合并的地方,并且你将进入功能冻结期(即新实现的功能将进入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提取问题、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. 审查并提交更改。一些问题/PR 标题可能不是有效的 reST(最常见的问题是 *,它被解释为未关闭的标记)。同时确认 codespell 没有发现任何问题。

备注

确保你对 GitHub API 进行身份验证。如果你不这样做,GitHub 会因为你超过 API 速率限制而阻止你。你可以通过以下两种方式之一进行身份验证:

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

  • 使用个人访问令牌;在 这个GitHub页面 生成一个新令牌,使用 repo:public_repo 范围,并将令牌放置在 ~/.ghoauth 中。

更新并验证文档#

合并 *-doc 分支#

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

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

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

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

对于宏版本发布更新,请在 SECURITY.md 中更新表格,以指定前一个宏版本系列中的最后一个中版本仍受支持。取消对宏版本系列最后一个版本的支持将根据具体情况处理。

更新发布说明#

新增内容#

仅在宏和介观发布时需要。错误修复发布不应包含新功能。

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 中,并删除这些单独的文件。

发行说明目录#

更新 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

检查所有活动里程碑的一致性。较旧的文档里程碑也应向后移植到更高的中尺度版本(例如,v3.6-doc 应向后移植到 v3.6.xv3.7.x,如果 v3.7.x 分支存在)

发布管理 / DOI#

通过 GitHub UI,将新推送的标签转换为发布。如果这是一个预发布,记得将其标记为预发布。

对于最终版本,还需要从 Zenodo 获取 DOI(一旦推送标签,Zenodo 将自动生成一个)。将 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 的 wheel 文件以及源代码 tarball。大多数构建器在标签推送到 GitHub 后应自动触发:

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

  • 自动标签机器人应该在 conda-forge feedstock 中打开一个拉取请求。审查并合并(如果你有权限的话)。

警告

由于这是自动化的,因此按照 创建发布提交和标签 中的讨论,将所有分支从标签中移出极其重要。

手动上传到 PyPI#

备注

如上所述,GitHub Actions 工作流程应自动构建并上传源代码压缩包和 wheel 包。如果由于某些原因,您需要手动上传这些工件,请按照本节中的说明操作。

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

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

并将所有轮子复制到 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 仓库中。将更改推送到主分支会自动更新网站。

文档按版本组织在子目录中。最新的稳定版本从 stable 目录中创建符号链接。当前主分支的文档在 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