Slack×Hubot×GitLabでレビューを効率化しよう

この記事はSlack Advent Calendar 2014 - Qiitaの22日目の記事です。

内容

チーム内でのちょっとした開発にはGitLabを使っているのですが、MargeRequest(以下MR)を投げた時にレビューを効率化するためにの方法を説明したいと思います。

Slack導入以前

別にMRが発生したらメールを投げればいいのですが、メールだとすぐに見ないことも多いのも事実。 そこで、Slackを入れる前はMRが起こるたびにYoを送ってMRが飛んだよーということを気づかせるようにしていました。

ちょうどYoが無駄に流行っている時期でもあったし、Yo APIもあったのでしばらくこれでしのいでいました。

そのとき作ったのがこれです。

Flask-yo

しかし、最初のうちは楽しくてみんな反応していたのですがだんだんと反応しなくなりました。結局Push型でみんなにYoが行くので、誰かレビューするだろ?ってなっちゃうんですよね。

Slackの導入

チーム内のコニュニケーションを円滑にするためにSlackを導入しました。 Slackいいですよね。チーム内のコニュニケーションがかなり活性化されたと思います。 業務中はだいたいのメンバーはSlackに常駐しているのでGitLabのMRもこっちに流そうと思いました。

やりたいこととしては以下となります。

  • MRが飛んだらMRのタイトルと内容とリンクを特定のチャネルに通知
  • 合わせて、@でランダムでレビュワーを割り当てる
    Slackの通知をスマートフォンアプリでも

これによりMRがいつ飛んだのか、誰がレビューするべきかを明確にします。

導入準備

まず今回試しているGitLabのバージョンは「GitLab 7.4.3」となります。

  1. SlackにHubot Integration
    まずはこれが必要です。ちょうどちょっと前にSlack APIのアップデートがあり以前とちょっと方法が変わっています。 すばらしいことにSlack Advent Calendar 2014の4日目にKeitaMoromizatoさんがこの新しいIntegrationの導入方法の記事を書いてくれていますので詳細はこちらを参照して下さい。
    SlackのHubot Integrationが知らぬ間にアップデートされてた
    また、hubot-slackもバージョンアップされておりこれによりプライベートチャネルにもHunotが常駐できるようになりました!素晴らしい!これが出るまではXMPP経由でHubotの設定をしなくてはならず若干面倒くさかったのですよね。。。

  2. Hubotの用意
    様々な記事があるようにHerokuに立てるのが一番楽だと思います。これも参考になる記事がいくつもあるので以下をご参照下さい。他にもググれば参考になる情報がたくさんでてきます。
    slackにHubotを導入(Heroku経由)

  3. GitLabの設定
    スクリプトを作成する前にGitLab側の設定を行いましょう。GitLabにはWebHookの機能がありますのでこれを使用します。
    設定したいプロジェクトの「Setting」→「WebHook」を選択します。

f:id:braitom:20141222133302p:plain

ここを見てもらえると分かるのですが、GitLabでは以下のタイミングでWebHookを使うことができます。
・Push events
・Tag push events
・Issues events
・Merge Request event

今回はMRだけ取りたいので「Merge Request event」にチェックを入れます。そしてURLにはリクエストを送る先のURL(Hubotが動いているURL)を入力して「Add Web Hook」を押します。
もちろんMR以外のイベントもHookして取り回したいという場合はスクリプト側でハンドリングしてあげればOKです。

スクリプトの作成

まずスクリプトの全体は以下となります。これをHubotのscriptsフォルダにおけばOKです。

hubot-gitlab mearge request review

特に難しいことはしていません。ポイントを解説すると、

Slack APIを直接たたいている

hubot-slackを使えば楽ちんなのですがHubotからSlackへ投稿すると@(メンション)と#(チャネル)はデフォルトでリンクとなりません。 こんな感じにただのテキストとして扱われてしまいます。これだとメンション扱いにならないので気付かずにスルーしてしまいそうですよね。

f:id:braitom:20141222134330p:plain

この辺のSlackの仕様は以下のリンク先で確認して下さい。

Slack API Message Formatting

今回は@できちんとメンションとして通知したいという目的がありますのでこの方法でいきました。

4行目のBASE_URLでSlack API Tokenを設定しています。

BASE_URL = 'https://slack.com/api/chat.postMessage?token=xxxx-xxxxxxxxx-xxxxxxxxxx-xxxxxxxxx-xxxxxxx' #replace your Slack API key!

44行目のurlの一番最後に&link_names=1を付与しています。これにより@がきちんとメンションとして機能するようになります。

url = BASE_URL + 'channel=' + channel + '&text=' + encodeURIComponent(message) + '&link_names=1'

レビュアーのランダム化

Hubotのrandom関数を使うようにしています。

random = require('hubot').Response::random

使い方は簡単です。36行目です。

assignee = random members

これでassigneeに6行目のmembersで定義したメンバーがランダムに入ってきます。

GitLabからのHook先

hubotにはrouterの機能があるので指定したURLにPostが来たときの動作を書くことができます。14行目ですね。

robot.router.post '/hubot/gitlab', (req, res) ->

これでhttp://HubotのURL/hubot/gitlabにPostが来た時にこの関数が呼ばれます。 つまりこのURLを上で述べたGitLabのWebHook設定時のURLに指定するわけです。

GitLabからのHook内容をハンドリングする

これは21行目〜24行目で行っています。GitLabが実際にどのようなJsonを送ってくるかは以下を参照して下さい。

GitLab Web hooks

※このJsonの内容はGitLabのバージョンによって変わってきますのでお使いのGitLabのバージョンのドキュメントをきちんと確認して下さい。

Pushでも反応させたい、MRクローズ時も反応させたい等の機能はここを書き換えることになります。

まとめ

この状態でMRが飛ぶと以下のようにメンション付きでbotが教えてくれます。

f:id:braitom:20141222134853p:plain

この方法でMRをレビューすることで前より効率がよくなった気がします。あと、おみくじ的な感じでなかなか面白いです。(また俺が担当かよー!みたいなこともありますが。)

今後もいろいろ改善していきたいですね。よいSlackライフを!