GitHub Actions "concurrency" とは

CI安定化

最近、RowicyのCIを少し安定させるための修正を行った

pnpmのバージョンを固定し、pnpm installを--frozen-lockfileするのが目的

付加的に、concurrencyを追加した

.github/workflows/test.yml
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
...

concurrencyとはなんだろか

concurrencyとは

GitHub Actionsでは、同じブランチへの複数pushするとCIインスタンスはその度に起動し、各々のタイミングで開始し完了まで走る

しかしlintやテストは最新コミットのCI結果を見れば十分で
古いJobを完了まで走らせるよりはキャンセルしちゃったほうがいい

Job ───────×
Job ▶ ─────────────────────

これにはconcurrencyキーが使える

concurrency:
group: test
cancel-in-progress: true

groupの指定

並行制御グループをつくる

concurrency:
group: hoge

と書けば、これがグルーピング指定

名前は何でもいい

しかしこうすると、Jobはすべてhogeグループになる
コミット先ブランチ、ワークフロー関係なく

なので変数でわける

name: 'Test'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

これでTestワークフローならTest-refs/heads/<branch>というgroup名になり
他ブランチのCIがJobをキャンセルすることはない

cancel-in-progress

キャンセル制御をグループと合わせて宣言

グループ内で新しいJobがきたら、今走っているJobはどうするかを宣言

cancel-in-progress: true

Job ───────×
Job ▶ ───────────────────── ✓

cancel-in-progress: false

Job ──────────────── ✓
Job ----wait--- ▶ ───────────────────── ✓
設定挙動ユースケース
cancel-in-progress: true中断最新のコミットのみ実行でいい- PR 毎のテスト
- lint / 単体テスト
- ビルド確認
cancel-in-progress: false中断せずに、新しい実行を待機途中でキャンセルされると困る- 本番デプロイ
- データ移行ジョブ
- 夜間バッチ処理

待機は1件のみ

cancel-in-progress: falseのとき
待機できるのは最新の1件のみ

ここでqueue: maxつけると最大100件まで待機させられる

concurrency:
group: deploy
cancel-in-progress: false
queue: max

今回は必要がなかったのでつけてない

WorkflowにもJobにも設定できる

GitHub ActionsではWorkflowにJobが含まれる

Workflow
└── jobs
└── <job_name>
├── runs-on
└── steps

並行制御のグルーピングはWorkflow単位とJob単位でできる
concurrencyの階層を変えるだけ

  • Workflow
name: 'Test'
concurrency:
group: hoge
cancel-in-progress: true
jobs:
...
  • Job
name: 'Test'
...
jobs:
test:
concurrency:
group: hoge
cancel-in-progress: true

GitLab CI

GitLab CIにも同様のキャンセル機能があるが少し制御が異なる

.gitlab-ci.yml
workflow:
auto_cancel:
on_new_commit: interruptible #キャンセル判断をワークフローで指定
stages:
- test
unit_test:
interruptible: true # 割り込みOK
stage: test
script:
- npm run test
integration_test:
interruptible: true # 割り込みOK
stage: test
script:
- npm run test:e2e

Githubとちがい、ワークフローレベルでワークフローのキャンセル判断を指定
Job側でキャンセル可否を宣言する

キャンセル判断とはon_new_commitの値だが以下が指定できる

設定値動作主なユースケース
interruptible割り込み可能OKと言ってるJobあったらキャンセルしてテストやビルドは途中で止める
conservative割り込み可能NGのJobあったら最後まで完了させて不整合を極力避けたい
noneキャンセル判断なし無設定と同じ

これに対してJob側でinterruptibleを指定
キャンセルされて構わないかどうかを指示する

ここでconservativeを指定するとGitHubの cancel-in-progress: false のように待機列に入るかというとそうではない
Jobはキャンセルされず完了まで各々走るだけ
on_new_commitの指示に待機列は関係ない

resource_group

Jobの同時実行数制御はresource_groupで行う

deploy_production:
stage: deploy
script:
- ./deploy.sh
resource_group: production

resource_groupが同じJobは直列に実行される
deploy_productionジョブが複数発生しても順番に実行される

Githubは並行制御用グルーピングだったが、Gitlabは直列実行用グルーピングであることに注意
キューと同等

GithubとGitlabのJob制御の違い

GitHubとGitLabでは並行制御とグルーピングの考え方が違う

GitHubはWorkflow, Job単位でグルーピング、そこでキャンセルか、直列実行

GitLabはWorkflowでキャンセル判断を示すがキャンセルの意思表示はJob側で 直列実行はまた別でJob側でグルーピング指定

こんな感じに分けられる

RiiiM

Author: RiiiM

Backend Developer

Share

Link is copied.