CI/CDを当たり前にした状態で開発をしていると短い時間で連続的にPushすることも時としてあるのではないでしょうか。 短い時間で複数Pushしたときは最新の状態で1回だけ実行されれば期待している効果を得ることができますが、Push単位でワークフローが実行されるため、ただの消化試合的なものが生まれてしまいます。 もちろん、リソース無制限で完全無料な何かであればそこまで気にすることはないと思いますが、大体のサービスは一定の利用を超えると従量課金として費用が発生します。 あまりお金のことに関わることが少ないと、コスト意識を持つことは難しいかもしれませんが、少しでも効果の薄い処理は減らした方がよいと思います。
また、並列実行するような処理では一般的に知られていることかと思いますが、順序性が保証されていないので、後から実行されたものが最初に終了することもあります。 もし、コンテナレジストリなどにイメージ情報を登録するなどの処理を行なっていた場合に、順序が入れ替わることで意図しない変更内容で登録されてしまい、不具合につながることもあるかもしれません。
①→②→③の順番でワークフローの実行が終わらない間に連続的に何らかの変更がPushされたとします。最新の状態は③になりますが、並列実行で①〜③のものが実行されて、最終的に処理が終わった順番が①→③→②となってしまうと、最新のコンテナイメージの情報は②となってしまいます。
ポイント
- 共通リソースに対して登録や更新をすることがあるか
- コンテナレジストリにイメージ情報を登録して、コンテナ起動時に最新の内容が参照される など
解決方法
同一ワークフローが同時に起動されようとした際に、既に実行中のワークフローをキャンセルします。 GitHub ActionsやCircleCIでは起動中の同一ワークフローをキャンセルする仕組みが用意されていますが、それぞれで呼び方や設定方法が異なるため、それぞれの手順をご紹介します。
GitHub Actionsの場合
GitHub Actionsでは、concurrencyという機能を使用します。この機能を使用することでconcurrencyに定義したキーワードが一致するワークフローが既に実行中の場合には終了するまで待機するようにできます。また、cancel-in-progress
にtrue
を指定することで既に実行中のワークフローを途中でキャンセルすることもできます。
concurrency: group: ${{ github.ref }} cancel-in-progress: true
CircleCIの場合
CircleCIではAuto Cancel機能を使用します。設定方法は、GitHub Actionsと違い画面から設定を行います。
設定を有効化したいプロジェクトを開き、設定を有効化します。
設定画面が表示できたら、Advanced
のタブをクリックします。
詳細設定画面が表示できたら、画像の設定項目が表示されるまで下にスクロールしてラジオボタンをONにします。