GitHub Actions Matrix戦略:テスト時間を「極限」まで削ぎ落とす並列実行の極意
CI/CDのボトルネックは、常に「テストの待ち時間」だ。プロダクトが成長するにつれ、多様なOS、複数の言語バージョンを担保するためのテスト時間は指数関数的に増大する。
「とりあえず全部通せばいい」という考えは、開発スピードを殺す。本稿では、GitHub ActionsのMatrix戦略を駆使し、テストを並列化して「待ち時間を一定に抑える」ためのプロの戦術を伝授する。
—
1. Matrix戦略の真髄:単なる「網羅」で終わらせない
Matrix戦略は、単に組み合わせを自動生成する機能ではない。「ボトルネックを特定し、並列実行の粒度を最適化するための戦略的マッピング」である。
以下の設定は、Node.jsの主要バージョンとOSを網羅しつつ、実行時間を最小化するベストプラクティス構成だ。
実践YAML設定:`strategy.matrix` の最適化
name: CI Pipeline
on: [push, pull_request]
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
# fail-fastをfalseにすべきか?
# 開発初期はtrueで即時検知、安定期はfalseで全環境の失敗を一挙に把握するのが定石
fail-fast: false
matrix:
node-version: [18.x, 20.x, 22.x]
os: [ubuntu-latest, windows-latest, macos-latest]
# 特定の環境でのみ走らせたいテストがある場合はincludeを活用
include:
- os: ubuntu-latest
node-version: 22.x
is-primary: true # カバレッジ計測はこの環境だけで十分
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: ‘npm’ # 実行時間を劇的に短縮する必須設定
- run: npm ci
# is-primaryのみカバレッジを出力し、CIコストを削減
- run: npm test — –coverage
if: matrix.is-primary == true
- run: npm test
if: matrix.is-primary != true
【現場の知見】実行時間を削る3つの掟
1. `cache` は神。 `actions/setup-` 系のキャッシュ機能を使わないのは、深夜2時にオフィスで手動デプロイするのと同じくらい非効率だ。
2. 実行環境を絞れ。 全ての組み合わせでカバレッジを取る必要はない。Ubuntu最新版のみ詳細計測し、残りは「パスするか否か」の検証に徹する。
3. `fail-fast: false` の戦略的運用。 巨大なテストスイートの場合、1つ落ちた時点で全て止めるか、全部流して「どの環境で何が落ちるか」を可視化するか、プロジェクトのフェーズで使い分けろ。
—
2. 開発スピードを加速させる「裏技」と神ツール
GitHub Actionsを日常的に使うなら、以下のツールとテクニックは「標準装備」にすべきだ。
隠れた神プラグイン・拡張機能
- [GitHub Actions VS Code Extension](https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-github-actions): YAMLのバリデーションはもちろん、実行中のジョブのログをエディタ内で追える。ブラウザを行き来する時間をゼロにせよ。
- [act (Run GitHub Actions locally)](https://github.com/nektos/act): 「コミットしてプッシュして確認」のサイクルを繰り返していないか?`act`を使えば、ローカルのDocker環境でGitHub Actionsをエミュレートできる。これなしのCI開発は、視界不良の中を高速道路で走るようなものだ。
チーム開発の共有化ルール
設定ファイルが肥大化すると、誰も修正できなくなる。
- Composite Actionsの活用: 頻出するセットアップ処理(Dockerログインや認証系)は、`action.yml`として外部リポジトリに切り出せ。
- Reusable Workflows: 複数のリポジトリで同じCI戦略を強制したい場合、コピペは禁止だ。`on: workflow_call:` を使い、CIの標準化を強制しろ。
—
3. テックリードからの提言:CIの「負債」を積むな
CIが「遅い」と感じた瞬間が、アーキテクチャの改善しどきだ。
1. テストの分割: 1つのジョブが10分かかるなら、それはテストが肥大化しすぎている証拠。`npx jest –shard=1/4` のように、テスト自体を分割して並列実行する戦略を検討せよ。
2. キャッシュの汚染を避ける: `npm ci` を使うのは当然として、`package-lock.json` の変更検知を正しく行うこと。
3. 「失敗」を設計する: 成功時だけでなく、失敗時の通知(Slack/Teams)と、失敗したジョブへのリンク生成までがCIエンジニアの仕事だ。
最後に
CI/CDは「自動化のための自動化」になってはいけない。「エンジニアが安心してコードを書き、一瞬でフィードバックを得るためのインフラ」であるべきだ。
Matrix戦略を使いこなし、多様な環境でのテストを「当たり前の日常」に組み込んでほしい。コードが成長する速度を、CIが妨げるような未来は、我々の手で終わらせよう。
—
「自動化は、怠惰になるためではなく、創造的な議論に時間を使うためにある。」
— 伝説のエンジニアより