ある日 GitHub Actions が失敗していた。。
GitHub Actions の実行結果が表示されるページにThis job failedと表示されていました。
Re-run jobsしてもジョブは失敗したまま。よく見ると、エラーメッセージが。
The job was not started because recent account payments have failed or your spending limit needs to be increased. Please check the 'Billing & plans' section in your settings.
GitHub Actions の無料枠を使い切っていました。とりあえず追加料金を払う設定をしてエラーは解決しました。
ですが、ちょうど最近 GitHub Actions の実行が終わるまで20分以上かかるようになっていて、待つのがしんどくなってきていた所だったので改善に取り組むことにしました。
結果、 21分かかっていた処理が、12分程度 まで短縮できました。この記事はその時の記録です。
GitHub Actions の構成
運用していた GitHub Actions の構成です。
- Nuxt3 をセットアップ(
npm ci等) - ユニットテスト(Vitest)
- e2e テスト(Playwright)
- Dockerfile からイメージをビルド
- Cloud Run にアップロード
やったこと
- 使ってないライブラリを依存関係から削除
node_modulesをキャッシュ- job の並列実行
1. 使ってないライブラリを依存関係から削除
GitHub Actions では基本的に毎回依存関係を都度ダウンロードする必要があります。キャッシュを使っていたとしても初回は必ずダウンロードします。
通信の無駄なので、以前使っていて今は使っていないライブラリがpackage.jsonに残っていたのでアンインストールしました。
npm uninstall [使っていないパッケージ名]
2. node_modulesをキャッシュする
次はnode_modulesのデータをキャッシュします。次回からキャッシュから復元することで、npm ciするより早くnode_modulesを構成できます。
jobs:
setup:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: 1. node_modules をキャッシュする
id: cache-npm-node-modules
uses: actions/cache@v3
env:
cache-name: node-modules
with:
path: "node_modules"
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('package-lock.json') }}
- name: 2. キャッシュがなかったら npm ci を実行
if: steps.cache-npm-node-modules.outputs.cache-hit != 'true'
run: |
npm ci
ポイント 1. node_modules をキャッシュする
actions/cacheを使用してデータをキャッシュします。
id: Step2で Step1の結果を取得envcache-name:key内で使用
withpath: キャッシュするディレクトリを指定key: キャッシュした時のディレクトリ名
actions/cacheはkeyに合致するキャッシュがあったら、キャッシュから復元します。keyにhashFiles('package-lock.json')を含めることで、package-lock.jsonの変更、つまり依存関係の変更を検知します。
keyに合致するキャッシュがなかったらactions/cacheはキャッシュを復元しません。
ポイント 2. キャッシュがなかったら npm ci を実行
npm ciはnode_modulesがあったとしても依存関係を再ダウンロードします。なので、実行時間を短縮するためにはキャッシュがあった場合はnpm ciを実行したくありません。
node_modulesがあった場合はnpm ciを実行しないnode_modulesがなかった場合はnpm ciを実行する
という挙動をifを使って作っています。
そうすることで初回実行時や、依存関係に変更があった時だけnpm ciを実行しています。
3. job の並列実行
元々、ユニットテストと、e2e テストを直列で実行していましたが、並列で実行するように変更しました。
jobs:
setup:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
# 依存関係のインストール等
# 依存関係をキャッシュ
test-unit:
needs: [setup]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
# 依存関係を復元
# ユニットテストを実行
test-e2e:
needs: [setup]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
# 依存関係を復元
# e2e テストを時効
deploy:
needs: [setup, test-e2e, test-unit]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
# 依存関係を復元
# ビルドしてデプロイ
ポイント
needsでジョブが実行されるまでに完了している必要があるジョブを定義しています。例えばdeployジョブはsetup、test-e2e、test-unitが正常に終わっていないと実行されません。
また、各ジョブではインストールしたnode_modulesなどは引き継げないので、キャッシュして復元する必要があります。
さいごに
全部の対策を行なった結果、 21分かかっていた処理が12分程度まで短縮できました!










を使ったテストを作る,co_rgb:fff,w_620,c_fit/w_300/ogp_image_zorhlz.png)
