使用 GitHub Actions CI/CD 工作流发布包分发版本¶
GitHub Actions CI/CD 允许您在 GitHub 平台上发生事件时运行一系列命令。一种流行的选择是创建一个由 push 事件触发的工作流。本指南将向您展示如何在推送带有标签的提交时发布 Python 发行版。它将使用 pypa/gh-action-pypi-publish GitHub Action 进行发布。它还使用 GitHub 的 upload-artifact 和 download-artifact 操作来临时存储和下载源包。
注意
本指南假设您已经有一个项目,并且您知道如何为其构建发行版,并且它位于 GitHub 上。本指南还避免了构建特定于平台项目的细节。如果您有二进制组件,请查看 cibuildwheel 的 GitHub Action 示例。
配置可信发布¶
本指南依赖 PyPI 的 可信发布 实现来连接 GitHub Actions CI/CD。出于安全原因,建议这样做,因为生成的令牌是为您的每个项目单独创建的,并且会自动过期。否则,您需要为 PyPI 和 TestPyPI 生成一个 API 令牌。如果是发布到像 devpi 这样的第三方索引,您可能需要提供用户名/密码组合。
由于本指南将演示同时上传到 PyPI 和 TestPyPI,因此我们需要配置两个可信发布者。以下步骤将引导您为新的 PyPI 项目 创建“待定”发布者。但是,如果您是所有者,也可以将 可信发布 添加到任何现有项目。
注意
如果您遵循了本指南的早期版本,您已经为直接访问 PyPI 和 TestPyPI 创建了 secret PYPI_API_TOKEN 和 TEST_PYPI_API_TOKEN。这些现在已过时,如果您要用新设置替换旧设置,则应将它们从 GitHub 仓库中删除,并在 PyPI 和 TestPyPI 账户设置中撤销它们。
我们开始吧!🚀
填写您希望发布新 PyPI 项目 的名称(
setup.cfg或pyproject.toml中的name值)、GitHub 仓库所有者的名称(组织或用户)、仓库名称,以及.github/文件夹下的发布工作流文件的名称,请参阅 创建工作流定义。最后,添加我们将在您的仓库下设置的 GitHub 环境名称(pypi)。注册可信发布者。现在,前往 https://test.pypi.org/manage/account/publishing/ 并重复第二步,但这次,输入
testpypi作为 GitHub 环境的名称。您的“待定”发布者现在已准备好首次使用,一旦您首次使用它们,它们将自动创建您的项目。
注意
如果您没有 TestPyPI 账户,您需要创建一个。它与常规 PyPI 账户不同。
注意
出于安全原因,您必须要求对
pypi环境的每次运行都进行手动批准。
创建工作流定义¶
GitHub CI/CD 工作流在存储在仓库的 .github/workflows/ 目录中的 YAML 文件中声明。
让我们创建一个 .github/workflows/publish-to-test-pypi.yml 文件。
以一个有意义的名称开始,并定义应使 GitHub 运行此工作流的事件
name: Publish Python 🐍 distribution 📦 to PyPI and TestPyPI
on: push
检出项目并构建发行版¶
我们将不得不定义两个作业分别发布到 PyPI 和 TestPyPI,以及一个额外的作业来构建发行包。
首先,我们将定义用于构建项目分发包并将其存储以备后用的作业
jobs:
build:
name: Build distribution 📦
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.x"
这将把您的仓库下载到 CI 运行器中,然后安装并激活最新的可用 Python 3 版本。
现在我们可以从源代码构建发行版并存储它们。在这个例子中,我们将使用 build 包。所以将其添加到步骤列表中
- name: Install pypa/build
run: >-
python3 -m
pip install
build
--user
- name: Build a binary wheel and a source tarball
run: python3 -m build
- name: Store the distribution packages
uses: actions/upload-artifact@v4
with:
name: python-package-distributions
path: dist/
定义工作流作业环境¶
现在,让我们为将发布到 PyPI 的作业添加初始设置。这是一个将执行我们稍后定义的命令的过程。在本指南中,我们将使用 GitHub Actions 提供的最新稳定的 Ubuntu LTS 版本。这还为作业定义了一个 GitHub 环境,以便在其上下文中运行,以及一个将在 GitHub UI 中漂亮地显示的 URL。此外,它允许获取 pypi-publish 动作实现无秘密可信发布到 PyPI 所需的 OpenID Connect 令牌。
publish-to-pypi:
name: >-
Publish Python 🐍 distribution 📦 to PyPI
if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes
needs:
- build
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.ac.cn/p/<package-name> # Replace <package-name> with your PyPI project name
permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing
这还将确保 PyPI 发布工作流仅在当前提交带有标签时触发。
将发行版发布到 PyPI¶
最后,在末尾添加以下步骤
steps:
- name: Download all the dists
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/
- name: Publish distribution 📦 to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
此步骤使用 pypa/gh-action-pypi-publish GitHub Action:在 download-artifact action 下载存储的发行包后,它无条件地将 dist/ 文件夹的内容上传到 PyPI。
提示
从 v1.11.0 版本开始,pypa/gh-action-pypi-publish 默认生成并上传 PEP 740 兼容的每个发行版证明。不需要额外的手动签名步骤。
独立工作流发布到 TestPyPI¶
现在,重复这些步骤,并在 jobs 部分下创建另一个用于发布到 TestPyPI 包索引的作业
publish-to-testpypi:
name: Publish Python 🐍 distribution 📦 to TestPyPI
needs:
- build
runs-on: ubuntu-latest
environment:
name: testpypi
url: https://test.pypi.org/p/<package-name>
permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing
steps:
- name: Download all the dists
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/
- name: Publish distribution 📦 to TestPyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/
提示
在 testpypi GitHub 环境中要求手动批准通常是不必要的,因为它旨在在每次提交到主分支时运行,并且通常用于指示健康的发布管道。
完整的 CI/CD 工作流¶
本段展示了遵循上述指南后的完整工作流。
点击此处显示完整的 GitHub Actions CI/CD 工作流定义
name: Publish Python 🐍 distribution 📦 to PyPI and TestPyPI
on: push
jobs:
build:
name: Build distribution 📦
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Install pypa/build
run: >-
python3 -m
pip install
build
--user
- name: Build a binary wheel and a source tarball
run: python3 -m build
- name: Store the distribution packages
uses: actions/upload-artifact@v4
with:
name: python-package-distributions
path: dist/
publish-to-pypi:
name: >-
Publish Python 🐍 distribution 📦 to PyPI
if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes
needs:
- build
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.ac.cn/p/<package-name> # Replace <package-name> with your PyPI project name
permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing
steps:
- name: Download all the dists
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/
- name: Publish distribution 📦 to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
publish-to-testpypi:
name: Publish Python 🐍 distribution 📦 to TestPyPI
needs:
- build
runs-on: ubuntu-latest
environment:
name: testpypi
url: https://test.pypi.org/p/<package-name>
permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing
steps:
- name: Download all the dists
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/
- name: Publish distribution 📦 to TestPyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/
就这些了,各位!¶
现在,每当您将带标签的提交推送到 GitHub 上的 Git 仓库远程端时,此工作流都会将其发布到 PyPI。并且它会将任何推送发布到 TestPyPI,这对于向您的 alpha 用户提供测试版本以及确保您的发布管道保持健康非常有用!
注意
如果您的仓库提交活动频繁,并且每次推送都按所述上传到 TestPyPI,则项目可能会超出 PyPI 项目大小限制。可以增加限制,但更好的解决方案可能是使用像 pypiserver 这样的 PyPI 兼容服务器在 CI 中进行测试。
注意
建议将集成的 GitHub Actions 保持在最新版本,并经常更新它们。