はじめに
GitHub Actions を用いて、PR作成時等に pytest
と Ruff
を実行することで、開発サイクルに単体テスト実行とフォーマットを組み込みました。その際に開発環境と同様に、uv
をパッケージ管理ツールを使いました。基本的には uv
のドキュメントに沿って動かすことができましたが、追記した箇所が一部あるため、備忘録を兼ねて記事として共有します。
Using uv in GitHub Actions
まずは、uv
の公式ドキュメントに沿って、GitHub Actions 上で uv
を利用できる状態を実現しました。
name: Example
jobs:
uv-example:
name: python
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v4
pytest
続いて、上記の yml
をベースに pytest
を実行する job を作成します。参考として、pip
を用いて、pytest
を GitHub Actions を実行する方法は、下記のドキュメントに記載されています。
次のような yml
ファイルを作成して、GitHub Actioons を実行してみました。すると、自作のパッケージが読み込めずテスト実行できないというエラーが発生してしまいました。
name: Example
jobs:
uv-example:
name: python
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version-file: "pyproject.toml"
- name: Install the project
run: uv sync --all-extras --dev
- name: Run tests
run: uv run pytest tests
この問題は env
に PYTHONPATH: ${{ github.workspace }}
の1行追加するだけで解決しました。${{ github.workspace }}
はGitHub Actionsのコンテキスト変数で、現在のリポジトリのクローンがチェックアウトされるディレクトリを指します。リポジトリ内のPythonモジュールやパッケージをインポートして使用することが可能になります。PYTHONPATH
を設定することで、これは uv に起因する問題ではないですが、躓いたので記載しました。
name: Example
jobs:
uv-example:
name: python
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version-file: "pyproject.toml"
- name: Install the project
run: uv sync --all-extras --dev
- name: Run tests
env:
PYTHONPATH: ${{ github.workspace }}
run: uv run pytest tests
これにより、下図のように pytest
が実行できるようになりました。
Ruff
Ruff についても、GitHub Docs の下記の例を参考にしました。
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install the code linting and formatting tool Ruff
run: pipx install ruff
- name: Lint code with Ruff
run: ruff check --output-format=github --target-version=py39
- name: Check code formatting with Ruff
run: ruff format --diff --target-version=py39
continue-on-error: true
上記の例をもとに、uv を使用する下記の記述に書き直してみました。
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version-file: "pyproject.toml"
- name: Install ruff
run: uv pip install --system ruff
- name: Lint code with Ruff
run: ruff check --output-format=github --target-version=py313
- name: Check code formatting with Ruff
run: ruff format --diff --target-version=py313
continue-on-error: true
これにより、下図のように Ruff
が実行できるようになりました。
その他の工夫
ここまでの設定で実行はできるようになりましたが、効率的なリソース活用のために、追加で2点の工夫をしたので、その内容についても記載します。
重複実行回避
次の設定をすることで、同じワークフロー名とリファレンスを持つワークフローが同時に実行されないようにしました。
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
タイムアウト設定
GitHub Actions では、デフォルトのタイムアウト時間が6時間になっているので、時間を明示的に5分まで短く設定しました。
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 5
おわりに
以上の作業を経て、下記の2つの yml
ファイルを作成しました。GitHub Actions で uv
を動かす方の参考になれば幸いです。もし改善点等あればコメントください。
name: pytest
on:
push:
branches:
- main
pull_request:
branches:
- main
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version-file: "pyproject.toml"
- name: Install the project
run: uv sync --all-extras --dev
- name: Run tests
env:
PYTHONPATH: ${{ github.workspace }}
run: uv run pytest tests
name: ruff
on:
push:
branches:
- main
pull_request:
branches:
- main
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version-file: "pyproject.toml"
- name: Install ruff
run: uv pip install --system ruff
- name: Lint code with Ruff
run: ruff check --output-format=github --target-version=py313
- name: Check code formatting with Ruff
run: ruff format --diff --target-version=py313
continue-on-error: true