Python Tips: Python のプロジェクトで GitHub Actions を使いたい

GitHub Actions

今回は Python のプロジェクトで GitHub Actions を導入する方法をご紹介します。実際に動くかんたんなサンプルを使って説明します。

追記

  • 2021/07/30: 環境変数 PATH の追加と Poetry インストールの方法を最新のものに変更しました。

GitHub Actions とは

最初に GitHub Actions についてかんたんに説明します。

GitHub Actions とは GitHub 公式のワークフロー自動化ツールです。 2018 年 10 月にパブリックベータ版が公開され、 2019 年 11 月に一般公開されました。 それまで GitHub で CI / CD を行うには外部のサービスを利用する必要がありましたが、 GitHub Actions が導入されたことでコード管理と CI / CD を GitHub 内で一元的に行えるようになりました。

GitHub Actions を利用するには、 リポジトリルート/.github/workflows/ 以下に自動化したい処理を記述した YAML ファイルを置きます。 処理を実行するプラットフォームは Linux / macOS / Windows の中から選べます。

GitHub Actions の特徴のひとつに、 GitHub 公式や他のユーザーが作成したアクションを利用できる点があります。 たとえば、次の内容を設定ファイルに記述すると、 actions/checkoutactions/setup-python というアクションをかんたんに利用することができます。

name: pytest

on:
  push:

jobs:
  pytest:
    name: Run tests with pytest
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Set up Python 3.9
        uses: actions/setup-python@v2
        with:
          python-version: 3.9

汎用度の高いアクションは誰かがオープンソースとして公開してくれていることもあるので、必ずしもすべての手順を自分でゼロから書く必要はありません。 CI / CD の経験があまり無い方やプログラミング初心者の方にも始めやすいかと思います。

Python プロジェクトでの GitHub Actions の使い方

Python プロジェクトでの GitHub Actions の使い方を説明します。

公式のドキュメントを読めば大体のことは書かれているので、そこを読んでスムーズに理解できる方は公式のドキュメントを読むのがいちばんです。 ここでは動くサンプルを使ってさわりの部分だけ説明します。

以下前提として、 GitHub にアカウントを持っていて Python プロジェクトのリポジトリを置いているものとします。

GitHub Actions を使い始める方法は 2 つあります。

  • ブラウザで Actions のページを開く
  • ファイル .github/workflows/xxx.yml を作成してコミットする

ブラウザで Actions のページを開くにはリポジトリの「 Actions 」タブをクリックします。 ファイル .github/workflows/xxx.yml をコミットする場合は、手元のテキストエディタとターミナルをそのまま使います。どちらの形を選んでも最終的にできることは同じです。

以下、テストとスタイルチェックを行うかんたんなサンプルを使って説明します。 次のツールを使用します。

  • poetry: 依存パッケージを管理する
  • pytest: テストを実行する
  • black: コーディングスタイルのチェックを行う

動作確認には以下のバージョンを使用しました( 2021/07/30 更新)。

  • Python 3.9.6
  • Poetry 1.1.7

まずリポジトリを新規に作成して、次の 2 つのファイルをコミットします。

hello.py:

"""関数 `hello()` を提供する"""

def hello(name: str = "world") -> None:
    """`Hello, xxx.` のメッセージを出力する"""
    print(f"Hello, {name}.")

tests/test_hello.py:

from hello import hello

def test_hello_default(capsys):
    hello()
    out, err = capsys.readouterr()
    assert out == "Hello, world.\n"

def test_hello_with_name(capsys):
    hello("サザエ")
    hello("カツオ")
    out, err = capsys.readouterr()
    assert out == "Hello, サザエ.\n" "Hello, カツオ.\n"

次に pytest をインストールします。 私は Python のパッケージには poetry をよく使いますがここは pip でもそれ以外のものでもかまいません。

poetry add --dev pytest

pytest が無事にインストールできたら、 setup.py を作成してからテストを実行します。

setup.py:

from setuptools import setup, find_packages

setup(name="hello-github-actions", version="1.0", packages=find_packages())
poetry run pytest tests/test_hello.py
=================================================== test session starts ====================================================
platform darwin -- Python 3.9.6, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: /Users/hayato/repos/hello-github-actions
collected 2 items                                                                                                          

tests/test_hello.py ..                                                                                               [100%]

==================================================== 2 passed in 0.01s ====================================================

成功することが確認できました。

続いて、このテストを GitHub Actions で実行するように設定ファイルを書きます。

リポジトリのルート以下の .github/workflows/ci.yml にファイルを作成し以下の内容で保存します。

.github/worflows/ci.yml:

name: pytest

on:
  push:
  pull_request:

env:
  POETRY_VERSION: 1.1.7
  POETRY_URL: https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py

jobs:
  pytest:
    name: Run tests with pytest
    # 実行環境として `ubuntu-latest` という名前のものを選ぶ
    runs-on: ubuntu-latest
    # 複数の Python のバージョンでテストするために `strategy.matrix` を設定する
    strategy:
      matrix:
        python-version: [3.8, 3.9]
    steps:
      # リポジトリをチェックアウトする
      # See: https://github.com/actions/checkout
      - name: Checkout
        uses: actions/checkout@v2
      # Python のランタイムをセットアップする
      # バージョンは `strategy.matrix` に並べたものを指定する
      # See: https://github.com/actions/setup-python
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v2
        with:
          python-version: ${{ matrix.python-version }}
      # Poetry そのものをインストールする
      - name: Install Poetry
        run: |
          curl -sSL ${{ env.POETRY_URL }} | \
            python - --version ${{ env.POETRY_VERSION }}
          echo "$HOME/.local/bin" >> $GITHUB_PATH
      # インストールした Poetry を使って必要な Python パッケージをインストールする
      - name: Install Dependencies
        run: poetry install --no-interaction
      # pytest を実行する
      - name: Run Tests
        run: poetry run pytest tests/

メインとなるのは jobs.pytest.steps の部分で、ここに指定されたアクションが上から順に実行されます。

ci.yml というファイル名は必ずこの名前でないといけないわけではありません。 適当にわかりやすい名前を付ければ OK です。

ファイルが作成できたらコミットします。 poetry を使っている場合は pyproject.tomlpoetry.lock を、 pip を使っている場合は requirements.txt も忘れずコミットします。

ここまでのコミットを GitHub にプッシュすると、リポジトリの Actions のページでテスト用のタスクが実行されることが確認できます。

これがうまく行ったら、おまけで black を使ったスタイルチェックも追加してみます。 poetry add をして、先ほどの .github/workflows/ci.yml を編集します。

poetry add --dev black

ファイルの末尾に以下の内容を追加します( black: の行が jobs の下に来るようにします)。インデントがおかしいと正しく動かないので注意してください。

  black:
    name: Check code style with Black
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Set up Python 3.9
        uses: actions/setup-python@v2
        with:
          python-version: 3.9
      - name: Install Poetry
        run: |
          curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py | python -
          echo "$HOME/.local/bin" >> $GITHUB_PATH
      - name: Install Dependencies
        run: poetry install --no-interaction
      - name: Check code style with Black
        run: poetry run black --check --diff .

コードに問題がなければ、このワークフローも GitHub Actions で実行され、結果が success として報告されるはずです。

ということで、かんたんにですが Python プロジェクトでの GitHub Actions の使い方について説明しました。 GitHub Actions について深く知りたい方は公式のドキュメントその他をご確認ください。

今回使ったサンプルを少し整理して GitHub にあげています。 興味のある方は参考にしてみてください:

参考リンク