Skip to main content
ドキュメントへの更新が頻繁に発行されており、このページの翻訳はまだ行われている場合があります。 最新の情報については、「英語のドキュメント」を参照してください。

Python のビルドとテスト

Pythonプロジェクトのビルドとテストのための継続的インテグレーション(CI)ワークフローを作成できます。

はじめに

このガイドは、Pythonパッケージのビルド、テスト、公開の方法を紹介します。

GitHub ホスト ランナーには、Python と PyPy を含む、ソフトウェアがプレインストールされたツール キャッシュがあります。 自分では何もインストールする必要がありません! 最新のソフトウェアと、Python および PyPy のプレインストールされたバージョンの完全なリストについては、「GitHub ホステッド ランナーの概要」を参照してください。

前提条件

YAMLとGitHub Actionsの構文に馴染んでいる必要があります。 詳しくは、「GitHub Actions について」を参照してください。

Python、PyPy、pipの基本的な理解をしておくことをおすすめします。 詳細については、次を参照してください。

Python スターター ワークフローの使用

GitHub では、ほとんどの Python プロジェクトで使える Python スターター ワークフローが提供されています。 このガイドには、スターター ワークフローのカスタマイズに使用できる例が含まれます。 詳細については、「Python スターター ワークフロー」を参照してください。

すぐに作業を開始するには、リポジトリの .github/workflows ディレクトリにスターター ワークフローを追加します。

YAML
name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]

    steps:
      - uses: actions/checkout@v3
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install ruff pytest
          if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
      - name: Lint with ruff
        run: |
          # stop the build if there are Python syntax errors or undefined names
          ruff --format=github --select=E9,F63,F7,F82 --target-version=py37 .
          # default set of ruff rules with GitHub Annotations
          ruff --format=github --target-version=py37 .
      - name: Test with pytest
        run: |
          pytest

Pythonのバージョンの指定

GitHub ホスト ランナー上で Python または PyPy のプレインストールされたバージョンを使うには、setup-python アクションを使用します。 このアクションでは各ランナーのツール キャッシュから指定されたバージョンの Python または PyPy を見つけ、必要なバイナリを PATH に追加します。これは、残りのジョブで永続化されます。 特定のバージョンの Python がツール キャッシュにプレインストールされていない場合、setup-python アクションでは python-versions リポジトリから適切なバージョンをダウンロードして設定します。

setup-python の使用は、GitHub Actions で Python を使うための推奨される方法です。これは、そうすることでさまざまなランナーやさまざまなバージョンの Python で一貫した動作が保証されるためです。 セルフホスト ランナーを使用している場合は、Python をインストールして PATH に追加する必要があります。 詳細については、「setup-python アクション」を参照してください。

以下の表は、各GitHubホストランナー内でのツールキャッシュの場所です。

