GithubのHookについてのまとめとソリューション
Githubはpushだったり、pull-requestなりのイベントを通知してくれるHook機構がある。Travisとかもその一環。リポジトリのSettings -> Service Hooksで設定できる。
Hookのイベント設定
各Hookで受け取れるイベントの種類は増やしたり減らしたりすることができる。
例えば、IRC通知の場合だと受け取ることができるイベントは今のところ以下の6種類。
- commit_comment
- issue_comment
- issues
- pull_request
- pull_request_review_comment
- push
その中でデフォルトでONになっているのはpushとpull_requestの2種類。どのHookがどのイベントに対応しているかはhttps://api.github.com/hooksを見れば分かる。
どのようにイベントの追加設定をするかというと、soh335先生のgithub の irc hook で issue も hook してもらうというエントリーに書いてあるが、hook設定のAPIに対してPATCHメソッドでJSONを送りつけるようになっている。
僕としてはAPIのURLを調べたり、どのHookがどのeventに対応しているかとか調べるのがめんどくさかったので、Github::Hooks::Managerというものを書いた。これは上記の操作を行うことができるWebUIを提供するものである。まだGithub止まりである。
インストールするとgithub-hooks-manager-server
というスクリプトがインストールされるので、以下のように起動すればよい。organizationはoptional。
% github-hooks-manager-server --repository='secret-project' --organization='kayac'
こうすると、手元の2299番ポートでサーバーが立ち上がるのでブラウザでアクセスすることでHookのイベント設定が可能になる。
Web Hookでイベントを受け取る
https://api.github.com/hooksを見れば分かるようにWeb Hookは全てのイベントの通知を設定することができる万能Hookである。
適当なHTTPサーバーを立てておけば、そこにリクエストが飛んでくる。payloadというキーにJSONが入っているのでそれをパースして自前でIRCへの通知なりCIの登録なりを行ったりすることができる。
どのイベントがどういうpayloadを送ってくるかを調べるにはhttp://developer.github.com/v3/activity/events/types/を見れば良い。
長らくpayloadからイベントの種類を推測するのが難しいと思っていたのだが、https://github.com/github/github-servicesのソースを眺めていると、実はWeb HookにはリクエストヘッダのX-GitHub-Event
にイベント名が入ってくることがわかった。
で、喜び勇んで、Github::Hooks::Receiverというものを書いたのが今。
package SampleReceiver;
use strict;
use warnings;
use utf8;
use Github::Hooks::Receiver;
on_event push => sub {
my $event = shift;
warn $event->event;
my $payload = $event->payload;
...
};
on_event issue_comment => sub {
...
};
1;
などとやって、
% plackup -ML -e 'SampleReceiver->to_app'
とかで立ち上げれば、簡単にWeb Hookを受け付けることができるようになる。
追記: Github::Hooks::Receiverはインターフェースを大幅に変えてCPANizeしました。
アクセスがフルオープンだとまずいので、IPアドレス制限をかけてやる必要がある。以下にアクセス元のIPが開示されているので適宜制限を書ければよい。
https://help.github.com/articles/what-ip-addresses-does-github-use-that-i-should-whitelist
ちなみに、https://github.com/github/github-servicesは結構カジュアルにp-rを取り込んでくれるようなので、サービスに要望がある場合はp-rを送ってみても良いと思う。