维护者信息#

发布#

本节介绍如何准备主/次要版本、候选版本 (RC) 或错误修复版本。我们遵循PEP440 的版本方案,并指示不同类型的版本。我们的约定是遵循“主版本.次版本.微版本”方案,尽管实际上主版本和次要版本之间没有根本区别,微版本是错误修复版本。

我们采用了以下发布计划:

  • 每 6 个月发布主/次要版本,通常在 5 月和 11 月。这些版本的编号为X.Y.0,前面是一个或多个候选版本X.Y.0rcN

  • 错误修复版本根据需要在主/次要版本之间发布,并且仅适用于最新的稳定版本。这些版本的编号为X.Y.Z

准备工作

  • 确认已解决为里程碑标记的所有阻塞问题,并且可以推迟为里程碑标记的其他问题。

  • 确保已处理为此次发行版标记的弃用、FIXME 和 TODO。

  • 对于主/次要最终版本,请确保已完成发行亮点页面作为可运行的示例,并检查其HTML渲染是否正确。它应该链接到新版本 scikit-learn 的新增功能文件中。

权限

  • 发布经理必须是scikit-learn/scikit-learn 仓库的**维护者**,才能发布到pypi.orgtest.pypi.org(通过手动触发专用的 Github Actions 工作流程)。

  • 发布经理必须是conda-forge/scikit-learn-feedstock 仓库的**维护者**,才能发布到conda-forge。这可以通过编辑第一个发行版拉取请求中的recipe/meta.yaml 文件来更改。

参考步骤#

假设我们正在准备发布1.6.0rc1

