GitHub Actions Matrixの極致:ビルド時間を「物理的に」削り取る並列戦略
テックリードとして現場を見ていると、CIの実行時間が10分を超えたあたりからエンジニアの集中力が途切れ始めるのを痛感する。テストが終わるのを待つ間にSlackを見始め、コンテキストスイッチが起きる。この「待機時間」こそが、開発効率を殺す最大の敵だ。
GitHub ActionsのMatrix戦略は、単に「OSや言語バージョンを網羅する」ためのツールではない。CIを「線形」から「並列」へ構造転換し、フィードバックループを極限まで短縮するための戦略的兵器だ。
今日は、大規模なMatrix構成をスマートに管理し、コストを抑えつつテスト時間を最小化する「プロの現場の設計思想」を伝授する。
—
1. 脳死のMatrix設定から脱却せよ:動的マトリクス生成
多くのプロジェクトで見かけるのは、`yaml`にハードコードされた固定リストだ。しかし、環境が増えるたびにYAMLを編集するのはナンセンスだ。
神テクニック:JSON出力による動的マトリクス
依存関係やテスト対象が動的に変わる場合、前段のジョブでJSONを生成し、それを後段のMatrixに渡す。これが「CIの柔軟性」を担保する鍵だ。
jobs:
prepare-matrix:
runs-on: ubuntu-latest
outputs:
# JSON文字列として出力する
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- id: set-matrix
run: |
# ここでAPIやファイルベースでテスト対象を特定
TEST_TARGETS='[“test-a”, “test-b”, “test-c”]’
echo “matrix=$TEST_TARGETS” >> $GITHUB_OUTPUT
test:
needs: prepare-matrix
runs-on: ubuntu-latest
strategy:
matrix:
# 前段の出力を受け取って展開
target: ${{ fromJson(needs.prepare-matrix.outputs.matrix) }}
steps:
- run: ./run-test.sh ${{ matrix.target }}
—
2. 実行時間を極限まで圧縮する「fail-fast」と「max-parallel」
Matrixはデフォルトで256並列まで走るが、無制限に走らせれば当然コストが跳ね上がる。ここで意識すべきは「失敗の早期発見」と「リソースの最適化」だ。
- `fail-fast: true` (デフォルト): 1つのマトリクスが失敗した瞬間に他のジョブをキャンセルする。これは「失敗したなら即座に修正」というDevOpsの原則に則っている。
- `max-parallel`: 課金上限を制御する命綱だ。
strategy:
fail-fast: true
max-parallel: 10 # 同時実行数を制限し、無駄な課金を防ぐ
matrix:
os: [ubuntu-latest, windows-latest]
node-version: [18, 20]
—
3. 「神プラグイン」と開発者体験(DX)の向上
GitHub Actionsを日常的に使うなら、以下のツールはもはや必須装備だ。
- [GitHub CLI (`gh`)](https://cli.github.com/):
ターミナルから `gh run watch` を叩けば、ブラウザを開かずにCIの進行状況を追跡できる。これを使うだけでコンテキストスイッチの回数が激減する。
- [Action-validator](https://github.com/mondeja/action-validator):
CIを回す前にローカルでYAMLの構文チェックを済ませる。`commit` → `push` → `fail` のサイクルを断ち切るために不可欠だ。
—
4. チーム開発における「設定の共有化」ルール
プロジェクトが大きくなると、各リポジトリで同じような`workflow`を書いてしまい、「修正のたびに全リポジトリを更新」という地獄を見る。
究極の回避策:Composite Actionsの活用
共通のセットアップ(Node.jsのインストール、キャッシュ設定、認証)は、Composite Actionsとして別リポジトリで管理せよ。
.github/actions/setup-node/action.yml
name: ‘Composite Setup’
runs:
using: ‘composite’
steps:
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Cache dependencies
uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles(‘/package-lock.json’) }}
これを呼び出すだけで、全リポジトリで同じビルド環境を「即座に」統一できる。
—
5. テックリードからの提言:CIの「見える化」
ただ速くするだけでは不十分だ。「どのテストが遅いのか」を定量的に可視化せよ。
`junit.xml` を出力し、`mikepenz/action-junit-report` を使ってPR上にテスト結果をコメントさせる。これにより、「最近このテストの実行時間が伸びている(=コードが肥大化している)」という異常検知が誰の目にも明らかになる。
まとめ:今日からやるべきこと
1. 静的なMatrixを動的なJSON生成に切り替える。
2. `fail-fast` を適切に設定し、無駄なビルド時間を削減する。
3. Composite ActionsでCIの定義をリポジトリ横断的に共通化する。
CIは開発者の心臓部だ。ここを最適化することは、単なる技術的な遊びではなく、チーム全体の生産性を物理的に向上させる経営課題に近い。さあ、今すぐYAMLを書き換え、あなたのチームのビルド時間を削り出そう。