【GitHub Actions】並列JOBでビルド時間を短縮する

【GitHub Actions】並列JOBでビルド時間を短縮する

GitHub Actionsの並列ジョブを活用することで、実行時間を大幅に短縮する。本記事では、その際に用いた具体的な手法や設定について、備忘録として共有します。

GitHub Actions #CI/CD#Github#備忘録

【GitHub Actions】並列JOBでビルド時間を短縮する

サムネイル

GitHub Actionsの並列ジョブを活用することで、実行時間を大幅に短縮する。本記事では、その際に用いた具体的な手法や設定について、備忘録として共有します。

更新日: 6/25/2025

プロジェクトの規模が拡大するにつれ、テストが増えたり静的解析など対応しなければらないこともあり、CI/CDの実行時間が増加しがちです。

基本的な並列JOB

lintやユニットテストのように、互いに依存しないタスクは、jobs配下に並べて定義するだけで並列実行されます。これが最も基本的な並列化の手法です。

# .github/workflows/ci.yml
jobs:
  test-unit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm test:unit

  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm run lint

一方、「ビルド後にテストを実行する」といった依存関係の制御には、needsキーワードを用います。これにより、先行JOBの完了を待って後続のJOBを開始させることが可能です。以下の例では、buildの完了後に2つのテストが並列で実行されます。

# .github/workflows/ci.yml
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: npm run build
      # この後、ビルド成果物をアーティファクトとしてアップロード

  test-chrome:
    needs: build # buildジョブの完了を待機
    runs-on: ubuntu-latest
    steps:
      # アーティファクトをダウンロードしてからテスト実行
      - run: npm test:chrome

  deploy:
    needs: [test-chrome, test-firefox] # 2つのテストジョブの完了を待機
    runs-on: ubuntu-latest
    steps:
      - run: echo "All tests passed, deploying..."

アーティファクト

GitHub Actionsの各JOBは独立した仮想環境で実行されるため、JOB間でファイルなどの成果物に当たる物を直接共有することはできません。

そこで、JOB間でファイルを共有する仕組みとして「アーティファクト」を利用します。先行JOBでactions/upload-artifactを用いてファイルをアップロードし、後続のJOBでactions/download-artifactでダウンロードすることで、データの受け渡しをします。

バージョンv4は高速化されており、利用を推奨されているようです。また、retention-days: 1のように保持期間を短く設定することで、ストレージコストを抑える工夫も有効です。

# .github/workflows/ci.yml
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: npm run build
      - uses: actions/upload-artifact@v4
        with:
          name: dist-files
          path: ./dist
          retention-days: 1

  package:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: dist-files
      - run: ls -l # distディレクトリが展開されている

テストの効率化

strategy.matrixを使用すると、複数のOSやNode.jsバージョンなど、様々な組み合わせのテストを効率的に実行できます。マトリックスに定義した組み合わせに基づき、JOBが自動で生成され、並列処理される仕組みのようですね。

# .github/workflows/ci.yml
jobs:
  test:
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        node: [16, 18, 20]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
      - run: npm test

ワークフローの最適化

コスト削減
concurrencyを設定することで、同一ブランチへの連続プッシュ時に、実行中のワークフローを自動でキャンセルできます。これにより、不要なリソース消費を防ぐことが可能です。

# .github/workflows/ci.yml
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

ジョブ失敗時の挙動
continue-on-error: trueを設定することで、特定のJOBが失敗した場合でも、ワークフロー全体が停止するのを防ぐことが可能です。また、後続のジョブでif: always()条件を使用すれば、先行JOBの成否にかかわらず処理を実行させることもできます。

# .github/workflows/ci.yml
jobs:
  test-optional:
    runs-on: ubuntu-latest
    continue-on-error: true # このJOBが失敗しても後続は止まらない
    steps:
      - run: npm test:experimental

  deploy:
    needs: test-optional
    if: always() # test-optional JOB の成否に関わらず実行
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying..."

まとめ

GitHub Actionsの並列処理機能を活用することで、CI/CDの実行時間を大きく改善できるかもしれません。

  • 独立タスクの並列化が基本
  • needsによる依存関係の定義
  • アーティファクトによるデータ共有
  • **matrixによる多環境テストの効率化
  • concurrencyなどによるワークフローの最適化

検索

検索条件に一致する記事が見つかりませんでした