🏗️

Github Actions の Workflow と向き合う

2024/06/25に公開2

はじめに

Github Workflow わかんないよ〜〜〜〜!!

皆さんは CI/CD を組んだことがあるでしょうか。
「継続的インテグレーション/継続的デリバリー」と言われるやつです。
CircleCI や GitLab、 Github Actions などなどで使ったことがあるという方も多いと思います。
僕は Github Actions のみですが、しばしば触る機会があります。

さて、初手で嘆いてしまい恐縮なのですが、 CI/CD に関してしばしば悩んでおりまして。
既に解決済みなのですが、今回はその悩みについてしたためた記事になります。

悩み

僕が困っていたのはこの二つです。

  1. concurrency で同時に実行されないよう制御しているはずなのに止まらない
  2. 本番環境へのリリース PR を作った際に、なぜかステージング環境へのデプロイが走ってしまう

concurrency についてはこちら
既定だと同じワークフローを同時に回せるのですが、それを回せないようにするっていうやつですね。

悩み2 の前提条件ですが、develop に push されたらステージング環境に、master に push されたら本番環境にデプロイする、というワークフローを組んでいます。

【悩み1】 同時実行が止まらない

修正前のヤムルファイル

repository_dispatch は CMS の更新で SSG 処理が走るように設定しています。
CMS の更新を連続して行ったり、PR のマージを短期間で行ったりした場合は、先に回っている方が正常にキャンセルされます。
ただ、PR のマージと、CMS の更新を連続して行った場合に、キャンセルされないという問題でした。

concurrency は、ドキュメントからのコピペで指定していたのですが、どうもこれがうまく動いていないようです。
とはいえドキュメントが間違っているなんてこともなく……。
原因を調査した結果、PR をマージして回る Actions と、Webhook 経由で回る Actions とでは github.ref の値が異なっていることに気づきました。

PR をマージすると github.ref = refs/heads/master
Webhook 経由だと github.ref = refs/heads/develop

となっており、それが原因で同時実行が止まらない状態になっていたわけですね。
現在は -${{ github.ref }} の箇所を削除し、 github.workflow だけで concurrency の判断を行うようにしています。

【悩み2】 リリース PR を作るとなぜかステージングへのデプロイが走る

修正前のヤムルファイル

悩み1 は原因がすぐにわかったのでいいものの、こっちは困りました。

ステージングにデプロイするワークフローは上図の通り。
リリースPRを作るだけでは、これで回るはずがないと思っていたのですが……(だって develop に push してないもんね)。
僕が Github Actions の挙動を誤解していたら詳しい人に教えていただきたいです。

というわけで、別の判定方法がないか模索。
結論から言うと、特定ブランチにコードが push されたタイミングではなく、任意の PR がマージされたタイミングで回るように変更しました。

修正後のヤムルファイル

変更点は3箇所。

  1. on.push にしていた判定箇所を on.pull_request に変更
  2. on.pull_request.typesclosed を指定
  3. jobs.build.if に Webhook が発火するか PR がマージされたらという判定を追加

これで無事、本番環境へのリリース PR を作っても、ステージングへのデプロイワークフローが回らなくなりましたとさ。

おわりに

悩み2、解決したけどいまだに謎が残っています。なんでだろ〜。
Github Actions の挙動にお詳しい方からのご意見お待ちしております。

今回みたいなケースにばったり出くわす可能性は低いかもしれませんが、Webhook 経由と PR 経由とでは github.ref が違うっていうのは、どっかのタイミングで役に立つかもな〜と思います。

PR がマージされたとき、という条件に変えておくと、万が一 Github に直接 push されたタイミングでのデプロイが防げるなどの利点もあるような気はします。
とはいえ、直接 push できないようにしておくほうが安全ですね。
最適な使い分けとかあるのか気になるところです。

今回の記事はこのへんで!
それでは〜。

参考

https://docs.github.com/ja/actions/using-workflows/events-that-trigger-workflows#running-your-pull_request-workflow-when-a-pull-request-merges

ファンタラクティブテックブログ

Discussion

rakiraki

repository_dispatch は CMS の更新で SSG 処理が走るように設定しています。

って書いてあるくらいだから、CMSでディスパッチされてるだけじゃないんですかね。。。?
(なので解決策のようなコンディション処理が条件に合えば正しい書き方になる)
コンテキストをちゃんと確認してみたら、別のところや条件から発火させられてるかもしれない?

うずらうずら

コメントありがとうございます!
悩み2 に関してですかね?
ところがこれがCMSの更新をしていないのを確認していても発火してしまうので謎でした……。