その手の平は尻もつかめるさ

ギジュツ的な事をメーンで書く予定です

特定のユーザーのイベントによるGitHub ActionsのActionを保留状態にしておき、後で手動実行できるようにする

dependabotだとかrenovateだとかを使ってライブラリのバージョンアップのpull requestを自動的に送ってもらう、というような機構を利用されている方が多いと思います。
常にこれらのpull requestに目を光らせておいて常に取り込み続けるというのが理想的な形・そうあるべきだとは思うのですが、ふと気を抜くとバージョンアップのpull requestが溜まっていき、pull request自身も改訂に改訂を重ねている......みたいなことが起きがちではないでしょうか。

そういった折、誰も結果を見もしないCI (i.e. GitHub Actions) だけが回り続けているのを見て「このチェックは『ライブラリアップグレード業』をやる時に手動で回せばコンピューティングリソースの削減になるのでは?」と思い、それを試したという次第です。

この記事では例として、renovateからのpull requestに対して自動でActionを回す (つまり一般的な "CI" ) のではなくレビュアーの承認が降りた際に回すようにしてみます。

Environmentを作る

RepositoryにGitHubのEnvironmentを作ります。例えば、"renovate" という名前のEnvironmentを作ってみることとします。

"Required reviewers" にチェックを入れて、renovateからのpull requestに対するActionの実行を承認するユーザーあるいはチームを指定します。
この用途の場合は "Deployment branches" は "All Branches" で適当かと思いますが、都度環境に合わせると良いでしょう。

Action定義を書く

ここは普通にGitHub Actionsの定義を書きましょう。
重要な点は、普段 (つまりrenovate以外が) 実行するActionとrenovateが実行するActionをそれぞれ用意するということです。

普段実行するActionの定義については

...
jobs:
  your-action:
    if: ${{ github.actor != 'renovate[bot]' }}
...

と書いておき、renovateが実行するActionの定義には

jobs:
  your-action:
    if: ${{ github.actor == 'renovate[bot]' }}
    environment: renovate

と書いておくことで、renovate以外の時は普通に自動実行され、renovateの時は environment: renovate が有効になり承認が降りないとActionが実行されないこととなります。

このyaml中のifにどういった条件が書けるかについては以下のドキュメントを参照すると良いでしょう。

今回はactor (イベントの主体) の名前によって判断するという素朴な方法を採りましたが、その他のcontextを使うと色々ハイテクなことができそうです。例えばrenovateに限らず「botの時」はこういうふうにするとか。

あと、手元のyamlではrenovateが実行するActionのイベントに on push で指定しているのですが、これは on pull_request で十分なのかもしれない。

こんな感じになる

この場合 "e2e-test.yml" というのが普段走るActionのyaml、 "e2e-test-for-renovate.yml" がrenovateの時に走らせるActionのyamlとなっています。
これはrenovateによって作られたpull requestなのですが、「普段走るAction」がスキップされており「renovateの時に走らせるAction」がpending状態になっていることがわかると思います。

この時、 "This branch is waiting to be deployed" からメニューをポチポチ選んでゆくと

このような状況になるので、Review Deploymentsから承認することでActionがマニュアル実行されるという寸法です。あとは実行結果を見て、マージするかどうかを精査しましょう!

課題

task定義を複数用意するのダサくない・メンテ面倒じゃない?

それは本当にそう! 何か良い方法があると良いのですが......

[追記]

あと、composite actionを使えば良いのではないか、というアドバイスもありました: Creating a composite action - GitHub Docs

知見ありがとうございます。

[追記ここまで]


承認できるReviewersを6人までしか指定できないのは少ないし、何より権威主義的だ!!!

個人だけでなくチームを指定できるのでそこである程度カバーできるのではないでしょうか。

依存アップデートのpull requestのActionが自動で完了してないと、更にマージするモチベーション下がらない?

そうかも......なのでモチベーション高く常に依存アップデートのpull requestを見てるよ・マージしてるよ、という環境では不要だと思います。

一方、ある程度まとめて依存のアップデートをしているような環境だと都度都度Actionが回っている必要が無い、ということでリソースを節約できるのではないか、というのがこの仕組みの狙いです。

とはいえ、この方法を運用しはじめてから日が浅いので今後何か良い点・悪い点が見えてくる可能性があります。どうなることやら。