GitHub Actions Worlflowを途中でキャンセルしてCIコスト削減してみた

2023/12/24に公開2

はじめに

先日、GitHub Actions に Larastan と Laravel Pint を導入する記事を作成しました。

https://zenn.dev/tatsuyaaa/articles/9ab20a08b07488

https://zenn.dev/tatsuyaaa/articles/bd5b73ef1f1882

こちらを更に補完する形の記事になります。

「GitHub Actions の無料枠をすぐ使い切ってしまう、プランも上げたくないし...」といったユーザーの方は是非ご一読ください。

プランを上げる前にコスト削減できるかもしれません。

結論

古いCIは強制的に停止させよう。

背景

以前いた現場でいつも通りPR作成し、レビュー修正等をした後更にコミット&プッシュをしていると、普段動いているはずのCIが全く動かない問題が起きていました。

エラー文は忘れてしまったのですが、「CIの無料枠を使い切ってしまったため利用できないです」といった内容を示すものです。

GitHub Actions は、CIが動いている時間によって課金が決まります。

プランによって無料枠が決められていて、それを超えると追加で課金しないと利用できないといったものですね。

詳しくは以下をご参照ください。

https://docs.github.com/ja/billing/managing-billing-for-github-actions/about-billing-for-github-actions

その無料枠を全て使い切ってしまったということなのですが、基本的にプランを上げるしか手段が無いのかな?といったところです。

ただその当時にいたエンジニアの方が更に調査を進め、この無料枠を使い切る原因を突き止めました。

原因

「古いCIが実行完了するまで動いていた」ことが原因です。

PRを作成したタイミングでCIが起動するのですが、これを「Worlflow_1」とします。

その直後に修正し、CIの起動が終わる前にコミット&プッシュした時も新たにCIが起動するのですが、これを「Workflow_2」とします。

しかし、実際にCIで検査をしてほしいのは最新のコミットであって、既に古いコミットとなってしまった Workflow_1 が成功しようが失敗しようが関係ありません。

そのため、Workflow_1が動いている時間は完全に無駄になってしまいます。

こういったものがたくさん積み重なることで、大量にCIリソースを消費してしまったということが無料枠を使い切る原因の一つです。

これを防ぐために、「新しいCIが起動するタイミングで古いCIを停止する」という処理を追加する必要があります。

方法

styfle/cancel-workflow-action を追加しましょう。

https://github.com/styfle/cancel-workflow-action

workflow.yml
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を入念に設定していて、コミッターが多い案件だとどうしても無くなってしまうことがあると思います。

それに少しでも抗うことがコスト削減につながると思いますので、まずはこの手法を一度試してみてからプラン変更を検討するのが良いかもしれませんね。

GitHubで編集を提案

Discussion

re3turnre3turn

同一ブランチに対するCIの同時実行を制御したい場合、concurrencyを設定した方が手っ取り早いと思います。
例:コンカレンシーとデフォルトビヘイビアーの使用

ワークフローをキャンセルするワークフローは不要です。

TatsuyaaaTatsuyaaa

ありがとうございます!

確かにこれで実現できそうですね...GitHub Actionsでそもそも用意あったんですね...。
大変勉強になりました!ありがとうございます🙏