Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

こんばんは,うどん大 情報系 院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として作られてます.
こちらはプルリクの一覧表示ができるなど,高機能で良いですね.

hiconyan
大手町でクラウドエンジニアしてます。うどん大学院 情報系出身。趣味は料理と映画、カメラ。
https://hiconyan.page/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした