发布与分发

前言

本文档涵盖了管理当前次要版本更新和发布新版本的过程。 在本文档中,git远程upstream指的是主要的QuTiP组织仓库,而origin指的是您个人的分支。

简而言之,您需要采取的步骤是:

  1. 准备发布分支(参见 git)。

  2. 运行“构建轮子,可选部署到PyPI”的GitHub操作来构建二进制和源代码包,并将它们上传到PyPI(参见deploy)。

  3. 创建一个GitHub发布并将构建的文件上传到其中(参见github)。

  4. 更新 qutip.org 上的新链接和文档 (web)。

  5. 更新conda feedstock,将包部署到conda (cforge)。

设置发布分支

在这一步中,您将在主QuTiP存储库上准备一个git分支,该分支包含即将发布的代码状态。 如果您正在发布一个新的次要或主要版本,与如果您正在制作一个错误修复补丁版本相比,这个过程有很大的不同。 对于新的次要或主要版本,请执行更新日志,然后跳转到发布。 对于现有版本的错误修复,请执行更新日志,然后跳转到错误修复

不向后兼容的更改只能在主要版本中进行。 不影响向后兼容性的新功能可以在次要版本中添加。 错误修复版本应该很小,只修复错误,不引入任何新功能。

在日常开发过程中,有一些步骤应该保持最新,但可能并不完全准确。 对于即将成为发布内容的每一个更改,请确保:

  • 文档中的用户指南已更新,包含任何新功能或现有功能的更改。

  • 任何新的API类或函数在doc/apidoc中的适当RST文件中都有条目。

  • 任何新的或更改的文档字符串都是最新的,并在API文档中正确呈现。

请向master提交一个正常的PR,修正这些点中缺失的内容,并在开始发布之前将其合并,如有必要。

更新需求

确保QuTiP的测试在要求中支持的最旧版本上通过。 在主要和次要版本上,要求可以向上调整,但补丁版本不得更改最低要求。 我们遵循NEP29以确定最低支持的版本。

- All minor versions of Python released 42 months prior to the project, and at minimum the two latest minor versions.
- All minor versions of numpy and scipy released in the 24 months prior to the project, and at minimum the last three minor versions.

如果需要更新依赖版本,请在主分支中更新它们。可能需要更新的文件包括:.github/workflows/tests.ymlsetup.cfgroadmap.rst。最后,确保 PyPI 轮子和 conda 构建至少涵盖这些版本。

更新变更日志

无论进行何种类型的发布,这都需要完成。

  1. 创建一个新分支以用于提出拉取请求。

  2. 使用 towncrier 更新变更日志:

    towncrier build –version=<版本号>

其中 是预期的版本号

  1. 在主qutip/qutip仓库上提交一个包含此变更日志的拉取请求,并让管理团队的其他成员批准它。

  2. 将此合并到 master

现在跳转到release如果你正在进行主要或次要版本发布,或者跳转到bugfix如果你只是在修复之前版本中的错误。

创建新的次要或主要版本

