BotkitのConversationでプルリクをマージする

  • 21
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

こんばんは,うどん大 情報系 院2年の@hico_horiuchiです.
この記事はSLP KBIT Advent Calendar 2015の22日目です.
(ChatOps Advent Calendar 2015の15日目が空いてたので,兼用で登録しました.)

先日の「Botkit + ImgurでプルリクにLGTMする」に引き続き,Botkitを使ってみます.
SLPでもGitHubとSlackを使っているので,Botを活用できるシーンを考えてみました.
(SlackはTeamが乱立してるので,統合してChannnelでまとめたい感….)

ちなみに,昨年は「Hubotで始める簡単Bot開発」だったので,2年連続でBotネタですね.

Botkit?

昨日のSlack Platformの発表の中で,新しく紹介されたBot Frameworkです.

第一印象やHubotとの違いなどは「Botkit + ImgurでプルリクにLGTMする」を参照して下さい.

Conversation(対話機能)

Botkitでは,標準で 対話機能 が提供されるようです.
(質問文と,それに続く返答での条件分岐が,対話と定義されてるようです.)

bot.startConversation を使うと,Yes/Noなどの対話を簡単に実装できるようです.
Yes/Noの判定基準となる単語は,このように定義されていました.

  • bot.utterances.yes : yes, yeah, yup, ok, sure
  • bot.utterances.no : no, nah, nope

今回は対話機能を使って,Botkitにプルリクエストをマージさせます.
利用シーンとしては,こんな感じでしょうか.
(GitHub上でマージしちゃった方が早い気がしなくもない.)

  1. Slackに「プルリクが作成されたよ」とGitHubの通知が飛んでくる.
  2. Slack上でプルリクについて,あーだこーだ議論してみる.
  3. Botkitに「マージして」と言うと,「本当に良い?」と聞いてくる.
  4. 「Yes」と答えるとマージ,「No」と答えると何もしない.

ちなみに,誤爆を防ぐために「Botしかマージする権限を持っていない」という会社もあるようです.
マージをトリガにして,CIを使ってデプロイする所まで自動化していると楽しそうですね.
この辺りの話は,Rebuild.fmで有名な@naoya_itoさんが書かれてます.

Conversationでプルリクをマージ

ここからが本題です.

最初に,SlackとGitHubでAPIトークンを取得しておきます.
こちらは,Qiitaに投稿されている記事を参考にします.

次に,適当な作業ディレクトリを作って,必要なライブラリをインストールします.

$ mkdir ~/botkit
$ cd ~/botkit
$ npm install --save botkit node-github 

さて,少し長いですが,Botkitのコードはこのようになります.
GitHub APIの呼出にはnode-githubを利用しました.

~/botkit/bot.json
var SLACK_TOKEN = 'xoxb-0123456789abcdefghijklmnopqrstuvwxyz';
var GITHUB_ACCESS_TOKEN = '0123456789abcdefghijklmnopqrstuvwxyz0123';

var botkit = require('botkit');
var githubAPI = require('node-github');

var controller = botkit.slackbot({
  debug: false
});

controller.spawn({
  token: SLACK_TOKEN
}).startRTM();

var pullRequestsMerge = function(bot, message, args) {
  console.log(args);

  github = new githubAPI({
    version: '3.0.0'
  });

  github.authenticate({
    type: 'oauth',
    token: GITHUB_ACCESS_TOKEN
  });                                                                                                                   

  github.pullRequests.merge({
    user: args.user,
    repo: args.repo,
    number: Number(args.id)
  }, function(error, _) {
    if (error) {
      bot.botkit.log('Failed to request of GitHub API:', error);
    }
  });
};

controller.hears('^merge +(.+)\/(.+) +([0-9]+)$', 'direct_mention', function(bot, message) {
  var matches = message.text.match(/^merge +(.+)\/(.+) +([0-9]+)$/i);                                                   

  bot.startConversation(message, function(err,convo) {
    convo.ask('Are you sure you want to merge?', [{
      pattern: bot.utterances.yes,
      callback: function(response, convo) {
        pullRequestsMerge(bot, response, {
          user: matches[1],
          repo: matches[2],                                                                                             
          id: matches[3]
        });

        convo.next();
      }
    }, {
      pattern: bot.utterances.no,
      callback: function(response, convo) {
        bot.api.reactions.add({
          timestamp: response.ts,
          channel: response.channel,                                                                                    
          name: '-1',
        }, function(error, _) {
          if (error) {
            bot.botkit.log('Failed to add emoji reaction:', error);
          }
        });

        convo.next();
      }
    }]);
  });
});

実際に使ってみる

では,実際にBotkitを起動してみましょう.

$ node bot.js 
** No persistent storage method specified! Data may be lost when process shuts down.
** Setting up custom handlers for processing Slack messages
** API CALL: https://slack.com/api/rtm.start
** BOT ID:  bot  ...attempting to connect to RTM!

コマンドのフォーマットは @bot: merge <user>/<repo> <id> です.
(イカに深い意味はありません.)

botkit_ikaring.png

「no」と返すと :thumbsdown: されますが,これもBotkitでやってます(後述).
「yes」と返すと,ちゃんとマージされてることが分かりますね.
(GitHubと連携してることが多いと思うので,敢えてBotkitで結果を返してません.)

(おまけ) BotkitからAdd Reactionする

BotkitはSlackに特化してるので,Add ReactionなどのAPIも簡単に利用できます.
以下,howdyai/botkit/bot.jsより抜粋.

bot.js
bot.api.reactions.add({
  timestamp: message.ts,
  channel: message.channel,
  name: 'robot_face',
},function(err,res) {
  if (err) {
    bot.botkit.log("Failed to add emoji reaction :(",err);
  }
});

このメソッドは,SlackのAPIをそのまま叩いてる感じですね.
タイムスタンプとChannelで,Add Reactionするメッセージを特定するみたいです.

Conversationだと callback: function(response, convo) {}response に返答が入ってるようです.
(「yes」「no」などのメッセージオブジェクト.)
これを指定して bot.api.reactions.add() してやると,返答にEmojiを付けられます.

まとめ

Botkitだと,標準で対話機能が提供されてるので,簡単に実装できました.
SLPでもこんな感じで,SlackとGitHubを連携させて,ChatOpsが流行ればなーと思っています.
(ChatOpsすると自動化が必要になるので,色々便利になったり,運用ミス減らせるんじゃないかな?)

Hubotで同様の機能を,@bouzuyaさんがhubot-prとして作られてます.
こちらはプルリクの一覧表示ができるなど,高機能で良いですね.

この投稿は ChatOps Advent Calendar 201515日目の記事です。