GitHub Actionsの同時実行設定でワークフローがキャンセルされる原因を確認する

GitHub Actionsのrunning取消とpending置換を分け、group値・queue single/max・部分成功の扱いを確認します。

AIものさし編集部

GitHub Actionsのconcurrencyでrunがcancelledになるときは、実行中runが中断されたのか、待機中runが新しいrunへ置き換わったのかを分けます。cancel-in-progressがfalseでも、既定queueでは古いpendingが残る保証はありません。解決後のgroup値と、どのrunが同じgroupへ入ったかを時刻順に確認します。

この記事は既存workflowの同時実行制御の診断を扱います。workflowの変更・実行・取消、deployment、外部処理の復旧は行っていません。run A/B/Cの例は架空で、GitHub上で挙動を再現した結果ではありません。GitHub.comと利用中のEnterprise Server等で採用できる構文が同じかも確認してください。

cancelled直前のrunを探す

対象run ID、workflow、job、event、ref、commit、開始・待機・取消時刻を並べます。UIのconclusionだけでなく、concurrencyに関するlogや表示と、直前に同じgroupへ入ったrunを照合します。手動取消やtimeoutなど、別の理由も同じcancelled表示になるためです。

表は横にスクロールできます

観測先に見る設定別の確認
実行中のAがBで止まるcancel-in-progressAの外部副作用
pendingのBがCで消えるqueueの既定・値Aは走り続けていないか
別workflowで相互に止まる解決後groupの衝突共有が意図したものか
設定後に起動できないqueueとcancelの組合せ構文対応・validation error

workflow-levelとjob-levelのconcurrencyを両方使う場合も、どの単位の制御で待っているかを区別します。表面上同じ名前のjobでも、workflow全体が待機中なら原因箇所が違います。

groupは式ではなく、評価された値で比べる

GitHub公式concurrencyガイド(新しいタブで開く)は、同じrepository内で同じgroupを使うworkflowやjobが制御対象になると説明しています。workflowファイルを分けても、共通の固定名なら互いに影響する可能性があります。

group名は大文字・小文字を区別しません。Productionとproductionを別の排他単位にしたつもりでも、分離にはなりません。branch名やPR番号などを使うなら、pushとPRで利用できるcontextが違う点を確認し、欠けた値で意図せず同じgroupに集まらないかを見ます。

通常CIをworkflowとrefごとに分ける設計と、複数workflowから同じ配布先を守るため共通groupにする設計は、目的が違います。衝突を避けようとして何でも別groupにすると、守る必要のある共有resourceへ同時に処理することになります。何を直列化したいかを先に決めます。

running取消とpending置換を区別する

Workflow syntaxのconcurrency仕様(新しいタブで開く)では、通常は同groupで一つがrunningになります。既定のqueue singleはpendingも一つなので、新しいrunが来ると、古いpendingがcancelされ置き換わります。cancel-in-progressは、runningも取り消すかを指定する別の条件です。

架空のAがrunning、Bがpendingの間にCが入る例では、既定queueならBがCへ置き換わる可能性があります。runningのAまで止める設定でなければ、Aを走らせたままでもBは消えます。この違いを見ずに「falseなのに取消はbug」と判断しないようにします。

表は横にスクロールできます

保ちたい挙動確認する方針合わない用途
最新変更のCIを優先古いrunの取消を許すか全入力を一件ずつ必ず処理
すべての対象を順に扱うpending queueと容量最新一件へ置換する既定
共有先へ一度に一処理resourceに対応するgroupworkflow名だけで分離
外部処理の完了を守る取消後の照合・再開取消すれば自動rollback

queue maxは無制限保存ではない

現在の公式構文は、queue maxで最大100のpendingを待機させる方法を案内しています。満杯なら追加runはcancelされ、cancel-in-progress trueとの併用はvalidation errorになります。古い「pendingは必ず一件だけ」という説明をすべての設定へ当てはめないようにします。

一方、待機順はconcurrency待ちに入った時点によるため、workflowのdispatch順と完全に一致する業務queueとは考えません。すべての業務入力を厳密な順序で処理する必要があるなら、外部queueや処理状態を含めた設計を別に検討します。queue maxへの変更だけで、欠落・重複・順序をすべて解決したとはしません。

取消済みrunの外部状態を照合する

runのcancelは、外部へ行った書込や配布を取り消す保証ではありません。最後に完了したstep、応答を失った要求、生成された成果物、外部側の対象IDを確認します。状態が不明な作成・送信を、再実行で二重にしないことが必要です。

架空例で、外部への登録は済んだが確認step前にcancelされた場合、未登録として最初から作り直すと重複します。処理IDと外部の現在状態を照合し、未実行・完了・結果不明に分けます。concurrencyの修正と、すでに発生した部分成功の復旧は別の作業として記録します。

小さな条件で方針を検証する

許可された検証では、外部送信を伴わない待機用jobなどで、A running/B pending/C到着を区別して観測します。実業務のdeploymentや通知を大量に起動して試す必要はありません。default single、running取消を有効にした場合、対応するmax設定など、採用する条件だけを確認します。

変更前のgroup式・queue・cancel条件と、採用した設定を保存します。取消の件数が減っただけで成功にせず、必要なrunが処理されたか、待機が際限なく延びていないか、同時処理してはいけないresourceが守られたかを確認します。意図しない並行処理が増えたなら設定を戻し、保留・取消済み対象を処理IDで整理してから再開します。