すぐにできる!CIを高速化する3つの方法【GitHub Actions】
CIの実行速度が遅くてイライラしている人向け。
GitHub ActionsでCIの実行を高速化する方法を3つご紹介します。
CIを高速化する3つの方法【GitHub Actions】
今回紹介するのは以下の3つの方法です。
- Jobの分割
- パッケージのキャッシュ処理を追加
- テストの分割と並列実行
Jobの分割
Jobは分割することで、それぞれのJobが並列に動作するようになります。
例えば、ユニットテストの実行とLinterの実行は、多くの場合独立して動作しても問題ないものです。
これらは一つのJobの中に直列に記述するのではなく、Jobを分けて記述した方が効率的でしょう。
jobs:
test:
runs-on: ubuntu-22.04
steps:
...
lint:
runs-on: ubuntu-22.04
steps:
...
パッケージのキャッシュ処理を追加
パッケージは、キャッシュしておくと時間のかかるパッケージのインストール処理をスキップできるのでおすすめです。
公式が提供しているactions/cacheを利用して、キャッシュの処理を実装しましょう。
以下の場合は、OS、Nodeバージョン、もしくはパッケージ情報を管理しているファイル(package-lock.json)に変更がある場合のみnpm ci
が実行され、それ以外の場合はキャッシュが利用されます。
- name: cache and restore packages
id: cache-npm
uses: actions/cache@v4.0.2
with:
path: node_modules
key: ${{ runner.os }}-${{ steps.tool_versions.outputs.nodejs }}-${{ hashFiles('**/package-lock.json') }}
- name: install npm packages
if: steps.cache-npm.outputs.cache-hit != 'true'
run: npm ci
shell: bash
テストの分割と並列実行
テストの実行に時間がかかる場合は、テストを分割した上で、それぞれを並列で実行することで高速化を図れます。
例えば、Jestの場合は、GitHub Actionsのmatrix strategyとコマンドオプションの--shardを組み合わせることで、テストの分割と並列実行を簡単に実現できます。
matrix strategy
は、一つのJob内で、変数に定義した値ごとにJobを動作させる手法で、--shard
はテストを分割するオプションです。
これらを使って、以下のようなワークフローを定義します。
jobs:
test:
runs-on: ubuntu-22.04
strategy:
matrix:
shard: [1/4, 2/4, 3/4, 4/4]
steps:
- name: checkout
uses: actions/checkout@v3
- name: setup environment
uses: ./.github/actions/setup
- name: run test
run: npx jest --ci --shard=${{ matrix.shard }}
これにより、4つのJobが並列で動作し、それぞれのJobが1/4ずつテストを実行してくれます。
Jest以外にも--shard
のようなオプションがあるかは分からないですが、考え方自体はどの言語にも応用できると思います。
⚠️matrix strategyの注意点
あまりにJobを分割しすぎると、GitHub Actionsの課金時間(Billable time)が大幅に増加する可能性があります。
どの程度Jobを分割するかは、ワークフローの実行時間(Total duration)だけでなく、課金時間(Billable time)も見た上で適切な値を設定するようにしましょう。
他にも方法はある
今回は手軽にできるCIの速度改善方法として、以下の3つを紹介しました。
- Jobの分割
- パッケージのキャッシュ処理を追加
- テストの分割と並列実行
ただ、これら以外にもlarger runnerを利用する方法や、変更があった部分のみテストを実行する方法など、速度改善の手法は色々とあります。
使える時間的・経済的なリソースを認識した上で、できる範囲で少しずつ改善していくのがおすすめです。
Discussion