第一个 RC 最理想的是作为功能冻结。之后每个候选版本和最终版本都应该只包含较小的文档更改和错误修复。任何主要增强功能或新功能都应排除在外。

  • 在主仓库中直接创建发布分支1.6.X,其中X确实是字母 X,**不是占位符**。1.6 的最终版本和后续错误修复版本的开发也应该在此分支下使用不同的标签进行。

    git fetch upstream main
    git checkout upstream/main
    git checkout -b 1.6.X
    git push --set-upstream upstream 1.6.X
    
  • 创建一个指向1.6.X 分支的 PR。将以下发布清单复制到此 PR 的描述中以跟踪进度。

    * [ ] Update the sklearn dev0 version in main branch
    * [ ] Set the version number in the release branch
    * [ ] Check that the wheels for the release can be built successfully
    * [ ] Merge the PR with `[cd build]` commit message to upload wheels to the staging repo
    * [ ] Upload the wheels and source tarball to https://test.pypi.org
    * [ ] Create tag on the main repo
    * [ ] Confirm bot detected at https://github.com/conda-forge/scikit-learn-feedstock
          and wait for merge
    * [ ] Upload the wheels and source tarball to PyPI
    * [ ] Update news and what's new date in main branch
    * [ ] Backport news and what's new date in release branch
    * [ ] Announce on mailing list and on LinkedIn, Bluesky, Twitter
    
  • 创建一个从main 分支并指向main 分支的 PR,以递增sklearn/__init__.py 中的 dev0 __version__ 变量。这意味着当我们处于候选版本期间,最新的稳定版本比main 分支落后两个版本,而不是一个版本。在此指向main 分支的 PR 中,你还应该在doc/whats_new/ 目录下包含一个新的新增功能文件,以便我们为下一个版本准备更改日志。

  • 在发布分支中,将sklearn/__init__.py 中的版本号__version__ 更改为1.6.0rc1

  • 使用[cd build] 提交标记触发轮子构建器。另请参见轮子构建器的工作流运行

    git commit --allow-empty -m "[cd build] Trigger wheel builder workflow"
    

    注意

    [cd build] 中的缩写 CD 代表持续交付,指的是用于生成发布工件(二进制文件和源代码包)的自动化。这可以看作是 CI 的扩展,CI 代表持续集成。GitHub Actions 上的 CD 工作流也用于自动创建夜间构建并为 scikit-learn 的开发分支发布软件包。另请参见安装夜间构建

  • 一旦 PR 中的所有 CD 作业都成功完成,请使用提交消息中的[cd build] 标记将其合并。此时,结果将上传到暂存区。然后,你应该能够使用PyPI 发布工作流程 的“运行工作流程”表单将生成的工件(.tar.gz.whl 文件)上传到https://test.pypi.org/

    警告

    此 PR 应使用 rebase 模式而不是通常的 squash 模式进行合并,因为我们希望使1.6.X 分支的历史记录与 main 分支的历史记录保持一致,这将有助于未来的错误修复版本。

    此外,如果在合并时,包含`[cd build]`标记的最后一次提交为空,则不会触发持续交付 (CD) 作业。在这种情况下,您可以直接向`1.6.X`分支推送包含该标记的提交来触发它们。

  • 如果以上步骤顺利完成,请**谨慎**创建新的发行版标签。只有在您几乎确定发行版已准备好时才应执行此操作,因为向主仓库添加新标签可能会触发某些自动化流程。

    git tag -a 1.6.0rc1  # in the 1.6.X branch
    git push [email protected]:scikit-learn/scikit-learn.git 1.6.0rc1
    

    警告

    不要使用 GitHub 界面发布发行版来创建标签,因为它会自动向所有关注该仓库的用户发送通知,即使网站尚未更新且轮子尚未上传。

  • 确认机器人已在 conda-forge 代码库 conda-forge/scikit-learn-feedstock 上检测到该标签。如果没有,请提交一个针对`rc`分支的发行版 PR。

  • 再次触发 PyPI 发布工作流,但这次是将工件上传到真正的 https://pypi.ac.cn/。为此,请在“运行工作流”表单中将`testpypi`替换为`pypi`。

    **或者**,您可以本地收集生成的二进制 wheel 包和源代码包,然后将它们全部上传到 PyPI。

    从本地上传工件#

    检出发行版标签并运行以下命令。

    rm -r dist
    python -m pip install -U wheelhouse_uploader twine
    python -m wheelhouse_uploader fetch \
      --version 1.6.0rc1 --local-folder dist scikit-learn \
      https://pypi.anaconda.org/scikit-learn-wheels-staging/simple/scikit-learn/
    

    这些命令将下载累积在 anaconda.org 托管服务的暂存区 中的所有二进制包,并将它们放入您本地的`./dist`文件夹中。检查`./dist`文件夹的内容:它应该包含所有 wheel 包以及源代码包`.tar.gz`。确保该文件夹中没有 scikit-learn 包的开发者版本或旧版本。在上传到 PyPI 之前,您可以先测试上传到`test.pypi.org`。

    twine upload --verbose --repository-url https://test.pypi.org/legacy/ dist/*
    

    然后一次性将所有内容上传到`pypi.org`。

    twine upload dist/*
    

假设我们正在准备`1.6.0`发行版。

  • 从`main`分支创建一个新分支,然后从`1.6.X`开始交互式变基以选择需要回退的提交。

    git rebase -i upstream/1.6.X
    

    这将打开一个交互式变基,其中`git-rebase-todo`包含`main`上的所有最新提交。在此阶段,您必须至少与其他人一起执行此交互式变基(以免遗漏某些内容并避免疑问)。

    • 不要删除行,而是通过将`pick`替换为`drop`来放弃提交。

    • 对于错误修复版本,要选择的提交通常以`FIX`、`CI`和`DOC`为前缀。它们至少应包含为此次发行版设置里程碑的已合并 PR 的所有提交。

    • 对于错误修复版本,要`drop`的提交通常以`FEAT`、`MAINT`、`ENH`和`API`为前缀。不包含它们的原因是为了防止行为发生变化(这应该只发生在主要/次要版本中)。

    • 放弃或挑选提交后,**不要退出**,而是将`git-rebase-todo`消息的内容粘贴到 PR 中。此文件位于`.git/rebase-merge/git-rebase-todo`。

    • 保存并退出以启动交互式变基。如有必要,解决合并冲突。

  • 创建一个指向1.6.X 分支的 PR。将以下发布清单复制到此 PR 的描述中以跟踪进度。

    * [ ] Set the version number in the release branch
    * [ ] Check that the wheels for the release can be built successfully
    * [ ] Merge the PR with `[cd build]` commit message to upload wheels to the staging repo
    * [ ] Upload the wheels and source tarball to https://test.pypi.org
    * [ ] Create tag on the main repo
    * [ ] Confirm bot detected at https://github.com/conda-forge/scikit-learn-feedstock
          and wait for merge
    * [ ] Upload the wheels and source tarball to PyPI
    * [ ] Update news and what's new date in main branch
    * [ ] Backport news and what's new date in release branch
    * [ ] Update symlink for stable in https://github.com/scikit-learn/scikit-learn.github.io
    * [ ] Publish to https://github.com/scikit-learn/scikit-learn/releases
    * [ ] Announce on mailing list and on LinkedIn, Bluesky, Twitter
    * [ ] Update SECURITY.md in main branch
    
  • 在发行版分支中,将`sklearn/__init__.py`中的版本号`__version__`更改为`1.6.0`。

  • 使用[cd build] 提交标记触发轮子构建器。另请参见轮子构建器的工作流运行

    git commit --allow-empty -m "[cd build] Trigger wheel builder workflow"
    

    注意

    [cd build] 中的缩写 CD 代表持续交付,指的是用于生成发布工件(二进制文件和源代码包)的自动化。这可以看作是 CI 的扩展,CI 代表持续集成。GitHub Actions 上的 CD 工作流也用于自动创建夜间构建并为 scikit-learn 的开发分支发布软件包。另请参见安装夜间构建

  • 一旦 PR 中的所有 CD 作业都成功完成,请使用提交消息中的[cd build] 标记将其合并。此时,结果将上传到暂存区。然后,你应该能够使用PyPI 发布工作流程 的“运行工作流程”表单将生成的工件(.tar.gz.whl 文件)上传到https://test.pypi.org/

    警告

    此 PR 应使用 rebase 模式而不是通常的 squash 模式进行合并,因为我们希望使1.6.X 分支的历史记录与 main 分支的历史记录保持一致,这将有助于未来的错误修复版本。

    此外,如果在合并时,包含`[cd build]`标记的最后一次提交为空,则不会触发持续交付 (CD) 作业。在这种情况下,您可以直接向`1.6.X`分支推送包含该标记的提交来触发它们。

  • 如果以上步骤顺利完成,请**谨慎**创建新的发行版标签。只有在您几乎确定发行版已准备好时才应执行此操作,因为向主仓库添加新标签可能会触发某些自动化流程。

    git tag -a 1.6.0  # in the 1.6.X branch
    git push [email protected]:scikit-learn/scikit-learn.git 1.6.0
    

    警告

    不要使用 GitHub 界面发布发行版来创建标签,因为它会自动向所有关注该仓库的用户发送通知,即使网站尚未更新且轮子尚未上传。

  • 确认机器人已在 conda-forge 代码库 conda-forge/scikit-learn-feedstock 上检测到该标签。如果没有,请提交一个针对`main`分支的发行版 PR。

  • 再次触发 PyPI 发布工作流,但这次是将工件上传到真正的 https://pypi.ac.cn/。为此,请在“运行工作流”表单中将`testpypi`替换为`pypi`。

    **或者**,您可以本地收集生成的二进制 wheel 包和源代码包,然后将它们全部上传到 PyPI。

    从本地上传工件#

    检出发行版标签并运行以下命令。

    rm -r dist
    python -m pip install -U wheelhouse_uploader twine
    python -m wheelhouse_uploader fetch \
      --version 1.6.0 --local-folder dist scikit-learn \
      https://pypi.anaconda.org/scikit-learn-wheels-staging/simple/scikit-learn/
    

    这些命令将下载累积在 anaconda.org 托管服务的暂存区 中的所有二进制包,并将它们放入您本地的`./dist`文件夹中。检查`./dist`文件夹的内容:它应该包含所有 wheel 包以及源代码包`.tar.gz`。确保该文件夹中没有 scikit-learn 包的开发者版本或旧版本。在上传到 PyPI 之前,您可以先测试上传到`test.pypi.org`。

    twine upload --verbose --repository-url https://test.pypi.org/legacy/ dist/*
    

    然后一次性将所有内容上传到`pypi.org`。

    twine upload dist/*
    
  • 在`main`分支中,编辑`doc/whats_new`目录中的相应文件,以更新发行日期,链接发行亮点示例,并添加贡献者姓名列表。假设先前主要/次要版本的最后一次发行的标签是`1.5.2`,那么您可以使用以下命令检索贡献者姓名列表

    git shortlog -s 1.5.2.. |
      cut -f2- |
      sort --ignore-case |
      tr "\n" ";" |
      sed "s/;/, /g;s/, $//" |
      fold -s
    

    然后在发行版分支中 cherry-pick 它。

  • 在`main`分支中,编辑`doc/templates/index.html`以更改登录页面中的“新闻”部分以及发行月份。不要忘记删除旧条目(两年前或三个版本之前的条目)并更新“正在进行的开发”条目。然后在发行版分支中 cherry-pick 它。

  • 更新 scikit-learn.github.io (scikit-learn/scikit-learn.github.io) 中的 versionwarning.js 文件中 stable 的符号链接和 latestStable 变量。

    cd /tmp
    git clone --depth 1 --no-checkout [email protected]:scikit-learn/scikit-learn.github.io.git
    cd scikit-learn.github.io
    echo stable > .git/info/sparse-checkout
    git checkout main
    rm stable
    ln -s 1.6 stable
    sed -i "s/latestStable = '.*/latestStable = '1.6';/" versionwarning.js
    git add stable versionwarning.js
    git commit -m "Update stable to point to 1.6"
    git push origin main
    
  • scikit-learn/scikit-learn 发布版本,并在邮件列表和社交网络上发布公告。请记住在发行说明中添加指向变更日志的链接。理想情况下,只有当软件包同时在 PyPI 和 conda-forge 上可用,并且网站已更新后,才执行此步骤。

  • 更新 SECURITY.md 以反映最新的支持版本 1.6.0

