あけましておめでとうございます。morishitaです。
世間はコロナで大変な状況ですが、早くいこーよでお出かけ先を探して思う存分遊びに行けるようになればいいのになぁと思いながら新年を迎えました。本年もよろしくおねがいします。
さて、今回は小ネタを1つ。
以前、Pronto を Github Action で実行するというエントリを投稿しました。
アクトインディの開発では Github のプルリクエスト上で Pronto を実行して、Rubocop によるチェックを行い、違反があれば次のようにコメントで指摘されるというワークフローを使っています。
プルリクエストに Push するたびに実行され便利なのですが、毎回の Push で実行されると不便な場合もあります。
例えば次のようなケースです。
- 違反があるのはわかっていて、後でまとめて修正しようと思ってたのに Push したら指摘コメントがたくさんついてしまった
- UI の微調整で修正しては細かく Push して、たくさん実行してしまい無駄に Github Action の無料枠を食いつぶしてしまう。
(いこーよは作業ブランチ毎にステージング環境が作成され、Push すると自動的にデプロイされます。ディレクターチェックで UI の仕上がりをステージングで確認しながら修正していくときに起こりがちです)
実行したいときに実行を指示する方法としてはコマンドコメントを使う方法があります。
例えば、Dependabot が作ったプルリクエストに @dependabot rebase
とコメントすると Rebase するようなやつですね。同じようにワークフローも制御できそうなのですが、これだとどんなコマンドがあるか覚える必要があったり、タイピングが若干面倒です。
で、アクトインディでは特定のラベルの有無によって実行を制御しています。
具体的には Pronto
というラベルを付けているときだけ実行されるようにProntoを実行するワークフローを使っています。
Github workflow のトリガーイベント
ワークフローには実行トリガーとなるイベントを定義する必要があります。
いろんなイベントがありますが1、プルリクエスト上での操作をトリガーにしたい場合には、pull_request
イベントを使います。
そして、pull_request
イベントにはいくつかのアクションが定義され、どんな操作でトリガーされるのか指定できるようになっています2。
例えば、次のように定義するとプルリクエストを作ったときと、Push したとき、ラベルを付けたときにトリガーされます。
name: Pronto on: pull_request: types: [opened, synchronize, labeled] jobs: pronto: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - uses: HeRoMo/pronto-action@v1.10.0 with: github_token: ${{ secrets.GITHUB_TOKEN }}
で、これだと Push するたびに実行されてしまいますし、どんなラベルをつけたときにも実行されてしまいます。
コンテキストと式
さて、ここからが本エントリの本題です。
ワークフローの実行を制御する方法はトリガーイベントだけではありません。
イベントの中身を見て、実行するかどうかを判定できるコンテキストと式があります。
コンテキストとはワークフローの実行、ランナーの環境、ジョブ、ステップに関する情報にアクセスできるオブジェクトです。
いくつかの種類のコンテキストがあるのですが、その中で、github
コンテキストにはトリガーしたイベントの詳細情報が入っています。
pull_request
イベントの場合、github.event
に Webhook の pull_request
イベントのペイロードと同等の情報が含まれています。
github.event
の中にはどんなラベルを付けたのか? あるいはどんなラベルが付いているのか? という情報が含まれているのでそれらを使って実行を制御できます。
更に、コンテキストとリテラル、演算子を組み合わせて式を作ることもできます。
例えば、次の条件を満たす場合のみ実行したいとします。
- プルリクエストに
Pronto
というラベルを付けたとき Pronto
というラベルがついている状態で、 Push したとき
これは次のように if
条件に式を与えることで実現できます。
name: Pronto on: pull_request: types: [opened, synchronize, labeled] jobs: pronto: runs-on: ubuntu-latest # ↓ 追加 if: | ((github.event.action == 'labeled') && (github.event.label.name == 'Pronto')) || ((github.event.action == 'synchronize') && contains(github.event.pull_request.labels.*.name, 'Pronto') # ↑ 追加 steps: - uses: actions/checkout@v1 - uses: HeRoMo/pronto-action@v1.10.0 with: github_token: ${{ secrets.GITHUB_TOKEN }}
もう少し説明すると if
条件の中で使っている contains
はワークフロー内で使えるよう定義されている関数です。第一引数で渡された文字列や配列の中に、第二引数の文字列が含まれれば true
となります。
第一引数の github.event.pull_request.labels.*.name
というのは github
コンテキストからプルリクエストについたラベル名を配列で取り出す指定となります。
こうすることで、ラベルの付与やラベルの有無によりワークフローの実行を制御できました。
まとめ
- Github ワークフローをトリガーするイベントについて説明しました。
- イベントの情報を取得できるコンテキストについて紹介しました。
- 具体例として特定のラベルの有無でワークフローの実行を制御する例を紹介しました。
ワークフローには他にもコンテキストや関数がありますし、ワークフローコマンドなんてものもあったりするので工夫次第で使い方が広がると思います。
参考
- GitHub Actionsのワークフロー構文 - GitHub Docs
- GitHub Actions のコンテキストおよび式の構文 - GitHub Docs
- ワークフローをトリガーするイベント - GitHub Docs
- webhook イベントとペイロード
最後に
アクトインディではエンジニアを募集しています。 actindi.net