0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[Django+MySQL+GitHub Actions] Matrixを使って複数バージョンのPythonとUbuntuでPytestを実行しよう

Last updated at Posted at 2023-02-12

前提

今回はMatrixを使用する例としてDjangoとMySQLとPytestを使用します
DjangoとMySQLのサービスコンテナを使ってPytestを実行する方法について
本記事では解説しないので詳細に知りたい方は以下の記事を参照してください

Matrixとは

同じワークフローを複数の

  • 実行環境(Node.jsなど)
  • runnerOS (Ubuntuなど)
  • 言語(Pythonなど)

のバージョンで実行できる仕組みです
Matrixを使うと例えばバージョンをアップデートする際の検証やトラブルシューティングに役立つかと思います
デフォルトでは全てのバージョンを以下のように並列で実行できます

スクリーンショット 2023-02-12 11.54.17.png

また、Matrixを使用する際は一つのJobsが失敗すると他のJobsが実行されないのも特徴です
(ただし、continue-on-errorを追加した場合は除く)

スクリーンショット 2023-02-12 11.55.03.png

Matrixの設定方法

Matrixを設定する際は以下の例のようにstrategyを定義し、その下にmatrixを定義します
matrixの下に任意の変数を定義し、テストしたいバージョンの一覧を配列に入れます

.github/workflows/test.yml
jobs:
  Setup:
    name: Run Test Code
    # 実行したいバッケージ等のバージョンを配列内にstrategyとmatrixに指定
    strategy:
      matrix:
        python-version: [3.10.5, 3.10.6, 3.10.7]
        os: [ubuntu-latest, ubuntu-20.04]

Job内でMatrixで定義したバージョンを適用させたい処理には以下のように記載します
例えばOSのバージョンを適用させたいときは以下のように記載します

${{ matrix.os }}

実際に実行してみよう!

以上を踏まえてMatrixを適用させると以下の例のようになります

ディレクトリ構成

❯ tree 
.
├── .github
│   └── workflows
│       └── test.yml
└── application # Djangoのプロジェクトファイルおよびpyproject.tomlが入ったディレクトリ
    ├── project
    │   └── settings.py
    ├── manage.py
    ├── poetry.lock
    └── pyproject.toml

ワークフロー

.github/workflows/test.yml
name: Run Pytest Using Matrix

# ワークフローのイベントは任意です
# 今回は検証用なので手動でワークフローを実行するようにします
on: workflow_dispatch

env:
  SECRET_KEY: test
  DJANGO_SETTINGS_MODULE: project.settings
  ALLOWED_HOSTS: 127.0.0.1
  DEBUG: "True"
  MYSQL_ROOT_PASSWORD: root
  MYSQL_DATABASE: test-db
  MYSQL_HOST: 127.0.0.1
  MYSQL_PORT: 3306
  MYSQL_USER: test
  MYSQL_PASSWORD: test

jobs:
  Setup:
    name: Run Test Code
    # 実行したいバッケージ等のバージョンを配列内にstrategyとmatrixに指定
    strategy:
      matrix:
        python-version: [3.10.5, 3.10.6, 3.10.7]
        os: [ubuntu-latest, ubuntu-20.04]
    runs-on: ${{ matrix.os }}
    defaults:
      run:
        working-directory: application
    services:
      db:
        image: mysql:8.0
        ports:
          - 3306:3306
        env:
          MYSQL_ROOT_PASSWORD: ${{ env.MYSQL_ROOT_PASSWORD }}
          MYSQL_DATABASE: ${{ env.MYSQL_DATABASE }}
          MYSQL_USER: ${{ env.MYSQL_USER }}
          MYSQL_PASSWORD: ${{ env.MYSQL_PASSWORD }}
        options: >-
          --health-cmd "mysqladmin ping"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    steps:
      - name: Chekcout code
        uses: actions/checkout@v3
      - name: Grant privileges to user
        run: mysql --protocol=tcp -h 127.0.0.1 -P 3306 -u root -p$MYSQL_ROOT_PASSWORD -e "GRANT ALL PRIVILEGES ON *.* TO '$MYSQL_USER'@'%'; FLUSH PRIVILEGES;"
      - name: Install poetry
        run: pipx install poetry
      - name: Use cache dependencies
        uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python-version }}
          cache: 'poetry'
      - name: Install Packages
        run: poetry install
      - name: Run migration
        run: |
          poetry run python manage.py makemigrations
          poetry run python manage.py migrate
      - name: Run Pytest
        run: poetry run pytest -x -n auto --cov --no-cov-on-fail --suppress-no-test-exit-code

Django側の設定

settings.py
import os

SECRET_KEY = os.environ.get("SECRET_KEY")

DEBUG = os.environ.get("DEBUG") == "True"

ALLOWED_HOSTS = os.environ.get("ALLOWED_HOSTS").split(" ")

# データベースの設定を行う
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.mysql",
        "NAME": os.environ.get("MYSQL_DATABASE"),
        "USER": os.environ.get("MYSQL_USER"),
        "PASSWORD": os.environ.get("MYSQL_PASSWORD"),
        "HOST": os.environ.get("MYSQL_HOST", "db"),
        "PORT": os.environ.get("MYSQL_PORT", 3306),
    }
}

前述の通り、各Jobが並列で実行され、成功すると以下のようになります
スクリーンショット 2023-02-12 11.59.39.png

特定のバージョンのみ追加したいとき

例えば

  • Python 3.10.8
  • Ubuntu 18.04

だけ追加で検証したいときはincludeを使用します
2つとも配列に入れてしまうと

  • Python 3.10.8
  • Ubuntu 20.04 と latest

など、実行しなくてもいいバージョンのJobまで実行されてしまいます
そのため、今回みたいなケースではincludeを使用します

.github/workflows/test.yml
    strategy:
      matrix:
        python-version: [3.10.5, 3.10.6, 3.10.7]
        os: [ubuntu-latest, ubuntu-20.04]
        # includeを使って python-version: 3.10.8 と ubuntu-18.04 のみ追加
        include:
          - python-version: 3.10.8
            os: ubuntu-18.04

以下のように

  • Python 3.10.8
  • Ubuntu 18.04

のJobのみ追加されていることが確認できました

スクリーンショット 2023-02-12 12.14.17.png

特定のバージョンのみ除外したいとき

特定のバージョンのみ除外するときはincludeとは逆にexcludeを使用します
今回は

  • Python 3.10.5
  • Ubuntu 20.04

のJobのみ実行しないようにします

.github/workflows/test.yml
    strategy:
      matrix:
        python-version: [3.10.5, 3.10.6, 3.10.7]
        os: [ubuntu-latest, ubuntu-20.04]
        # includeを使って python-version: 3.10.5 と ubuntu-20.04 のみ除外
        exclude:
          - python-version: 3.10.5
            os: ubuntu-20.04

以下のように

  • Python 3.10.5
  • Ubuntu 20.04

が実行されていないことが確認できました
スクリーンショット 2023-02-12 12.17.24.png

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?