HubotでWebHookのHTTPリクエストを受け取る
Hubotはチャットの投稿を受け取って処理を実行するのに便利ですが、外部からHTTPリクエストを受け取って処理を行うこともできます。
HubotにはExpressが組み込まれており、デフォルトでは8080ポートをlistenします。HubotでHTTPリクエストを処理するには、以下のように robot.router
でルーティング定義を書きます。
module.exports = (robot) -> # /webhookにPOSTされたらログを表示する robot.router.post '/webhook', (req, res) -> console.info req.body res.end()
詳しくはHubotのドキュメントを参照してください。
hubot/scripting.md at master · github/hubot · GitHub
この仕組みを利用すると、外部からWebhookを受け取ってSlackにメッセージを流すといったことが簡単にできます。
ここではGitLabのWebhookを受け取ってみましょう。もちろんGitHubでも同じことができます。
Webhookの設定
GitLabでMerge Requestが作成された場合にWebhookを投げるには、リポジトリの設定画面でWebhookを有効にします。
doc/web_hooks/web_hooks.md | master | GitLab.org / GitLab Community Edition | GitLab
Merge Requestが作成されたり更新されたりすると、指定したURLに以下のJSONがPOSTされます*1。
{ "object_kind": "merge_request", "user": { "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" }, "object_attributes": { "id": 99, "target_branch": "master", "source_branch": "ms-viewport", "source_project_id": 14, "author_id": 51, "assignee_id": 6, "title": "MS-Viewport", "created_at": "2013-12-03T17:23:34Z", "updated_at": "2013-12-03T17:23:34Z", "st_commits": null, "st_diffs": null, "milestone_id": null, "state": "opened", "merge_status": "unchecked", "target_project_id": 14, "iid": 1, "description": "", "source": { "name": "awesome_project", "ssh_url": "ssh://git@example.com/awesome_space/awesome_project.git", "http_url": "http://example.com/awesome_space/awesome_project.git", "web_url": "http://example.com/awesome_space/awesome_project", "visibility_level": 20, "namespace": "awesome_space" }, "target": { "name": "awesome_project", "ssh_url": "ssh://git@example.com/awesome_space/awesome_project.git", "http_url": "http://example.com/awesome_space/awesome_project.git", "web_url": "http://example.com/awesome_space/awesome_project", "visibility_level": 20, "namespace": "awesome_space" }, "last_commit": { "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "message": "fixed readme", "timestamp": "2012-01-03T23:36:29+02:00", "url": "http://example.com/awesome_space/awesome_project/commits/da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "author": { "name": "GitLab dev user", "email": "gitlabdev@dv6700.(none)" } }, "work_in_progress": false, "url": "http://example.com/diaspora/merge_requests/1", "action": "open" } }
Hubotスクリプトの作成
ここではMerge Requestの作成時に通知を絞りたいので、ステータスをチェックします。また、JSONからいい感じに情報を抜き出してメッセージを作ります。
module.exports = (robot) -> robot.router.post '/gitlab-webhook', (req, res) -> if req.body.object_kind == 'merge_request' merge_request = req.body.object_attributes if merge_request.action == 'open' message = """#{merge_request.title}のコードレビューよろしく頼む。 #{merge_request.url}""" robot.send {room: 'bot'}, message res.end()
Hubotを実行して、GitLabでMerge Requestを作成してみましょう。「コードレビューよろしく頼む」というメッセージが通知されれば成功です。
応用編
コードレビューの担当者はチームでランダムに選出してもよいでしょう。
Merge RequestでAssigneeに指定されているた人にメンションを飛ばしたい場合は、JSONの assignee_id
からユーザ名を逆引きする必要があります。ユーザ情報はGitLab APIで簡単に取得できます。詳しくは以下を参照してください。GitHubならユーザ情報も一緒にもらえるんだけどなぁ。
http://doc.gitlab.com/ee/api/users.html
まとめ
Hubotはチャットをlistenするだけでなく、Webhookをlistenするのにも便利です。ここではGitLabのMerge Requestをチャットに通知する方法を紹介しました。さくっとスクリプトを書いて開発環境を快適にしましょう。