这涉及到创建一个新的分支来保存发布,并添加一些提交以将代码设置为“发布”模式。 此发布应通过直接从master分支的当前头部进行分支来完成。

  1. 在您的机器上,确保您的master副本是最新的(git checkout master; git pull upstream master)。 这至少应该包括获取您刚刚制作的更改日志PR。 现在,从master中的一个提交创建一个新分支,该提交具有您想要发布的代码状态。 命令是git checkout -b qutip-..X,例如qutip-4.7.X。 这个分支名称将是公开的,并且必须遵循此格式。

  2. 将新分支(相对于master没有提交)推送到主qutip/qutip仓库(git push upstream qutip-4.7.X)。 创建分支是唯一可以不经拉取请求直接推送到qutip/qutip的情况之一。

  3. 创建第二个新分支,该分支将被推送到你的fork,并用于对刚刚创建的qutip/qutip上的qutip-..X分支发起拉取请求。 你可以随意命名这个分支,因为它不会进入主仓库,例如git checkout -b prepare-qutip-4.7.0

    • VERSION文件更改为包含确切的新版本号,删除.dev后缀。 例如,如果您正在发布4.7小版本的首个版本,请将VERSION设置为包含字符串4.7.0。 (特殊情况:如果您正在制作alpha、beta或候选版本,请在版本字符串后附加.a.b.rc,其中是从0开始的整数,用于计算该预发布版本的次数。)

    • 编辑 setup.cfg,将 classifiers 部分中的“Development Status”行更改为

      Development Status :: 5 - Production/Stable
      

    提交两个更改(git add VERSION setup.cfg; git commit -m "Set release mode for 4.7.0"),然后将它们推送到你的分支(git push -u origin prepare-qutip-4.7.0

  4. 使用 GitHub,向发布分支(例如 qutip-4.7.X)提交一个拉取请求,使用你刚刚创建的这个分支。 你需要在拉取请求中更改“基础分支”,因为 GitHub 最初总是会尝试将 PR 提交到 master。 当测试通过后,将其合并。

  5. 最后,回到master分支,创建一个新的拉取请求,将VERSION文件更改为.dev,例如4.8.0.dev。 在master分支上的setup.cfg中的“开发状态”不应更改,并且应为

    Development Status :: 2 - Pre-Alpha
    

    因为 master 从未直接发布。

你现在应该可以在GitHub网站上看到一个名为qutip-4.7.X(或任何小版本号)的分支,其中的代码状态应该正是你想要作为新小版本发布的内容。 如果你注意到你犯了错误,你可以向发布分支提交额外的拉取请求来修复它。 master分支看起来应该非常相似,除了VERSION会更高并且带有.dev后缀,以及setup.cfg中的“开发状态”会有所不同。

  • 激活新创建版本分支的readthedocs构建,并将其设置为最新版本。

你现在已经准备好实际执行发布了。 前往 deploy

创建一个错误修复版本

在这里,您将通过“cherry-picking”一个或多个已经合并到master的拉取请求(包括您的新变更日志)来修改一个已经发布的分支,并增加版本号的“patch”部分。

  1. 在您的机器上,确保您的master副本是最新的(git checkout master; git pull upstream master)。 特别是,确保您在第一步中编写的更改日志是可见的。

  2. 找到你将修改的发布分支。 这应该已经存在于qutip/qutip仓库中,并且被称为qutip-..X(例如qutip-4.6.X)。 如果你看不到它,运行git fetch upstream以从主仓库更新所有分支引用。 从发布分支的头部检出一个新的私有分支(git checkout -b prepare-qutip-4.6.1 upstream/qutip-4.6.X)。 你可以随意命名这个分支(在示例中是prepare-qutip-4.6.1),因为它只会用于创建一个拉取请求。

  3. 按顺序挑选所有将添加到此次发布中的提交,包括编写新变更日志条目的PR(这将是您最后挑选的一个)。 您需要使用git log来查找相关的提交,从最旧到最新(它们的“年龄”是指它们被合并到master的时间,而不是PR首次打开的时间)。 根据特定PR使用的合并策略,命令略有不同:

    • “merge”:你只需要找到一个提交,尽管日志中可能包含多个;在git log中会有一个标题为“Merge pull request #1000 from <…>”的条目。 注意其哈希值的前7个字符。 通过git cherry-pick --mainline 1 进行cherry-pick。

    • “squash and merge”:整个PR只会有一个提交。 它的名称将是“<拉取请求的名称> (#1000)”。 注意其哈希值的前7个字符。 通过git cherry-pick 来挑选这个提交。

    • “rebase and merge”:这是最困难的,因为会有很多提交需要你手动查找,并且需要逐个挑选。 转到GitHub页面的这个PR,然后转到“Commits”标签。 使用你本地的git log(你可能会发现git log --oneline很有用),找到GitHub页面上列出的每个提交的哈希值,按从旧到新的顺序(在GitHub视图中从上到下,在git log中从下到上)。 你需要使用提交信息来完成这个操作;GitHub报告的哈希值可能与你本地的不同。 找到每个哈希值的前7个字符。 通过git cherry-pick ... 一次性挑选这些提交,其中是最旧的。

    如果任何精选提交有合并冲突,首先确认你是按从旧到新的顺序进行精选提交。 如果你仍然有合并冲突,你需要手动修复它们(如果这是一个非常简单的修复),或者你需要找到这个补丁依赖的额外PR,并重新开始包括这个额外补丁的错误修复过程。 如果你坚持进行非常小的错误修复,这种情况通常不应该发生;如果修复有深远的影响,可能更适合进行一个新的小版本发布。

  4. 通过将VERSION文件中的最后一个数字加一(两位数也是可以的,所以4.6.104.6.9之后),并提交更改。

  5. 将此分支推送到你的fork,并针对发布分支创建一个拉取请求。 在GitHub的PR屏幕上,你需要将“Base”分支更改为qutip-4.6.X(或任何版本),因为GitHub默认会将其针对master。 如果你忘记这样做,应该会非常明显,因为可能会有很多合并冲突。 一旦测试通过并且你获得了另一位管理员的批准,就可以合并PR。

你现在应该看到GitHub上的qutip-4.6.X(或其他)分支已经更新,并且现在包含了你刚刚所做的所有更改。 如果你犯了错误,可以随时提交额外的PR来纠正这种情况。

你现在已经准备好实际执行发布了。 前往 deploy

构建发布分发和部署

此步骤构建源(sdist)和二进制(wheel)分发文件,并将它们上传到PyPI(pip)。 您还可以自己下载构建的文件以上传到QuTiP网站。

构建和部署

这完全由GitHub Action处理。 前往QuTiP代码仓库顶部的“Actions”标签。 点击左侧边栏中的“Build wheels, optionally deploy to PyPI”操作。 点击标题通知中的“Run workflow”下拉菜单;它应该看起来像下面的图片。

../_images/release_guide_run_build_workflow.png
  • 使用下拉菜单选择您想要发布的分支或标签。 这应该被称为qutip-4.5.X或类似的名称,具体取决于您之前创建的内容。 这绝不能是master

  • 要发布到PyPI,请在“确认所选分支名称[…]”字段中输入分支名称(例如qutip-4.5.X)。 您可以将此字段留空以跳过部署并仅构建包。

  • (特殊情况)如果由于某些原因您需要覆盖版本号(例如,如果之前部署到PyPI 仅部分成功),您可以在“覆盖版本号”字段中输入有效的 Python 版本标识符。 您可能不需要这样做。 该机制旨在使使用夜间发布进行主要升级的 alpha 测试更容易。 即使是错误修复版本,您也应该将更改提交到 VERSION 文件。

  • 点击下方的“运行工作流程”以执行构建和部署。

此时,部署将自动进行。 大约需要30分钟到1小时,之后新版本将可以通过pip install qutip进行安装。 你应该能在QuTiP的PyPI页面上看到新版本的出现。

下载构建文件

当构建完成后,点击进入其摘要屏幕。 这是用于监控构建并查看其输出的主屏幕,成功时应如下图所示。

../_images/release_guide_after_workflow.png

构建的二进制轮子和源代码分发是底部的“构建产物”。 你需要下载轮子和源代码分发。 将它们保存在你的计算机上,并解压这两个文件;你应该有许多轮子 qutip-*.whl 文件,以及两个 sdist 文件:qutip-*.tar.gzqutip-*.zip。 这些文件与刚刚上传到 PyPI 的文件相同。

监控进度(可选)

在构建进行过程中,您可以通过点击“运行工作流”按钮下方列表中的条目来监控其进度。 您应该会看到几个子任务,类似于已完成屏幕,但它们可能尚未完成。

“验证 PyPI 部署确认”应该被勾选,无论如何。 如果失败,您可能在下拉菜单中忘记了选择正确的分支,或者在确认正确分支时输入了错误的内容,您需要重新开始此步骤。 您可以通过点击“验证 PyPI 部署确认”任务,并打开“比较确认与当前参考”子任务来检查部署指令是否已被理解。 如果您输入了确认信息,您将看到一条消息说“将部署构建的轮子”,如果您没有输入确认信息,您将看到“仅构建轮子”。 如果您看到“仅构建轮子”但您打算将发布部署到 PyPI,您可以取消工作流并在输入确认信息后重新运行它。

在GitHub上发布版本

这一切都是通过“Releases”部分在GitHub上的qutip/qutip仓库完成的。

  • 点击“Draft a new release”按钮。

  • 在下拉菜单中选择适合您版本的正确分支(例如 qutip-4.5.X)。

  • 对于标签名称,使用v,其中版本与VERSION文件中的内容匹配。 换句话说,如果你正在发布微版本4.5.3,使用v4.5.3作为标签,或者如果你正在发布主版本5.0.0,使用v5.0.0

  • 标题是“QuTiP ”,例如“QuTiP 4.6.0”。

  • 对于描述,请简要(约两行用于补丁发布)总结此版本的原因,并注意任何需要特别关注的面向用户的更改。 在下面,放置您在文档发布时编写的更改日志。 请注意,更改日志的.rst文件与此描述字段的Markdown之间可能存在一些语法差异(例如,GitHub的Markdown通常保持硬换行符,这可能不是您想要的)。

  • 将构建步骤后获得的所有qutip-*.whlqutip-*.tar.gzqutip-*.zip文件拖放到资产框中。 如果尚未解压,您可能需要解压wheels.zipsdist.zip文件以找到它们;不要上传这两个zip文件。

点击“发布版本”按钮以完成。

网站

这假设qutip.github.io已经被分叉,并且熟悉网站更新的工作流程。 文档不需要为每个补丁版本更新。

HTML 文件更新

  • 编辑 download.html

    • ‘最新发布’版本和日期应更新。

    • tar.gz 和 zip 链接需要在其文件名、标签和 trackEvent javascript 中更新其微版本号。 这些链接应指向您在 GitHub Releases 部分中创建时出现的“源代码”链接。 它们应该看起来像 https://github.com/qutip/qutip/archive/refs/tags/v4.6.0.tar.gz

    • 对于次要或主要版本,需要将前一个版本的最后一个微版本的链接移动(复制)到“先前版本”部分。

  • 编辑 _includes/sidebar.html

    • 添加新版本和发布日期。只应列出积极开发的版本。微版本替换之前的条目,但最后一个主要版本可以保留。

    • 应更新安装说明、文档、源代码和变更日志的链接。

  • 编辑 documentation.html

    • 对于主要和次要版本发布,应将之前版本的标签移动(复制)到“先前发布”部分,并将新版本的readthedocs链接添加到“最新发布”部分。

Conda Forge

如果之前没有完成,请分叉 qutip-feedstock

在你的分支上检出一个新分支,例如。

$ git checkout -b version-4.0.2

找到GitHub网页界面在生成名为“源代码”的发布时生成的tarball的sha256校验和。 这不是你之前下载的sdist,而是GitHub标记为“源代码”的新文件。 不过,当你下载它时,它的名字会看起来像是sdist。

$ openssl sha256 qutip-4.0.2.tar.gz

编辑recipe/meta.yaml文件。 更改文件顶部的版本,并更新sha256校验和。 检查配方包版本要求至少与setup.cfg中的匹配,并确保构建过程中的任何更改都反映在meta.yml中。 同时确保重置构建编号

build:
    number: 0

将更改推送到你的分支,例如

$ git push --set-upstream origin version-4.0.2

提交一个拉取请求。 这将触发包构建过程的测试。

如果(当)测试通过时,PR 可以被合并,这将触发将包上传到 conda-forge 频道。 要测试这些包,请以最低优先级添加 conda-forge 频道

$ conda config --append channels conda-forge

这意味着先决条件来自默认通道,但qutip包在conda-forge中找到。