ちょっと特殊な書き方が必要なのですよね
本題の前に、ちょっとしたDockerfileとdockerイメージを公開してみました。
dockerイメージ
生のDockerfile
このdockerイメージは何ができるの?
できる事は、「sudo可能」「yum可能」「viが初期インストール済み」「npm可能」というだけです。ベースイメージがCentOS6系なので、当然alpine linux等と比較すると巨大なファイルサイズ(190MByte)です。しかしviがあってsudo可能でyumが利用可能でnpmで追加モジュールインストール可能な状態なので、docker上での開発が非常にやりやすい筈です。というか何でもできます。
hubotのスクリプト開発用と割り切っているので、プロダクション環境では使い物にならないので、悪しからず。
なんでこれ作ったの?
私は以前からhubot+slackのスクリプトの開発が非常にやりにくいと思っていました。
- hubotとslackを連携しないとスクリプトの動作確認ができない。
- docker hubによくあるイメージはviも入っていない、sudoもできない、yumもできないものが多く、productionではなく開発に特化したイメージが無い。
- 会社でやろうとするとhubotを頻繁に再起動するので、ChatOpsに影響を与えてしまう。
- 会社のslackアカウントは管理権限を持っていないので、テストでhubot等が投稿したメッセージを削除する事ができない。
- できれば使い慣れたCentOS上で開発したい。
既存のdockerイメージは環境をいじらない前提の最小構成になっている場合がほとんどで、docker上でストレス無しに開発できそうなイメージは見つかりませんでした。まあそもそもdockerがイミュータブルな環境前提なのでそれは正しいのですが、開発にフォーカスした場合、そのイミュータブルさが逆に仇となって開発しにくくストレスが溜まるものでした。それが嫌だったので、もういっそイミュータブル要素を排除して、CentOSベースでviもsudoもyumもnpmもできるもの用意しちゃいました。
それならVagrantでいいじゃんという意見もあると思いますが、やはりdockerのコンテナの起動速度は魅力的なので、docker上で開発したいと考えていました。
hubotをwebhookに反応させる
さて、では本題です
slackアカウント作成等
ここに色々書きましたが、個人用のslackアカウントを作成し、App Directoryでhubotとincoming webhookを追加し、HUBOT_SLACK_TOKENをコピーし、「/invite hubot」でチャットルームにhubotを招待しておいて下さい。
dockerコンテナの起動
# イメージをpullする docker pull treetips/dockerfile-centos-hubot-slack:latest # コンテナを起動する docker run -dit --name hubot-slack -e HUBOT_SLACK_TOKEN=xoxb-XXXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXX treetips/centos-hubot-slack:latest # コンテナにsshする docker exec -it hubot-slack bash # hubotをslack連携して起動(フォアグランド起動) ./bin/hubot --adapter slack
これでチャットルームのhubotはオンライン状態になります。
incoming webhookに反応するhubotスクリプト
incoming webhookからhubotを呼び、mentionしたり色々したい事ってありますよね。あるよね・・・?
しかしhubot-slackのスクリプトは、robots.hear等ではincoming webhookの呼びかけに反応してくれません。
class SlackBotListener extends Listener
https://github.com/slackhq/hubot-slack/blob/master/src/listener.coffee
# SlackBotListeners receive SlackBotMessages from the Slack adapter
# and decide if they want to act on it. SlackBotListener will only
# match instances of SlackBotMessage.
#
# robot - A Robot instance.
# regex - A Regex that determines if this listener should trigger the
# callback.
# callback - A Function that is triggered if the incoming message matches.
#
# To use this listener in your own script, you can say
#
# robot.listeners.push new SlackBotListener(robot, regex, callback)
constructor: (@robot, @regex, @callback) ->
@matcher = (message) =>
if message instanceof SlackBotMessage
message.match @regex
こんな事がソースに書いてあって、何やら
「To use this listener in your own script, you can say」
「robot.listeners.push new SlackBotListener(robot, regex, callback)」
等とコメントに書いてあります。単純にrobots.hear等では駄目との事です。
$HUBOT_HOME/scripts/test.coffee を作成
では早速スクリプトを書いてみます。以下はincoming webhookでhubotに対して「おい」と呼びかけると、「なんだよ」と反応させるものです。
HubotSlack = require 'hubot-slack' module.exports = (robot) -> robot.listeners.push new HubotSlack.SlackBotListener robot, /^おい/i, (res) -> res.send "なんだよ"
$HUBOT_HOME/scripts/test.coffee に配置すると起動時に自動的に読み込んでくれるので、一旦フォアグランドで起動していたhubotをCtrl + cで終了し、test.coffeeを作成して下さい。続いて「./bin/hubot --adapter slack」で再びhubotをフォアグラウンド起動します。これで反応する準備はできました。
incoming webhookで呼びかけてみる
以下のような感じでPOSTで呼びます。呼び出すURLは、App DirectoryのIncoming WebHooksの設定の「Webhook URL」からコピって下さい。
curl -X POST --form 'payload={"channel": "#bot-room", "username": "ぼっと", "mrkdwn": true, "text": "おい"}' https://hooks.slack.com/services/XXXXXXXXX/XXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXX
では呼んでみます。
このGIFアニメだとちょっと解りにくいと思いますが、ターミナルで前述のcurlコマンドを叩いて、incoming webhookが「おい」と発言し、hubotがすぐに「なんだよ」と反応しています。
これができるという事は何か色々使えそうな気がしますね!
雑感
hubot-slackのスクリプト開発、正直辛いですね。とりあえずカッとなってdockerイメージ作ったので大分開発しやすくなりましたが、まだまだ開発しにくい感が否めません。
というか、hubotって「あの呼びかけにあれが反応しない」等が非常に解りにくいんですよね。hubotがhubot宛(自分宛)にmentionしても反応しなかったり(多分無限ループになるから)、その辺がいちいち面倒臭くて、あれこれ試してるうちにチャットルームがテスト投稿でビッシリ埋まってしまい、「てめー何チャットルーム荒らしてんだコラ」と怒られたりします。
そうならないためにも、個人でslackアカウント用意してしまって、dockerfile-centos-hubot-slackのイメージであれこれ試行錯誤すると、チャットルーム荒らしの汚名を着せられる事もなくなります。きっと・・・