1
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?

GitHub ActionsでPythonテストを徹底高速化:47ジョブ・15分→5分に短縮した実践手法

Posted at

はじめに

PythonのOSSプロジェクトで、3つのOS × 5つのPythonバージョン × 複数のテストパターンを実行すると、CI/CDの実行時間が大きな課題になります。本記事では、47個の並列ジョブを15分から5-6分に短縮(約65%削減)した実践的な高速化手法を紹介します。

プロジェクト概要

NanaSQLiteというPythonモジュールプロジェクトで以下の構成を実装しています:

  • テストジョブ: 15並列(3OS × 5バージョン)
  • 同期ベンチマークジョブ: 15並列(3OS × 5バージョン)
  • 非同期ベンチマークジョブ: 15並列(3OS × 5バージョン)
  • 集計・サマリージョブ: 2個
  • 合計: 47ジョブ

高速化手法1: UVによる依存関係インストールの爆速化

pipの8-10倍高速なパッケージマネージャーuvを導入しました。

- name: Install uv
  uses: astral-sh/setup-uv@v7
  with:
    enable-cache: true  # キャッシュを有効化

- name: Install dependencies
  run: |
    uv pip install --system pytest pytest-xdist pytest-benchmark
    uv pip install --system -e .

ポイント

  • astral-sh/setup-uv@v7が自動的にキャッシュを管理
  • --systemフラグでグローバル環境にインストール
  • 従来のpipと比較して依存関係解決が圧倒的に高速

高速化手法2: pytest-xdistによる並列テスト実行

テストを複数コアで並列実行することで大幅に時間短縮しました。

- name: Run tests
  run: |
    pytest tests/ -v -n auto --ignore=tests/test_benchmark.py

ポイント

  • -n auto: GitHub-hostedランナーの利用可能コア数を自動検出(通常2コア)
  • テストの独立性が保たれていれば、ほぼ2倍の高速化を実現
  • ベンチマークテストは--ignoreで除外(並列実行すると正確な計測ができないため)

高速化手法3: 大規模マトリックス設計

複数のOS・Pythonバージョンを効率的にテストするマトリックス戦略を採用しました。

strategy:
  fail-fast: false
  matrix:
    os: [ubuntu-latest, windows-latest, macos-latest]
    python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']

ポイント

  • fail-fast: false: 1つが失敗しても全ての組み合わせを実行
  • GitHub Educationで並列実行数40(通常20)を活用
  • macOSは5並列制限があるため段階的に実行される

高速化手法4: 段階実行による効率化

テスト失敗時に無駄なベンチマークを実行しないよう、needsで依存関係を設定しました。

jobs:
  test:
    # ... テスト実行
  
  benchmark:
    needs: test  # テスト成功後に実行
    # ... 同期ベンチマーク
  
  async-benchmark:
    needs: test  # テスト成功後に実行
    # ... 非同期ベンチマーク
  
  benchmark-summary:
    needs: [benchmark, async-benchmark]
    # ... 結果集計

実行フロー

  1. Stage 1: テスト(15並列)→ 約2-3分
  2. Stage 2: ベンチマーク(30並列)→ 約2-3分
  3. Stage 3: 集計・サマリー(2直列)→ 約数十秒

高速化手法5: Artifact収集とサマリー自動生成

全ジョブの結果を自動的に収集し、見やすいサマリーを生成します。

benchmark-summary:
  needs: [benchmark, async-benchmark]
  runs-on: ubuntu-latest
  steps:
  - name: Download sync benchmark results
    uses: actions/download-artifact@v6
    with:
      pattern: benchmark-results-*
      path: benchmark-results
  
  - name: Generate Combined Benchmark Summary
    run: |
      echo "## 📊 Performance Benchmarks" >> $GITHUB_STEP_SUMMARY
      python3 scripts/parse_benchmark.py benchmark-results sync >> $GITHUB_STEP_SUMMARY

出力内容

  • ✅/❌ 各ジョブの成功・失敗ステータス
  • 同期/非同期それぞれの最速・最遅・平均実行時間
  • OS・Pythonバージョン別の一覧表

完全なワークフロー構成

全体の構成は以下の通りです:

name: NanaSQLite Tests

on:
  push:
  pull_request:
    types: [opened, synchronize, reopened, ready_for_review]

jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
    
    steps:
    - uses: actions/checkout@v4
    - name: Install uv
      uses: astral-sh/setup-uv@v7
      with:
        enable-cache: true
    - name: Set up Python
      uses: actions/setup-python@v6
      with:
        python-version: ${{ matrix.python-version }}
    - name: Install dependencies
      run: |
        uv pip install --system pytest pytest-xdist
        uv pip install --system -e .
    - name: Run tests
      run: pytest tests/ -v -n auto

今後の展望

さらなる改善として以下を検討しています:

GitHub Pagesでのベンチマーク可視化

github-action-benchmarkを使用して、ベンチマーク結果を時系列グラフで可視化。パフォーマンスリグレッションを自動検出できます。

条件付き実行

PR時はUbuntu + 最新Pythonのみ実行し、mainマージ時に全OS・全バージョンをテストする戦略。

セルフホステッドランナー

将来的には自前サーバーで実行し、さらなる高速化とコスト削減を目指します。

まとめ

5つの手法を組み合わせることで、47ジョブの大規模CI/CDを15分から5-6分に短縮しました:

  1. UV + キャッシュ: 依存関係インストールを爆速化
  2. pytest-xdist: テストを並列実行
  3. 大規模マトリックス: 効率的な多環境テスト
  4. 段階実行: 無駄な実行を削減
  5. 自動サマリー: 結果の可視化

これらの手法は他のPythonプロジェクトでも応用可能です。特にOSSプロジェクトでは、GitHub Educationを活用することで並列実行数を倍増できるため、積極的に申請することをおすすめします。

1
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
1
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?