Hubot | 自作Script | gitlab_sample.coffee - GitLab - Hubot - Kandan の連携を検証するサンプル

# Hubot | 自作Script | gitlab_sample.coffee - GitLab - Hubot - Kandan の連携を検証するサンプル

## 概要
GitLab - Hubot - Kandan の連携を検証するサンプル script を作成します。
GitLab の Web hooks と、 Hubot の Web サーバー機能を利用します。

Hubot はデフォルトで 8080 ポートで起動していて、例えば

http//hubot_url:8080/hubot/version

にアクセスすると、

~~~
2.4.7
~~~

などのバージョンが返却されます。

## 仕様
### filename
gitlab_sample.coffee

### Hubot Webサーバーの受付URL
 http://hubot_url:8080/gitlab/hook

※hubot_urlはあなたのHubotサーバーのURLに置き換えてください

### 仕様補足
GitLab の Web Hook が返却してくる json のフォーマットについては下記参照
https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/web_hooks/web_hooks.md

## ソースコード

coffee:gitlab_sample.coffee

~~~coffeescript
module.exports = (robot) ->
  say = (message) ->
    # hubot-kandan が room を id 指定する前提になっていてつらい。
    # rails console とかでDBを除くか、 log から id を確認する必要がある。
    # いちいちサーバーに入りたくなかったら、ブラウザ付属の開発ツールなどで HTML の中を確認するのが早いか？
    # ※ブラウザの「ページのソースの表示」機能だと、ajaxとかで生成されたHTMLが確認できない
    # name にして欲しい。
    user = {
      room :
        id : 2
    }

    robot.send user, message

  issue = (json) ->
    say "GitLab issue"
    say "json['object_attributes']['title'] = #{json['object_attributes']['title']}"
    say "json['object_attributes']['description'] = #{json['object_attributes']['description']}"

  merge_request = (json) ->
    say "GitLab merge_request"
    say "json['object_attributes']['target_branch'] = #{json['object_attributes']['target_branch']}"
    say "json['object_attributes']['title'] = #{json['object_attributes']['title']}"
    say "json['object_attributes']['state'] = #{json['object_attributes']['state']}"

  push = (json) ->
    say "GitLab push"
    say "json['repository.name'] = #{json['repository']['name']}"
    say "json['commits'][0]['message'] = #{json['commits'][0]['message']}"

  robot.router.post "/gitlab/hook", (req, res) ->
    json  = req.body
    # 全ての json が持つ共通の属性がないので object_kind で判断
    # push だけは object_kind を持っていないので擬似的に "push " を設定
    #
    # issue         => GitLabのjson object_kind: issue
    # merge_request => GitLabのjson object_kind: merge_request
    # push          => GitLabのjson object_kind: ない
    event = json['object_kind'] || 'push'

    switch event
      when "issue" then issue json
      when "merge_request" then merge_request json
      when "push" then push json

    res.send 200
~~~

## 前提
* Kandan 1.1
* Hubot 2.4.7
* 対象リポジトリは自作 gem の gottani を GitLabに保存したもの

https://github.com/tbpgr/gottani

これをそのまま GitLab に放り込んでます。

## 手順
### gitlab_sample.coffee を配置

gitlab_sample.coffee を hubot サーバーの scripts 配下に保存する。

### Hubot の再起動
### ブラウザで GitLab の Web hooks を追加する

URL は http://kandan_path:8080/gitlab/hook に設定。
gitlab/hook の部分は gitlab_sample.coffee の

~~~coffeescript
robot.router.post "/gitlab/hook", (req, res) ->
~~~

の部分に対応。

