用GitHub Actions自动打包发布Python项目
用 GitHub Actions 自动打包发布 Python 项目
前言
还在手动打包上传 PyPI?GitHub Actions 自动化真香~!
在《Python 代码一键转流程图》一文里,我介绍了我的开源项目 PyFlowchart。过去这段时间里,已经有好几位小伙伴为这个项目提出了建议,或者报告了 Bug 啦。在这几位朋友的帮助下,项目也迭代了几个版本了。之前,这个项目每次版本更新,我都需要做很多写代码意外的麻烦工作:
- 在 GitHub 上 publish 一个 release,
- 手动打包上传 PyPI。
这个过程非常反人类,release 一个版本要做两个工作。更可怕的是,打包上传 PyPI 的工作十分模版化(鄙人拙作《如何用 pip 安装自己写的包》一文介绍了这个过程)。我觉得作为开发者,不应该把时间浪费在这种套路工作上。
于是我想去了过去我写过一篇叫做《还在手动发博客?GitHub Actions自动化真香》的文章,大致介绍了我是如何利用 GitHub Actions 自动更新博客网站的。所以,今回,我尝试用 GitHub Actions 搭建了一套发布新版本时,自动打包上传 PyPI 📦 的工作流程。
现在,发布新的版本时,就只需在 GitHub 上新建一个 Release。GitHub Actions 会自动帮我完成构建、打包、上传 PyPI 的工作。
本文就介绍如何利用 GitHub Actions 自动发布 Python 包到 PyPI。
(注:我在 PyFlowchart 项目中使用的实现和下文略有不同,我根据需求做了一些修改,如果你感兴趣,可以看一看我的实现:https://github.com/cdfmlr/pyflowchart/tree/master/.github/workflows)
下文翻译自 PyPA 的文章《Publishing package distribution releases using GitHub Actions CI/CD workflows》
GitHub Actions CI/CD 允许在 GitHub 平台上特定的事件发生时自动运行一系列的命令。用这个就可以做设置一个响应 push 事件的工作流程。本文将展示如何当有 git push 时发布一个新的 Python 包发行版(到 PyPI)。我们将使用到 pypa/gh-action-pypi-publish GitHub Action。
注意:这个教程假设你已经有在 GitHub 上有一个 Python 项目,并且你知道如何构建包,并把它发布到 PyPI。
在 GitHub 上保存 token
在本文中,我们会把项目上传到 PyPI 和 TestPyPI。所以需要生成两份独立的 token,并把它们保存到 GitHub 的仓库设置中。
我们开始吧!🚀
- 访问 https://pypi.org/manage/account/#api-tokens ,创建一个新的 API token。 如果你已经在 PyPI 里发布过你的项目了,那么你应该把 token 的范围(token scope) 限定为只能操作这个项目的。你可以把新 token 命名为
GitHub Actions CI/CD —project-org/project-repo
之类的,方便辨识。生成 token 后不要关闭浏览器页面—— token 只会显示一次。 - 在另一个浏览器选项卡或窗口中,打开 GitHub 上你的项目页面,点击
Settings
选项卡,然后点击左侧边栏里的 Secrets 。 - 创建一个新的 sercret,命令为
PYPI_API_TOKEN
,然后复制粘贴第一步生成的 token。 - 访问 https://test.pypi.org/manage/account/#api-tokens ,重复之前的步骤,把 TestPyPI 的 token 保存成
TEST_PYPI_API_TOKEN
。
注意:如果你还没有 TestPyPI 账号,你应该注册一个。TestPyPI 和 PyPI 的账号不共通哦。
创建 workflow
GitHub CI/CD 工作流程(workflow)是用 YAML 格式的文件储存到仓库的 .github/workflows/
目录里的。
我们创建一个 .github/workflows/publish-to-test-pypi.yml
文件。
我们将从一个有意义的名称开始,然后定义触发 GitHub 运行此工作流程的事件:
1 | name: Publish Python 🐍 distributions 📦 to PyPI and TestPyPI |
定义工作流程的工作环境
现在,我们来为工作(job)添加初始设置。这个过程将执行我们稍后定义的命令。在这里,我们将使用Ubuntu 18.04:
1 | jobs: |
签出项目,构建发行版
然后,在该 build-n-publish
部分下添加以下内容:
1 | steps: |
这些操作会把我们的项目源码下载到 CI 运行容器里,然后安装并激活 Python 3.7 环境。
现在,我们就可以从源码构建 dist 了。在此示例中,我们将使用build
包,所以假设项目里已正确设置 pyproject.toml
(请参见 PEP 517 / PEP 518)。
(注:emmm,其实这里不写 pyproject.toml
问题也不大)
提示:你可以使用任何其他方法来构建发行版,只要将准备好上传的包保存到 dist/
文件夹中即可。
将下面的代码加到 steps
里:
1 | - name: Install pypa/build |
发布到 PyPI 和 TestPyPI
最后,添加如下代码:
1 | - name: Publish distribution 📦 to Test PyPI |
这两个 step 调用了 pypa/gh-action-pypi-publish GitHub Action:
第一个步骤无条件地将 dist/
文件夹的内容上传到TestPyPI。第二个步骤将其内容上传到 PyPI,这一步只会对被打了标签(git tag)的提交执行。
完事,收工!
现在,每当你将打了标签(tag)的提交 push 到 GitHub 上时,此工作流程都会将其发布到 PyPI。同时,对于任意 push ,它都会将其打包发布到 TestPyPI,这对于提供 alpha 测试版本以及确保发布渠道保持健康非常有用!
1 | by("CDFMLR", "2021-01-17") |