【全セッカチに告ぐ】CIに時間がかかる時にやること
公開: 2025年11月29日
私はせっかちです。
待てません。待つ時間があろうものなら違うこと始めます。
そしてどこで何してるか訳わからなくなって誤pushします。
冗談はさておき、CIの実行速度ってPRの確認依頼までの速度に影響するし、待った挙句落ちたみたいなこともありエンジニアの生産性に直結しますよね。
今回8~9分かかるCiの実行時間を短くするタスクをいただいてやってきたのでその内容を共有します!!!!
Ruby on RailsとNext.jsなのですが、今回はNext.jsのみ取り上げます!!
※今回の内容はあんまり関係ないです
コードをpushするたびに自動でテスト・Lint・ビルドを実行して、問題がないか確認する仕組み です。
PRを出す前に「このコード壊してない?」をチェックしてくれるので、開発の安心材料になる反面、このCIが遅いと開発者がずっと待つことになります。
CI落ちるとマージしてはいけません!何か問題ある!(lintとか別にええやんなこともあるけど)
全てのjobが1直線で同期的に進行していたことがまず大きな原因でした。
言い換えると並列で走らせられる処理を、全部1本の直列で実行していたことでした。
具体的にはこんな状態:
Lint → Test → Build 全部が1列に並んで順番待ち。(1つのJob の中で、全部の処理が 1プロセスで順番に実行されてた)
Lintが終わらないとTestが始まらないし、Testが終わらないとBuildが始まらない。
この1本道の構成だと、どれか1つでも重いJobがあると全体が押しつぶされます。
本来なら:
Lint と Test は並列にできる(Lintの結果にTestは依存しない)
Test も複数分割して同時に走らせられる(matrix戦略)
なのに、今回は全部がひとつのJobに詰め込まれていたため8〜9分かかっていました。
イメージ以下のような感じです
jobs:
ci:
runs-on: ubuntu-latest
steps:
- lint
- test
- buildまずは並列で問題ないことをjobに分解して同時進行することにしました。
buildとlintチェックってそれぞれ処理の順番依存しないし、
npm run buildnpm run lint独立して実行できますよね?つまり並列処理可能ってことです。
こんなイメージ
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- run: npm install
- run: npm run lint
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- run: npm install
- run: npm run build
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- run: npm install
- run: npm testこうすることで
lint ┐
build ┼ → 同時に実行!
test ┘buildに3分、testに5分かかっていたとしたら並列処理する前は合計8分かかっていたのが、並列(job分ける)にすることでtestにかかる5分に短縮することができます!!!
一旦jobを並列処理することでだいぶ速度改善したのですがtestがちょっと遅い、、、
テストケースは今後も増えていくのでここはなんとかしたい。
GitHub Actions には matrix戦略 という仕組みがあり、
testファイルを複数グループに分けて
各グループを別runnerで同時実行できる
というものです。
例えば test を4つに分ければ、実質「4並列」で test が走ることになりめちゃくちゃ速くなります!!
test:
runs-on: ubuntu-latest
strategy:
matrix:
group: [1, 2, 3, 4]
steps:
- uses: actions/checkout@v3
- run: npm install
- run: npm run test:e2e --group ${{ matrix.group }}これにより、test が4つのrunnerに別れて一斉に実行されます。
Group1: testの一部
Group2: testの一部
Group3: testの一部
Group4: testの一部こうなる
Group1 ┐
Group2 ┼ → 4並列!!
Group3 ┼
Group4 ┘参考
これで8分50秒かかってたのが2分半まで短縮できました!!!
before
atfer
この一つひとつがjobです!
CI今までほぼ関わってこなかったのですが、数値で見てわかる改善なのでめちゃ楽しいです!!!!!
RailsとNext.js両方やったので(Railsに関しては各job内で2プロセス実行して実質8並列しました)、めちゃくちゃ貢献してる感ありますね🙌
あと一つリポジトリあるのでそっちも楽しみます!!