![web_hooks_setting.png](https://qiita-image-store.s3.amazonaws.com/0/43480/f65a3958-80b8-7a21-e0f7-f8105451e6ef.png)

## 確認
### push イベント
* GitLab へ push します

~~~bash
$ git commit -m "test for gitlab-kandan-hubot test"
$ git push origin master
~~~

* Kandan で Hubot の反応を確認します

![push1.png](https://qiita-image-store.s3.amazonaws.com/0/43480/7f0ccf5d-d7ae-7d54-afb0-35b6ee17ad6e.png)

### issue イベント
* GitLab へ issue を 追加します


* Kandan で Hubot の反応を確認します

※出力メッセージの順序が入れ替わってしまっていますが、一応ちゃんと動いてます

![issue2.png](https://qiita-image-store.s3.amazonaws.com/0/43480/98115157-8b07-0460-555f-87cbbadb54c9.png)

### merge_request イベント

* まずはローカル環境でトピックブランチを作って、 GitLab サーバーへ push します

~~~
$ git checkout -b test_for_gitlab_kandan_hubot
Switched to a new branch 'test_for_gitlab_kandan_hubot'
$ echo hoge > test_for_gitlab_kandan_hubot.txt
$ git add test_for_gitlab_kandan_hubot.txt
$ git commit -m "test_for_gitlab_kandan_hubot"
[test_for_gitlab_kandan_hubot 813615d] test_for_gitlab_kandan_hubot
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 test_for_gitlab_kandan_hubot.txt
$ git push origin test_for_gitlab_kandan_hubot
~~~

* GitLab で Merge Request を行います

![merge_request1.png](https://qiita-image-store.s3.amazonaws.com/0/43480/1543fee5-406a-baee-46c7-330f57bf4bb4.png)

![merge_request2.png](https://qiita-image-store.s3.amazonaws.com/0/43480/f99f75be-5a67-269d-e80d-29540e6e1428.png)

* Kandan で Hubot の反応を確認します

![merge_request3.png](https://qiita-image-store.s3.amazonaws.com/0/43480/735678b2-e715-fd46-3a45-dd6fb5c1448b.png)

## おまけ：KandanのChannel id を確認する方法
hubot-kandan で Web hook を利用して任意の Channel（Room） にメッセージを送る場合、
Channel の id が必要です。
Channel の id は画面に表示されていないので何らかの手を打つ必要があります。

### 方法1
ブラウザの開発ツールを利用してHTMLを確認する。
下記の画像の赤丸で囲んだ部分を見ることで、チャネルのタブの並び順に応じた id を確認できます。
channels-1 なら 1 が id 。

![kandan_channel_id.png](https://qiita-image-store.s3.amazonaws.com/0/43480/e76fceb7-c306-fb4e-1b90-aaa69d8ff576.png)

### 方法2
Kandan Server で rails console を起動して Channel.all で id を確認する

~~~
[1] pry(main)> Channel.all
  Channel Load (0.1ms)  SELECT "channels".* FROM "channels"
=> [#<Channel id: 1, name: "Lobby", created_at: "2014-08-08 22:33:18", updated_at: "2014-08-08 22:33:18">,
 #<Channel id: 2, name: "Test", created_at: "2014-08-08 22:55:09", updated_at: "2014-08-08 22:55:09">,
 #<Channel id: 4, name: "Test2", created_at: "2014-08-11 23:41:23", updated_at: "2014-08-11 23:41:23">,
 #<Channel id: 6, name: "Tes3", created_at: "2014-08-11 23:42:50", updated_at: "2014-08-11 23:42:50">,
 #<Channel id: 7, name: "Test4", created_at: "2014-08-11 23:44:32", updated_at: "2014-08-11 23:44:32">]
~~~

### 方法3
Kandan Server で log を確認しながら ブラウザから Kanban で id 取得したい Channel を操作する。
※ただし、ログレベルの設定次第

~~~
$ ~/kandan$ tail -f log/thin.log
Processing by AttachmentsController#index as JSON
  Parameters: {"channel_id"=>"2"}
  User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 3 LIMIT 1
  Channel Load (0.1ms)  SELECT "channels".* FROM "channels" WHERE "channels"."id" = ? LIMIT 1  [["id", "2"]]
  Attachment Load (0.1ms)  SELECT "attachments".* FROM "attachments" WHERE "attachments"."channel_id" = 2 ORDER BY created_at DESC
Completed 200 OK in 2ms (Views: 0.1ms | ActiveRecord: 0.3ms)
~~~

### 方法4
http://kandan_url:3000/channels.json を取得して、目当ての id を探す

こんな感じの json が返ってきます。
Test Channelの id が欲しければ、下記を確認して id が 2 であることが分かります。

~~~
[
{"id":1,"name":"Lobby","created_at":"2014-08-08T23:33:18Z","updated_at":"2014-08-08T23:33:18Z","activities":[
{"id":843,"content":hoge,"channel_id":1,"user_id":1,"action":"disconnect","created_at":"2014-08-14T23:00:43Z","updated_at":"2014-08-14T23:00:43Z","user":{ユーザー情報（略）}},
：
： Channel 1 のチャット情報
：
{"id":900,"content":hige,"channel_id":1,"user_id":1,"action":"disconnect","created_at":"2014-08-14T23:00:43Z","updated_at":"2014-08-14T23:00:43Z","user":{"user":{ユーザー情報（略）}}},
{"id":2,"name":"Test","created_at":"2014-08-08T23:55:09Z","updated_at":"2014-08-08T23:55:09Z","activities":[
：
]
~~~

## 参照
GitLab の Web Hook が返却してくる json のフォーマットについては下記参照
https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/web_hooks/web_hooks.md

## 補足
今のところ、 npm で公開したりする予定はないので適当にGitHubに突っ込んでおきます。
https://github.com/tbpgr/hubot_scripts