はじめに
弊社ではGitのホスティングサービスとしてBitbucketを、チャットとしてHipChatを、レビューツールとしてReviewBoardを使用しています。
今回は、レビュアーを自動でガチャるレビューガチャを上記3システムのAPIを駆使して作成したので紹介します。
なお、仕様が弊社向けにかなり特殊になっているため特にコードの公開などは行いません。
API/batchはLaravel5で,hubotはcoffescriptで作成しています。
前提
Bitbucket
Bitbucketのユーザはマージ権限を持つGeneralとマージ権限を持たないRookieの2種類どちらかの権限を所持しています。また、Bitbucketユーザにはエンジニア以外にデザイナーも存在します。
HipChat
HipChatにはエンジア以外にデザイナーや企画のメンバーもいます。
ReviewBoard
レビューボードのユーザは、自分が所属するグループに分類されています。
仕様
エンジニアがhipchatでレビュアーを選択したいとなったときに、
@hubot reviewerとすることで、ランダムにレビュアーが2人選ばれることとします。
ただし、レビュアーは以下の条件を満たす人が選ばれることとします。
・自分が所属するグループと所属しないグループから1人ずつ選択する
・自分自身は自分のレビューのレビュアーに選ばれない
・BitbucketのRookie権限のユーザはレビュアーに選ばれない
・非エンジニアはレビュアーに選ばれない
また、レビュアーに選ばれた時にはメンション付きで呼ばれることとします。
各サービスで必要な情報
hipchat
要素 | 説明 |
---|---|
user_name | hubotの引数としてuser_nameが与えられるため |
mention_name | hipchatでメンション付きで呼びたいため。 |
各サービスを示す一意のIDとしたいため | |
hipchat_id | hipchat上のid |
hipchat_private_api_url | hipchatで個人のユーザ情報を取得するapiURL |
reviewboard
要素 | 説明 |
---|---|
group | そのユーザが属するグループ判断のため |
bitbucket
要素 | 説明 |
---|---|
role | そのユーザがgeneralかrookieか |
詳細設計
前処理/実処理をやる都合上batch処理で前処理を行い実処理はapiを1つ作成して行う
前処理
- メンションネームとそのユーザのid,メールアドレス,user_nameをhipchatから取得
- ユーザのグループ情報をReviewboardから取得
- ユーザのroleをbitbucketから取得
実処理
- hipchatでメンションをつけて飛ばすとそのユーザ名が引数として渡される(User Name)
- coffescript側で引数をパラメータとして与えてapiを叩く
ex:bot-api.example.com/user_name - 出力
の形をとっています。
(画像を貼る)
各種情報取得API
hipchat API
userAPI
http://api.hipchat.com/v2/user?auth_token=
auth_tokenは以下の記事で紹介したように取得する
http://qiita.com/takky/items/51f8b2942437c9897ee1
これでuserの基本的な情報を取得できる。
https://www.hipchat.com/docs/apiv2/method/get_all_users/
なお返却情報はjsonで以下のような形式になる
items: [
{
id: 12345678,
links: {
self: "https://api.hipchat.com/v2/user/12345678"
},
mention_name: "TT",
name: "TANAKA TARO"
},
{
id: 12346586,
links: {
self: "https://api.hipchat.com/v2/user/12346586"
},
mention_name: "D",
name: "Yamada Taro"
},
https://api.hipchat.com/v2/user/12345678?auth_token=
上記APIでユーザの個別情報を取得できる。
{
created: "2013-04-11T02:13:25+00:00",
email: "t_tanaka@email-address.com",
group: {
id: 76929,
links: {
self: "https://api.hipchat.com/v2/group/{group_id}"
},
name: "{Team Name}"
},
これで全ユーザのメンションネーム/メールアドレス/ユーザーネームが取得できる
ReviewboardAPI
http://{reviewboard_server}/review/api/groups/{group}/users/
https://www.reviewboard.org/docs/manual/2.5/webapi/2.0/resources/review-group-user-list/
reviewboardは自社サーバにあるため、自社サーバのアドレスを指定している
reviewboardのAPIはデフォルトでXMLを返却するのでContent-Typeはapplication/jsonにする必要がある
jsonを指定した場合の返却情報は以下のようになる
{"username": "tanaka_taro", "first_name": "tanaka_taro", "last_name": "", "links":{"watched":{"href": "http://{reviewboard_server}/review/api/users/tanaka_taro/watched/",…},
bitbucketAPI
https://api.bitbucket.org/1.0/groups/{team_bitbucket_admin_user}
bitbucketAPIは id/passが必要なので、
CURLOPT_USERPDで id:passで送ること。
jsonでteam_adminの下にいるroleとそのroleに紐づくユーザが取得可能
"name": "general",
"permission": "write",
"email_forwarding_disabled": null,
"auto_add": true,
"members": [
{
"username": "mem-t_tanaka",
"first_name": "TANAKA",
"last_name": "TARO",
"display_name": "TANAKA TARO",
"avatar": "{avartor_url}",
"resource_uri": "/1.0/users/mem-t_tanaka",
"is_team": false
},
hubot実装
基本的に
robot.respond /select reviewer/i, (msg)->
user = msg.message.user.name
tmp = user.split(" ")
user = tmp[0] + "_" + tmp[1]
url = "http://bot-api.com/reviewers/#{user}"
のようにAPIを叩いて、返却結果を出力するだけ。
ここで、ポイントは@hubot select reviewerすると、
Tanaka Taro
のようにhipchatに登録したユーザ名が変数userに入る点。
apiを叩く際にスペースが入っていると叩けないため、_で連結して叩くようにしている。
api実装
http://bot-api.com/reiewers/Tanaka_Taro で叩くと、
{"data":[{"hipchat_mention_name":"A-SAN"},{"hipchat_mention_name":"B-SAN"}],"my_mention_name":[{"my_mention_name":"WATASHI"}]}
のように返却される
方法は、
・DBから自分のユーザ名で自分が所属するユーザリストをSELECT
・DBから各グループごとに自分以外のユーザをSELECT
・コントローラで上の結果からランダムに1人ずつ取得
・DBから自分のmentionnameをSELECT
という流れで取得してきている。
hubot側は上記jsonをパースして@hipchat_mention_nameで返却すれば
botがレビュワーを選択したようになる。
Q&A
Q.各種APIからの情報取得はどのタイミングで行っているの?
A.毎月定期的にbatchを動かして取得している
Q.なんでhubotから直接各種API叩かないの?
A.hipchatのAPIのlimit が 100アクセス/5分で弊社のユーザ数だと5分以内に2回目叩いた時にAPIが叩けなくなるから