假设我们正在准备发布 1.5.3 版本。

  • main 分支创建一个新分支,然后从 1.5.X 开始交互式变基,选择需要回退的提交。

    git rebase -i upstream/1.5.X
    

    这将打开一个交互式变基,其中`git-rebase-todo`包含`main`上的所有最新提交。在此阶段,您必须至少与其他人一起执行此交互式变基(以免遗漏某些内容并避免疑问)。

    • 不要删除行,而是通过将`pick`替换为`drop`来放弃提交。

    • 对于错误修复版本,要选择的提交通常以`FIX`、`CI`和`DOC`为前缀。它们至少应包含为此次发行版设置里程碑的已合并 PR 的所有提交。

    • 对于错误修复版本,要`drop`的提交通常以`FEAT`、`MAINT`、`ENH`和`API`为前缀。不包含它们的原因是为了防止行为发生变化(这应该只发生在主要/次要版本中)。

    • 放弃或挑选提交后,**不要退出**,而是将`git-rebase-todo`消息的内容粘贴到 PR 中。此文件位于`.git/rebase-merge/git-rebase-todo`。

    • 保存并退出以启动交互式变基。如有必要,解决合并冲突。

  • 创建一个指向 1.5.X 分支的 PR。将以下发行清单复制到此 PR 的描述中以跟踪进度。

    * [ ] Set the version number in the release branch
    * [ ] Check that the wheels for the release can be built successfully
    * [ ] Merge the PR with `[cd build]` commit message to upload wheels to the staging repo
    * [ ] Upload the wheels and source tarball to https://test.pypi.org
    * [ ] Create tag on the main repo
    * [ ] Confirm bot detected at https://github.com/conda-forge/scikit-learn-feedstock
          and wait for merge
    * [ ] Upload the wheels and source tarball to PyPI
    * [ ] Update news and what's new date in main branch
    * [ ] Backport news and what's new date in release branch
    * [ ] Publish to https://github.com/scikit-learn/scikit-learn/releases
    * [ ] Announce on mailing list and on LinkedIn, Bluesky, Twitter
    * [ ] Update SECURITY.md in main branch
    
  • 在发布分支中,将 sklearn/__init__.py 文件中的版本号 __version__ 更改为 1.5.3

  • 使用[cd build] 提交标记触发轮子构建器。另请参见轮子构建器的工作流运行

    git commit --allow-empty -m "[cd build] Trigger wheel builder workflow"
    

    注意

    [cd build] 中的缩写 CD 代表持续交付,指的是用于生成发布工件(二进制文件和源代码包)的自动化。这可以看作是 CI 的扩展,CI 代表持续集成。GitHub Actions 上的 CD 工作流也用于自动创建夜间构建并为 scikit-learn 的开发分支发布软件包。另请参见安装夜间构建

  • 一旦 PR 中的所有 CD 作业都成功完成,请使用提交消息中的[cd build] 标记将其合并。此时,结果将上传到暂存区。然后,你应该能够使用PyPI 发布工作流程 的“运行工作流程”表单将生成的工件(.tar.gz.whl 文件)上传到https://test.pypi.org/

    警告

    此 PR 应该使用变基模式而不是通常的 squash 模式进行合并,因为我们希望保持 1.5.X 分支的历史记录与主分支的历史记录接近,这将有助于未来的错误修复版本。

    此外,如果合并时,包含 [cd build] 标记的最后一个提交为空,则不会触发 CD 作业。在这种情况下,您可以直接将带有标记的提交推送到 1.5.X 分支以触发它们。

  • 如果以上步骤顺利完成,请**谨慎**创建新的发行版标签。只有在您几乎确定发行版已准备好时才应执行此操作,因为向主仓库添加新标签可能会触发某些自动化流程。

    git tag -a 1.5.3  # in the 1.5.X branch
    git push [email protected]:scikit-learn/scikit-learn.git 1.5.3
    

    警告

    不要使用 GitHub 界面发布发行版来创建标签,因为它会自动向所有关注该仓库的用户发送通知,即使网站尚未更新且轮子尚未上传。

  • 确认机器人已在 conda-forge 代码库 conda-forge/scikit-learn-feedstock 上检测到该标签。如果没有,请提交一个针对`main`分支的发行版 PR。

  • 再次触发 PyPI 发布工作流,但这次是将工件上传到真正的 https://pypi.ac.cn/。为此,请在“运行工作流”表单中将`testpypi`替换为`pypi`。

    **或者**,您可以本地收集生成的二进制 wheel 包和源代码包,然后将它们全部上传到 PyPI。

    从本地上传工件#

    检出发行版标签并运行以下命令。

    rm -r dist
    python -m pip install -U wheelhouse_uploader twine
    python -m wheelhouse_uploader fetch \
      --version 1.5.3 --local-folder dist scikit-learn \
      https://pypi.anaconda.org/scikit-learn-wheels-staging/simple/scikit-learn/
    

    这些命令将下载累积在 anaconda.org 托管服务的暂存区 中的所有二进制包,并将它们放入您本地的`./dist`文件夹中。检查`./dist`文件夹的内容:它应该包含所有 wheel 包以及源代码包`.tar.gz`。确保该文件夹中没有 scikit-learn 包的开发者版本或旧版本。在上传到 PyPI 之前,您可以先测试上传到`test.pypi.org`。

    twine upload --verbose --repository-url https://test.pypi.org/legacy/ dist/*
    

    然后一次性将所有内容上传到`pypi.org`。

    twine upload dist/*
    
  • main 分支中,编辑 doc/whats_new 目录中的相应文件,以更新发布日期并添加贡献者姓名列表。假设先前主/次要版本的最后一个版本的标签是 1.6.0,则可以使用以下命令检索贡献者姓名列表

    git shortlog -s 1.6.0.. |
      cut -f2- |
      sort --ignore-case |
      tr "\n" ";" |
      sed "s/;/, /g;s/, $//" |
      fold -s
    

    然后在发行版分支中 cherry-pick 它。

  • main 分支中,编辑 doc/templates/index.html 以更改登录页面的“新闻”部分以及发布月份。然后将其 cherry-pick 到发布分支。

  • scikit-learn/scikit-learn 发布版本,并在邮件列表和社交网络上发布公告。请记住在发行说明中添加指向变更日志的链接。理想情况下,只有当软件包同时在 PyPI 和 conda-forge 上可用,并且网站已更新后,才执行此步骤。

  • 更新 SECURITY.md 以反映最新的支持版本 1.5.3

更新作者列表#

本节介绍如何更新 scikit-learn 背后的团队。首先在 GitHub 上创建一个 经典令牌,并授予 read:org 权限。然后运行以下脚本,并在提示时输入令牌

cd build_tools
make authors  # Enter the token when prompted

合并拉取请求#

当 PR 在 GitHub 上合并时,各个提交会被压缩。合并之前

  • 如有必要,可以编辑生成的提交标题。请注意,这将默认重命名 PR 标题。

  • 包含所有提交标题的详细说明可以编辑或删除。

  • 对于有多个代码贡献者的 PR,必须注意保留 Co-authored-by: name <[email protected]> 标签在详细说明中。这将标记 PR 为具有 多个共同作者。代码贡献是否足够重要以值得共同署名,由维护者自行决定,与“新增功能”条目相同。

scikit-learn.org 网站#

scikit-learn 网站 (https://scikit-learn.cn) 托管在 GitHub 上,但很少通过推送到 scikit-learn/scikit-learn.github.io 存储库来手动更新。大多数更新可以通过推送到 main(对于 /dev)或发布分支 A.B.X 来完成,Circle CI 将自动构建并上传文档。

实验性功能#

sklearn.experimental 模块在 0.21 版本中引入,包含实验性功能和估计器,这些功能和估计器可能会在不经过弃用周期的前提下发生更改。

要创建实验性模块,请参考 enable_halving_search_cv.pyenable_iterative_imputer.py 的内容。

注意

这些是永久链接,例如在 0.24 版本中,这些估计器仍然是实验性的。它们在阅读时可能已经稳定,因此使用了永久链接。有关从实验性过渡到稳定的说明,请参见下文。

请注意,公共导入路径必须指向公共子包(例如 sklearn/ensemblesklearn/impute),而不仅仅是 .py 模块。此外,导入的(私有)实验性功能必须位于公共子包的子模块/子包中,例如 sklearn/ensemble/_hist_gradient_boosting/sklearn/impute/_iterative.py。这是为了确保在将来功能不再是实验性功能时,pickle 仍然可以工作。

为了避免类型检查器(例如 mypy)错误,应在父模块中直接导入实验性估计器,并受 if typing.TYPE_CHECKING 检查保护。有关示例,请参见 sklearn/ensemble/__init__.pysklearn/impute/__init__.py。还要编写遵循 test_enable_hist_gradient_boosting.py 中的测试的基本测试。

确保您编写的每个面向用户的代码都明确提到该功能是实验性的,并添加 # noqa 注释以避免与 PEP8 相关的警告

# To use this experimental feature, we need to explicitly ask for it
from sklearn.experimental import enable_iterative_imputer  # noqa
from sklearn.impute import IterativeImputer

为了使文档能够正确渲染,请在doc/conf.py文件中导入enable_my_experimental_feature,否则sphinx将无法检测并导入相应的模块。请注意,使用from sklearn.experimental import ***无效**。

注意

一些实验性的类和函数可能未包含在sklearn.experimental模块中,例如sklearn.datasets.fetch_openml

一旦该特性稳定,请移除scikit-learn代码库中所有enable_my_experimental_feature的出现,并将enable_my_experimental_feature改为仅发出警告的无操作函数,如enable_hist_gradient_boosting.py所示。该文件应永久保留,因为我们不想破坏用户的代码;我们只是鼓励他们通过警告移除该导入。同时,请记住相应地更新测试,参见test_enable_hist_gradient_boosting.py