GitHub Webhooksのpushイベントで重複しているcommitを判別したい
TL;DR
commitオブジェクトに生えているdistinct
プロパティを見れば良い.
distinct
が0の場合,それは重複しているcommitであることが分かる.
Ref; https://developer.github.com/v3/activity/events/types/#payload-18
本編
さて,GitHubのWebhooksのpushイベントを受け取って,それをIRCや他のチャットツール等にフォワードしたくなるようなことがままあると思います.
これをナイーブに実装しようとすると,pushイベントを受け取って,そのpayloadに乗ってくるcommitsをベロっと舐めてフォワードするような感じになるでしょう.
つまり,
2ac1745 commit3 26cecfa commit2 8ee5552 commit1
というcommit郡がpushされると,これらのcommitの情報がフォワードされるという感じですね.
で,例えばこの場合のpush先がfeatureブランチだったとして,そのfeatureブランチをmasterブランチにmergeするとどうなるかというと,webhookのpushイベントが発火して,merge commitと共に*1 上記のcommitsの情報が再びpayloadに乗ってやって来ることとなります.
このpayloadの情報をすべてフォワードすると,既にフォワードされた内容が再びフォワードされてしまうことになるので具合が悪いことがあります.
これをどう解決するかというと,冒頭に書いたとおりcommitのオブジェクトに生えているdistinct
プロパティを見れば良くて,このプロパティが0の時は重複しているcommit (雑な言い方をすると,過去に1度でもpushイベントのpayloadに乗ったことのあるcommit) で,1の時は重複していないcommitであるということが分かります.
従って,既にフォワードした内容を再度フォワードしたくない場合は,distinct
が1のcommitだけをフォワードすれば良いという事になります.
(Perlのコード例で恐縮ですが,つまりこんな感じです: https://github.com/moznion/App-GitHubWebhooks2Ikachan/blob/621e7ddef9d0d05a1396a8325a436f74de17e30a/lib/App/GitHubWebhooks2Ikachan/Events/Push.pm#L15)
かつてはHead Commitのcommit logを見て,「“Merge”から始まるcommitだから,これはmerge commit!」みたいな野蛮な方法で重複commitの判別を涙ぐましく行なっていたわけですが (しかもこの方法だとFast-Forwardの場合に対応できない!),distinct
を見ればそんな無駄な努力をする必要はありませんでしたよ,という話でした.
*1:Fast-Forwardの時はmerge commitは無いでしょうが