窓を作っては壊していた人のブログ

この謎のブログタイトルの由来を知るものはもういないだろう

GitHub Actionsのon pushでmaster branchだけ処理したい!

GitHub Actionsを使って、PRをmasterへmergeしたらbuildが走ってdeployする、みたいなことをしたかった時にハマった出来事です。 build & deploy周りの話は

【備忘録】Scala で Azure Functions やってみる(deploy編) - 窓を作っては壊していた人のブログ

の件です。

ネタバレ

  • PRのmergeと同時に行っていたブランチの削除がtriggerだった
  • deletedフラグを監視することでブランチの削除由来のアクションを抑制できる

on pushイベントが2回走ってる!

f:id:yamachu_co:20190329022649p:plain
2回走るon push to masterくん

PRをmasterにmergeしたらon pushイベントがどうしたことか2回走っています。 on pushイベント自体はブランチに関係なくcommitがpushされると走るのでその挙動自体には問題はありません。

問題なのはactions/binに実装されているfilter/branchでmasterを指定しただけだと効果がないということです。 というのも走っているactionsのどちらもmasterブランチに紐付いているからです。

なんとかしてmasterへのmergeだけを取り出せないか、やってみました。

案1. on pushイベントのevent.json内のref要素を見てfilter

on pushイベントは2回発火していましたが、GitHub Actionsでfilterなどをする時などに使うevent.jsonの中身は異なっていました。 diffを見ていて気になったのがref要素が違う、ということでした。

ブランチは両方masterではあるのですが、ref要素を見てみると

// PRにしたブランチ名は custom-filter
"ref":"refs/heads/custom-filter"
// こっちがmaster
"ref":"refs/heads/master"

の様な違いがあります。

であればこの要素を見てfilterかければ良さそうです。 ということでやってみたのが以下のPRです。

Custom filter by yamachu · Pull Request #9 · yamachu/play-actions · GitHub

中身としては actions/bin で使われているfilter系のスクリプトほぼそのままです。 外部からどの要素を使うか流し込めるようになっています。

action "filter head" {
  uses = "actions/bin/filter@master"
  runs = "/github/workspace/.github/custom-filter.sh"
  args = "refs/heads/master"
  env = {
    CUSTOM_JQ_FILTER = ".ref"
  }
}

これでon pushが2回走ろうがmasterのみをハンドリングできるようになりました。

案2. on pushイベントのevent.json内のdeleted要素を見てfilter

案1で満足していましたが、結局なぜ2回走っているのかはわかりませんでした。 そんな中

このツイートに対してリプライが飛んできて、どうもブランチを消したタイミングで2個目が走っているとの情報をいただきました。 情報非常に感謝です。 実際にmergeした後にブランチを削除しないと、確かに1つしかon pushイベントは飛んでいないのです。 完全に盲点だった………

え、ドキュメントに書いてあったっけ、と思い公式ドキュメントを見てみると

developer.github.com

………あまりそういう風には読み取れ…ないんだけど…自分の英語能力がアレなのかな…みたいになってしまいました。

ともかくそういうものである、ということにして進めていきます。

案1の時と同じ様にmergeのタイミングで取得できたevent.jsonと削除タイミングで取得できたevent.jsonを比較してみます。 すると

// 削除した時
"deleted":true
// mergeした時
"deleted":false

ビンゴです、完全に理解した。

ということで書き直してみます。

Update main.workflow by yamachu · Pull Request #10 · yamachu/play-actions · GitHub

action "filter not deleted event" {
  uses = "actions/bin/filter@master"
  runs = "/github/workspace/.github/custom-filter.sh"
  args = "false"
  env = {
    CUSTOM_JQ_FILTER = ".deleted"
  }
}

これで正攻法で戦えている気がします。

結局on pushでmaster branchのみを引っ張るには

  • filterでbranch masterを行う
  • "deleted": falseなものを通す

この2つをWorkflowに入れることで可能になりそうです。

今は外側からどの要素を取得するかみたいなスクリプトを自分で書いて入れていますが

github.com

リポジトリを見てみたらPRが上がっているようです。 mergeされるともう少し楽になりそうですね。

良きGitHub Actionsライフを!