自作のライブラリをリリースするときに、ローカルでビルドして、TestPyPIにアップロードして確認して、PyPIにアップロードして、最後にタグ切ってリリースして・・・
面倒なのでGitHub Actionsでデプロイできるようにしました。
この記事で目指すこと
リモートにタグをpushした際に、自動でPyPIにパッケージをアップロードし、GitHubにリリースを作成する。
ローカルからtagをpushすると、、、
git tag vX.X.X
git push origin vX.X.X
以下順番で自動的にデプロイされる
- testPyPIへのアップロード
- PyPIへのアップロード
- GitHub上にリリースを追加しソースコードを配布
下記画像のようなワークフローを作成します。
手順
準備
注意
パッケージングツールの設定ファイルとして setup.py ではなく、pyproject.toml を使用します。PEP-518により、モダンなPythonプロジェクトではpyproject.tomlの使用が推奨されています。
Pythonのパッケージを用意してPyPIとTestPyPIのプロジェクトとしてアップロードします。
すでに自作のライブラリがPyPI上にある場合は飛ばしてください。
下記のチュートリアルに従って、サンプルパッケージをTestPyPIとPyPIにアップロードします。
https://packaging.python.org/ja/latest/tutorials/packaging-projects/#creating-a-license
GitHub Actionsでワークフローファイルの作成
リポジトリ> Actions> set up a workflow yourself> 任意の名前でyamlファイル(今回はmain.yaml)を作成しcommit。空ファイルでOKです。
PyPIでPublishingの設定
従来、GitHub ActionsからPyPIにアップロードをするためにはPyPIでAPIトークンを作成し、GitHub側でそのトークンをSecretとして保持する必要がありました。
しかしPublishingを使用することで、事前に設定してある特定のサービス(および特定のユーザー、リポジトリなど)との接続の際に、一時的なトークンを発行、認証までを自動で行うことができます!
設定の簡単ですし、トークンの有効期限が短いのでセキュリティ的にもPublishingを使用する方が良さそうです。
PyPIのプロジェクトページからPublishing> Add a new publisherを選択します。
https://pypi.org/manage/project/[プロジェクト名]/settings/publishing/
以下画像のように記入し、Addします。
TestPyPIを開き、同じようにPublisherを作成します。
Environment nameはPyPIとは別のものにします。
GitHub Actionsでワークフローの設定
先ほど作成したyamlにワークフローを書いていきます。
1. タグがpushされたときにワークフローを開始する
name: Publish Python 🐍 distribution 📦 to PyPI and TestPyPI
on:
push:
tags:
- 'v*.*.*'
2. ビルド
ビルドするためにはpyproject.tomlがリポジトリ上に存在する必要がありますので.gitignoreに含めないでください。
jobs:
build:
name: Build distribution 📦
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4 # コードを取得
- name: Set up Python
uses: actions/setup-python@v5 # Python環境のセットアップ
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 # ビルド成果物をpython-package-distributionsという名前でdistディレクトリに一時的に保存
uses: actions/upload-artifact@v4
with:
name: python-package-distributions
path: dist/
3. TestPyPIへの公開
publish-to-testpypi:
name: Publish Python 🐍 distribution 📦 to TestPyPI
needs:
- build # ビルドジョブが完了した場合ジョブを開始する
runs-on: ubuntu-latest
environment:
name: testpypi # Publisherに設定したenvironment nameを入力
url: https://test.pypi.org/p/example-package-hanaosan0318 # プロジェクトURL
permissions:
id-token: write # Publishingの権限を付与
steps:
- name: Download all the dists # 先ほど保存したビルド成果物をダウンロード
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/
- name: Publish distribution 📦 to TestPyPI # TestPyPIへ公開
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/
4. PyPIへの公開
publish-to-pypi:
name: >-
Publish Python 🐍 distribution 📦 to PyPI
needs:
- publish-to-testpypi # TestPyPIへの公開が完了した場合ジョブを開始する
runs-on: ubuntu-latest
environment:
name: pypi # Publisherに設定したenvironment nameを入力
url: https://pypi.org/p/example-package-hanaosan0318 # プロジェクトURL
permissions:
id-token: write
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
5. リリースの作成
github-release:
name: >-
Create GitHub Release with source code
needs:
- publish-to-pypi # PyPIへの公開が完了した場合ジョブを開始
runs-on: ubuntu-latest
permissions:
contents: write # GitHubリリースを作成するための権限
steps:
- name: Checkout code
uses: actions/checkout@v4 # コードを取得
- name: Create GitHub Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # ワークフローが実行されるたびに自動的に生成される一時的なトークン
run: >-
gh release create
'${{ github.ref_name }}'
--repo '${{ github.repository }}'
--notes "Release for version ${{ github.ref_name }}"
これでワークフローを定義することができました!
yamlファイルの全体は以下リンクから見られます。
デプロイしてみる
pyproject.tomlのversionを今回リリースバージョンに修正してpushしておきます。
[project]
name = "example_package_hanaosan0318"
version = "2.0.3" # リリースバージョンに変更
authors = [
{ name="Example Author", email="author@example.com" },
]
タグを作成しpushします。
git tag v2.0.3
git push origin v2.0.3
PyPIとTestPyPIにパッケージがアップロードされています。
またリリースが作成され、ソースコードがzipとtar.gzで配布されていることが確認できるはずです。
これでリモートにタグをpushした際に、自動でPyPIにパッケージをアップロードし、GitHubにリリースを作成することができました。