UbuntuMacWindows
ツール キャッシュ ディレクトリ/opt/hostedtoolcache/*/Users/runner/hostedtoolcache/*C:\hostedtoolcache\windows\*
Python ツール キャッシュ/opt/hostedtoolcache/Python/*/Users/runner/hostedtoolcache/Python/*C:\hostedtoolcache\windows\Python\*
PyPy ツール キャッシュ/opt/hostedtoolcache/PyPy/*/Users/runner/hostedtoolcache/PyPy/*C:\hostedtoolcache\windows\PyPy\*

セルフホスト ランナーを使用している場合は、setup-python アクションを使って依存関係を管理するようにランナーを構成できます。 詳細については、setup-python README のセルフホスト ランナーでの setup-python の使用に関するページを参照してください。

GitHubは、セマンティックバージョン構文をサポートしています。 詳細については、「セマンティック バージョニングの使用」および「セマンティック バージョニングの仕様」を参照してください。

Pythonの複数バージョンの利用

YAML
name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      # You can use PyPy versions in python-version.
      # For example, pypy2.7 and pypy3.9
      matrix:
        python-version: ["2.7", "3.7", "3.8", "3.9", "3.10", "3.11"]

    steps:
      - uses: actions/checkout@v3
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python-version }}
      # You can test your matrix by printing the current Python version
      - name: Display Python version
        run: python -c "import sys; print(sys.version)"

特定のバージョンのPythonの利用

特定のバージョンの Python を設定することができます。 たとえば、3.10 です。 あるいは、最新のマイナーリリースを取得するためにセマンティックバージョン構文を使うこともできます。 以下の例では、Python 3の最新のマイナーリリースを使います。

YAML
name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3
      - name: Set up Python 3.x
        uses: actions/setup-python@v4
        with:
          # Semantic version range syntax or exact version of a Python version
          python-version: '3.x'
          # Optional - x64 or x86 architecture, defaults to x64
          architecture: 'x64'
      # You can test your matrix by printing the current Python version
      - name: Display Python version
        run: python -c "import sys; print(sys.version)"

バージョンの除外

使用できない Python のバージョンを指定すると、setup-python##[error]Version 3.6 with arch x64 not found などのエラーで失敗します。 このエラーメッセージには、利用できるバージョンが含まれます。

実行したくない Python の構成がある場合は、ワークフローで exclude キーワードを使用することもできます。 詳しくは、「GitHub Actions のワークフロー構文」を参照してください。

YAML
name: Python package

on: [push]

jobs:
  build:

    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", pypy2.7, pypy3.9]
        exclude:
          - os: macos-latest
            python-version: "3.7"
          - os: windows-latest
            python-version: "3.7"

デフォルトバージョンのPythonの利用

依存関係を明示的にしやすくなるので、ワークフローで使用する Python のバージョンの構成には setup-python を使うことをお勧めします。 setup-python を使わない場合は、python の呼び出し時にいずれかのシェルで PATH に設定された既定のバージョンの Python が使用されます。 デフォルトバージョンのPythonは、GitHubホストランナーによって様々なので、予想外の変更が生じたり、期待しているよりも古いバージョンが使われたりするかもしれません。

GitHubホストランナー説明
UbuntuUbuntu ランナーでは、/usr/bin/python および /usr/bin/python3 の下に複数のバージョンのシステム Python がインストールされています。 GitHubがツールキャッシュにインストールしエチルバージョンに加えて、UbuntuにパッケージングされているバージョンのPythonがあります。
WindowsツールキャッシュにあるPythonのバージョンを除けば、WindowsにはシステムPythonに相当するバージョンは含まれていません。 他のランナーとの一貫した動作を保ち、setup-python アクションなしですぐに Python が使えるようにするために、GitHub ではツール キャッシュからいくつかのバージョンを PATH に追加します。
macOSmacOSランナーには、ツールキャッシュ内のバージョンに加えて、複数バージョンのシステムPythonがインストールされています。 システム Python バージョンは /usr/local/Cellar/python/* ディレクトリにあります。

依存関係のインストール

GitHubホストランナーには、パッケージマネージャーのpipがインストールされています。 コードのビルドとテストに先立って、pipを使ってパッケージレジストリのPyPIから依存関係をインストールできます。 たとえば、以下の YAML では、pip パッケージ インストーラーと、setuptools および wheel パッケージがインストールまたはアップグレードされます。

ワークフローの速度を上げるために、依存関係をキャッシュすることもできます。 詳細については、「依存関係をキャッシュしてワークフローのスピードを上げる」を参照してください。

YAML
steps:
- uses: actions/checkout@v3
- name: Set up Python
  uses: actions/setup-python@v4
  with:
    python-version: '3.x'
- name: Install dependencies
  run: python -m pip install --upgrade pip setuptools wheel

Requirementsファイル

pip の更新後の一般的な次の手順は、requirements.txt から依存関係をインストールすることです。 詳しくは、「pip」をご覧ください。

YAML
steps:
- uses: actions/checkout@v3
- name: Set up Python
  uses: actions/setup-python@v4
  with:
    python-version: '3.x'
- name: Install dependencies
  run: |
    python -m pip install --upgrade pip
    pip install -r requirements.txt

依存関係のキャッシング

setup-pythonアクションを使用して依存関係をキャッシュおよび復元できます。

次の例では pip の依存関係をキャッシュします。

YAML
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
  with:
    python-version: '3.11'
    cache: 'pip'
- run: pip install -r requirements.txt
- run: pip test

既定で、setup-python アクションでは、リポジトリ全体で依存関係ファイル (pip の場合は requirements.txt、pipenv の場合は Pipfile.lock、poetry の場合は poetry.lock) を検索します。 詳細については、setup-python README のパッケージの依存関係のキャッシュに関するページを参照してください。

カスタム要件がある場合、またはキャッシュに対してより細かい制御が必要な場合は、cache アクションを使用できます。 ランナーのオペレーティングシステムによって、pipは依存関係を様々な場所にキャッシュします。 キャッシュする必要があるパスは、使用するオペレーティング システムによって、上記の Ubuntu の例とは異なる場合があります。 詳細については、cache アクション リポジトリの Python キャッシュの例に関するページを参照してください。

コードのテスト

ローカルで使うのと同じコマンドを、コードのビルドとテストに使えます。

pytest及びpytest-covでのテスト

この例では、pytest および pytest-cov をインストールまたはアップグレードします。 そしてテストが実行され、JUnit形式で出力が行われ、一方でコードカバレッジの結果がCoberturaに出力されます。 詳細については、JUnitCobertura に関するページを参照してください。

YAML
steps:
- uses: actions/checkout@v3
- name: Set up Python
  uses: actions/setup-python@v4
  with:
    python-version: '3.x'
- name: Install dependencies
  run: |
    python -m pip install --upgrade pip
    pip install -r requirements.txt
- name: Test with pytest
  run: |
    pip install pytest pytest-cov
    pytest tests.py --doctest-modules --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html

コードの lint に Ruff を使う

以下の例では、ruff をインストールまたはアップグレードし、それを使ってすべてのファイルを lint します。 詳しくは、「Ruff」を参照してください。

YAML
steps:
- uses: actions/checkout@v3
- name: Set up Python
  uses: actions/setup-python@v4
  with:
    python-version: '3.x'
- name: Install dependencies
  run: |
    python -m pip install --upgrade pip
    pip install -r requirements.txt
- name: Lint with Ruff
  run: |
    pip install ruff
    ruff --format=github --target-version=py37 .
  continue-on-error: true

リンティング ステップには continue-on-error: true が設定されています。 これにより、リンティング ステップが成功しなかった場合にワークフローが失敗しなくなります。 すべてのリンティング エラーに対処したら、ワークフローで新しい Issue を見つけられるようにこのオプションを削除できます。

toxでのテストの実行

GitHub Actionsでは、toxでテストを実行し、その処理を複数のジョブに分散できます。 tox を起動する際には、特定のバージョンを指定するのではなく、-e py オプションを使って PATH の Python のバージョンを選択する必要があります。 詳細については、tox に関するページを参照してください。

YAML
name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        python: ["3.9", "3.10", "3.11"]

    steps:
      - uses: actions/checkout@v3
      - name: Setup Python
        uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python }}
      - name: Install tox and any other packages
        run: pip install tox
      - name: Run tox
        # Run tox using the version of Python in `PATH`
        run: tox -e py

成果物としてのワークフローのデータのパッケージ化

ワークフローの完了後に、成果物をアップロードして見ることができます。 たとえば、ログファイル、コアダンプ、テスト結果、スクリーンショットを保存する必要があるかもしれません。 詳しくは、「ワークフロー データを成果物として保存する」を参照してください。

以下の例は、upload-artifact アクションを使って pytest の実行によるテスト結果をアーカイブする方法を示しています。 詳細については、「upload-artifact アクション」を参照してください。

YAML
name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]

    steps:
      - uses: actions/checkout@v3
      - name: Setup Python # Set Python version
        uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python-version }}
      # Install pip and pytest
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install pytest
      - name: Test with pytest
        run: pytest tests.py --doctest-modules --junitxml=junit/test-results-${{ matrix.python-version }}.xml
      - name: Upload pytest test results
        uses: actions/upload-artifact@v3
        with:
          name: pytest-results-${{ matrix.python-version }}
          path: junit/test-results-${{ matrix.python-version }}.xml
        # Use always() to always run this step to publish test results when there are test failures
        if: ${{ always() }}

パッケージレジストリへの公開

CI テストにパスしたら、Python パッケージをパッケージ レジストリに公開するようにワークフローを構成できます。 このセクションでは、GitHub Actions を使用して、リリースを公開するたびにパッケージを PyPI にアップロードする方法について説明します。

この例では、2 つの PyPI API トークンを作成する必要があります。 パッケージを公開するのに必要なトークンまたは資格情報を格納するために、シークレットを使用することができます。 詳しくは、「暗号化されたシークレット」を参照してください。

YAML
# このワークフローはGitHubによって認定されていないアクションを使用します。
# それらはサードパーティによって提供され、
# 別個の利用規約、プライバシーポリシー、
# ドキュメントを参照してください。

# GitHub では、コミット SHA にアクションをピン留めすることが推奨されます。
# 新しいバージョンを取得するには、SHA を更新する必要があります。
# タグまたはブランチを参照することもできますが、アクションは警告なしに変更される可能性があります。

name: Upload Python Package

on:
  release:
    types: [published]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.x'
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install build
      - name: Build package
        run: python -m build
      - name: Publish package
        uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
        with:
          user: __token__
          password: ${{ secrets.PYPI_API_TOKEN }}

スターター ワークフローの詳細については、「python-publish」を参照してください。