GitHub Actions の concurrency は、同じグループに属する実行が重なった際に古いものを自動でキャンセルしてくれる便利な仕組みです。ただし、実際の運用では「全部キャンセルしてほしいわけじゃない」というケースが多々あります。
たとえば以下のような状況です。
- リリースタグ(または release ブランチ)のビルドは絶対にキャンセルされたくない
- main ブランチは更新頻度が高いので、古い実行はどんどんキャンセルして効率化したい
こうした要件に柔軟に対応するために大事なのが、
cancel-in-progress と concurrency.group は workflow 単位でも job 単位でも設定できる
という点です。
concurrency は workflow でも job でも設定可能
一般的な例では、workflow のトップに次のように記述します。
concurrency:
group: my-group
cancel-in-progress: true
ただし、これは必須ではなく、
job の内部にも concurrency を記述できます。
そのため、
- workflow 全体で大きなルールを決める
- job 単位で細かくキャンセル方針を切り替える
といった構成が可能になります。
concurrency.group も workflow / job どちらにも書ける
group は「どの実行を同じグループとして扱うか」を決める識別子です。
これも workflow に書いてもよいですし、job に書いても構いません。
柔軟に設計できるので、
- workflow 全体で 1 つの group を採用する
- job ごとに group を分けて違うキャンセルポリシーにする
- イベント(タグ/ブランチ)によって group を変えて完全に別物として扱う
といった構成ができるようになります。
「タグはキャンセルしない、main はキャンセルする」を実現できる理由
上記の通り、workflow・job のどちらにも concurrency が書けるため、
条件分岐によってキャンセル挙動を切り替えることが簡単です。
とくに job レベルで制御できる点が強力で、「タグのときだけキャンセルしない」「特定のブランチだけキャンセルさせる」といった運用が自然に構成できます。
条件分岐を利用した concurrency 設定も可能
GitHub Actions の concurrency は、単に固定値を書くのではなく、
context を使って group や cancel-in-progress を動的に変化させる
こともできます。
例えば、次のような記述が可能です。
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ !contains(github.ref, 'release/') }}
ここで行っていることは以下の通りです。
-
group:
- workflow 名 + ref(ブランチやタグ名)を組み合わせて
→ イベントごとに完全に独立した concurrency グループを作成
- workflow 名 + ref(ブランチやタグ名)を組み合わせて
-
cancel-in-progress:
- ref に
release/が含まれる場合はfalse(つまりキャンセルしない) - 逆に含まれない場合は
true(キャンセルする)
- ref に
つまり、
release ブランチはキャンセルせず、その他はキャンセルする
というポリシーを 1 行で実現しています。
これはタグ運用にも応用できますし、
contains(github.ref, 'refs/tags') のようにすればタグ専用にもできます。
このように、cancel-in-progress に式を書けること自体が非常に強力で、
分岐ロジックを concurrency の中へ直接書き込める
という点を理解しておくと一気に表現力が広がります。
この仕組みがとても便利な理由
1. リリースビルドを確実に残せる
タグや release ブランチのビルドを絶対に止めないようにできるため、成果物生成が中断される心配がありません。
2. main の無駄な実行を自動で整理できる
プッシュが続いたときも古い実行がキャンセルされるため、CI の無駄が減ります。
3. workflow を分割する必要がない
タグ用 workflow / main 用 workflow などを複数に分けず、一つの YAML にまとめて管理できます。
4. context を使った柔軟なキャンセル制御ができる
contains() などの式を使うことで、「特定のブランチ名だけキャンセル禁止」といったルールが自然に書けます。
まとめ
GitHub Actions の concurrency は、一般的に workflow の先頭に置く例が多いものの、実際には workflow・job のどちらにも書ける 仕様になっています。
さらに、group や cancel-in-progress には context を使った式が書けるため、イベント内容に応じたきめ細かい制御が可能です。
その結果、
- タグ(または release ブランチ)はキャンセルしない
- main は古い実行を積極的にキャンセルする
- release など特定の ref だけキャンセル不可にする
といった現実的で実用性の高い運用が非常に簡単に実現できます。
当サークルでは npm パッケージや Docker コンテナを GitHub Actions にてビルド、プッシュして運用しています。
もしこの記事を読んで興味が湧いたという方、下記サイトや Discord サーバーをぜひ覗いてみてください!
⭐︎ 公式サイト ↓
⭐︎ Discord サーバー ↓
また、いいね・フォロー等もよろしくお願いします!