astahチームの開発を支える技術(プロジェクトの様々なことを自働化するロボット Hubot編)

こんにちは。製品事業部の近藤です。みなさんの現場ではHubotを活用されていますか?Hubotはプロジェクトの様々なことを自動的に解決してくれる優秀なロボットです。Hubotがチャットに常駐するだけで、こんなことを実現してくれるでしょう。

  • 朝会やふりかえりの時間を教えてくれる
  • Jenkinsおじさんにビルドやリリースをお願いしてくれる(ChatOps)
  • チャットに流れたチケット番号から、そのタイトルとリンク先を教えてくれる
  • GitHub等のチケットの状態をTrelloに反映してくれる

………ん?最後のTrac等のチケットの状態をTrelloに反映してくれるという話はなんでしょう?そうなんです。Hubotは各サービスのHubとなり、プロジェクトの運営を円滑に進めてくれている存在なのです!今回はHubotが各サービスのHubとなり、ロボットとして大活躍している様子とその仕組みを紹介します。

robot.respond と robot.hear

Hubotに処理をお願いするには、大きく分けて2つのコマンドがあります。それがrobot.respondrobot.hearです。

robot.respondは、予めコマンドを登録しておき、下記のようにHubotに呼びかけることで処理を実行できるようにするものです。

Hubot> hubot ping
PONG

この例では、予め登録されていたpingコマンドをHubotが受け取り、PONGとメッセージを返しています。

もう一つのrobot.hearは、チャットに流れているメッセージを監視し、該当するメッセージがあった時に処理を行ってくれるものです。例えば朝会等でチケット番号だけで話をするメンバーがいて、その番号がなんなのか分からない事が個人的にとても困っておりました。せめてチャットの上ではそのチケット番号がなんのタスクなのか分かるようにしています。

Idobata

メッセージの最後のTrac #777にHubotが反応して、そのチケットがなんなのか要約をチャットにつぶやいています。この反応している部分がrobot.hearです。

robot.hear /trac \#(\d+)(?=[^\w]|$)/ig, fetchTicket

robot.hearの最初の引数が監視条件の正規表現、2つ目の引数が処理を実装した関数です。(Tracからチケット情報を取り出す処理であるfetchTicketの解説は割愛します。興味のある方はリンク先のコードを読んでみてください。)

robot.hearを使ってサービス間連携を実現する

さて、見ての通り、Hubotはチャットに流れるメッセージ全てを監視しています。ということは、他のサービスから流れるメッセージを元に、Hubotに処理をさせることもできるはず。ということで、GitHub上のPull Requestのレビューの状態をTrelloに反映させたいなー、という妄想をモデル化し、下記のシーケンス図にしました。

貼り付けた画像_2015_04_27_10_19

厳密に言えば、IdobataとHubot間のメッセージの流れは複雑になりそうですが、モデル図なのでこれくらいで勘弁してください。GitHub上でPull Requestにラベルを付与するとIdobataに通知する流れは、それぞれのリポジトリでもOrganization全体でもWebHookの追加で対応できますよね。(英語のドキュメント)

idobataはGitHubからラベルの変更を受け取ると、次のようなメッセージを出力しています。

Idobata

これは下記の意味を持つ文字列です。

ユーザー名 labeled ラベル名 to 対象のPR情報 issueのタイトル

astahチームではPRのタイトルにはrefs #6131 チケットのタイトルというように、必ず修正したチケット番号とそのタイトルをつけています。(ここで登場するチケット番号はTracのものです。astahチームではいくつものリポジトリを扱うため、全体のバックログはTracで管理しています。この辺りの背景はまた次回以降お話させてください。)

今回の例ではrefs #6131という部分です。正規表現を使って、このissueの番号を取得することができます。非常に簡略的ですが、/.*\s+labeled (\w+).*#(\d+).*/iという正規表現で、1番目にマッチするのが対象のPR情報、2番目がチケット番号です。Trelloに登録しているカードも、同様にチケット番号 チケットタイトルとつけています。すると、カードをチケット番号で検索し、つけられたラベルに該当するListに移動させることができるのです!

_1__Pro_Board___Trello_と_ダウンロード

コードはこんな感じですね。

  robot.hear /.*\s+labeled (\w+).*#(\d+).*/i,(msg)->
    label = msg.match[1]
    ticket_id = msg.match[2]
    trello.get_board target_board_name,(err,board)->
      if err
        throw err
      trello.get_list board, label.capitalize(), (err,list)->
        if err
          throw err
        trello.get_cards_on_board board, (err,cards)->
          for card in cards
            re = /#(\d+).*/i
            match = card.name.match(re)
            if match
              card_id = match[1]
              if card_id == ticket_id
                 trello.move_card card, list, (err)->
                   if err
                     throw err

普段Javaをメインに使っているので、coffeescriptを綺麗に書く技術はないです。callbackで数珠つなぎになっているので、Promiseとか使って書いたほうがいいんでしょうか…。むずかしい。

Hubotはこういったサービス間で自動連携させたい時のHubになりうる存在であることがお分かりいただけたでしょうか?次回はastahチームの開発プロセスを紹介します。お楽しみに。

astahチームの開発を支える技術(プロジェクトの様々なことを自働化するロボット Hubot編)」への2件のフィードバック

コメントを残す