GitHub Actions Worlflowを途中でキャンセルしてCIコスト削減してみた
はじめに
先日、GitHub Actions に Larastan と Laravel Pint を導入する記事を作成しました。
こちらを更に補完する形の記事になります。
「GitHub Actions の無料枠をすぐ使い切ってしまう、プランも上げたくないし...」といったユーザーの方は是非ご一読ください。
プランを上げる前にコスト削減できるかもしれません。
結論
古いCIは強制的に停止させよう。
背景
以前いた現場でいつも通りPR作成し、レビュー修正等をした後更にコミット&プッシュをしていると、普段動いているはずのCIが全く動かない問題が起きていました。
エラー文は忘れてしまったのですが、「CIの無料枠を使い切ってしまったため利用できないです」といった内容を示すものです。
GitHub Actions は、CIが動いている時間によって課金が決まります。
プランによって無料枠が決められていて、それを超えると追加で課金しないと利用できないといったものですね。
詳しくは以下をご参照ください。
その無料枠を全て使い切ってしまったということなのですが、基本的にプランを上げるしか手段が無いのかな?といったところです。
ただその当時にいたエンジニアの方が更に調査を進め、この無料枠を使い切る原因を突き止めました。
原因
「古いCIが実行完了するまで動いていた」ことが原因です。
PRを作成したタイミングでCIが起動するのですが、これを「Worlflow_1」とします。
その直後に修正し、CIの起動が終わる前にコミット&プッシュした時も新たにCIが起動するのですが、これを「Workflow_2」とします。
しかし、実際にCIで検査をしてほしいのは最新のコミットであって、既に古いコミットとなってしまった Workflow_1 が成功しようが失敗しようが関係ありません。
そのため、Workflow_1が動いている時間は完全に無駄になってしまいます。
こういったものがたくさん積み重なることで、大量にCIリソースを消費してしまったということが無料枠を使い切る原因の一つです。
これを防ぐために、「新しいCIが起動するタイミングで古いCIを停止する」という処理を追加する必要があります。
方法
styfle/cancel-workflow-action
を追加しましょう。
steps:
# リポジトリをチェックアウト
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
# 現在動いているワークフローをキャンセル
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.8.0
with:
access_token: ${{ github.token }}
リポジトリのチェックアウトは別にしてもしなくても構わないと思います。
とにかく必要なのは、githubのアクセストークンを設定することです。
ただ基本的にCIではリポジトリをチェックアウトして何かしら動かすことが大半なので、リポジトリチェックアウト時にtokenを設定させて、それを使用するという流れで書いています。
これを使用することで、古いCIが停止し、以下のような状態になります。
終わりに
結局これを利用しても無料枠を使い切ってしまったのですが、月半ばで使い切ってしまったのが、月末付近に変わりました。
CIを入念に設定していて、コミッターが多い案件だとどうしても無くなってしまうことがあると思います。
それに少しでも抗うことがコスト削減につながると思いますので、まずはこの手法を一度試してみてからプラン変更を検討するのが良いかもしれませんね。
Discussion
同一ブランチに対するCIの同時実行を制御したい場合、concurrencyを設定した方が手っ取り早いと思います。
例:コンカレンシーとデフォルトビヘイビアーの使用
ワークフローをキャンセルするワークフローは不要です。
ありがとうございます!
確かにこれで実現できそうですね...GitHub Actionsでそもそも用意あったんですね...。
大変勉強になりました!ありがとうございます🙏