第4回までで、Hubotをセットアップしてチャットツールに接続し、独自のスクリプトを書くことができるようになりました。最終回となる今回は、もう少し複雑なスクリプトの書き方をサンプルコードをベースに紹介します。
定期実行で定時ミーティングの時間を通知する
デイリースクラムの時間を通知すると言った定期的な処理をHubotに行わせたい場合、cronモジュールを使うと便利です。本節では、cronモジュールの導入方法と使用例のサンプルスクリプトを掲載します。
cronモジュールの導入
cronモジュールのようなnpmのモジュールを使用するには、Hubotを導入したディレクトリの直下にあるpackage.json
ファイルのdependencies
にモジュールの情報を追加します。
通常、Hubotをインストールした直後はdependencies
の項目は次のようになっています。
ここにcronモジュールを追加することでスクリプトからcron
モジュールを使用できるようになります。
サンプルスクリプト
cronモジュールを使って月曜日から金曜日の午前11時にミーティングの開催を呼びかけるスクリプトの例を示します。
見てのとおり、cronモジュールでは、通常のcronと同様の書式で定期処理を書くことができます。
注意点として、普通のhear
やrespond
を使った発言方法ではmsg
オブジェクトのsend
メソッドなどを使いますが、定期実行のように誰かから話しかけられて返答するのではない場合は、robot
オブジェクトのsend
メソッドを直接使ってチャットルームに発言することになります。
send
メソッドの第一引数envelope
は発言先のチャットルームや発言対象のユーザの情報を格納したオブジェクトです。この例ではhubot-ircを使ってIRCの#chatroomチャンネルに発言することを想定しています。どのようなenvelope
が必要かは、使用しているAdapter
よって異なるため注意が必要です。
cronモジュールの詳しい使い方はリファレンスを参照してください。
永続化機能で投票結果を保存する
Hubotに何かを記憶させようとしたとき、初期状態ではメモリ上に情報を置くことしかできません。そのため、Hubotを再起動すると情報が消えてしまいます。この問題に対して、Hubotではbrain
というインターフェースを通じて様々なストレージに情報を永続化できます。
本節では、Redisを使った永続化の方法と、チャット参加者に投票する仕組みを作る例を記します。
redis-brainによるRedis永続化機能の追加
Redisを使った永続化を行うには、HubotからアクセスできるところでRedisが動いている必要があります。Redisの公式サイトなどを参考に予めRedisをインストールして、起動してください。
HubotとRedisを接続するには、hubot-scriptsのredis-brain.coffeeを使う方法が簡単です。redis-brain.coffee
を有効化するためには、hubot-scripts.json
でredis-brain.coffee
を読み込み、環境変数で接続先のRedisインスタンスを指定します。
このように設定すると、Hubotのbrain
から保存したデータを127.0.0.1:6379のRedisにhubot:storageというキーでJSON文字列として保存するようになります。
サンプルスクリプト
brain
を使った永続化のサンプルとして、チャット上で何か良いことをしたメンバーに投票する仕組みを作ってみます。
brain
の詳細については、公式のリファレンスとソースコードを参照してみて下さい。
HTTPリクエストを送ってURLからコンテンツを取得する
本節では、Hubotに組み込まれているscoped-http-clientを使用してHTTPリクエストを送る方法について説明します。
scoped-http-clientの使用方法
Hubotには、Robot
クラスのオブジェクトとResponse
クラスのオブジェクトにscoped-http-clientのオブジェクトがセットされているため、単純にGET
やPOST
でHTTPリクエストを送って結果を取得するだけなら新たなモジュールを追加する必要はありません。
URLを受け取って取得したHTML文字列をチャットに発言するサンプルを次に示します。
msg.httpにURLを渡すと、HTTPリクエストを送るためのオブジェクトが返ってきます。このオブジェクトの実体は、scoped-http-clientのScopedClient
オブジェクトです。
scoped-http-clientの詳しい使い方は公式リファレンスを参照してください。
サンプルスクリプト
ここでは、例としてチャットにURLが投稿されると、そのページのタイトルを取得してHubotが発言するというスクリプトを紹介します。
Node.js
でスクレイピングするときには、jQueryに似た書式で書けるcheerioモジュールを使うと便利です。cheerioを使うには、cronモジュールのときと同様にdependenciesに追加してください。
このように、HTTPリクエストを送って結果を解析することは簡単に行えます。WebAPIを叩くような処理も同様に実装できます。
本節で紹介したscoped-http-clientはモジュールを追加しなくても使えるため手軽ではありますが、302リダイレクトのレスポンスが返ってきた場合に自動で遷移先のコンテンツを取得してくれなかったりと不便な点もあります。実装したい機能をscoped-http-clientモジュールで実現できない場合は、requestなど別のモジュールを使用することも検討して下さい。
Webサーバ機能を使って外部からのリクエストを待ち受ける
HubotはデフォルトでexpressによるWebサーバが立ち上がるようになっており、スクリプトからルートを登録することで特定のURLに対するリクエストを受け取り処理することができます。 この機能を使うと、簡単に外部からHubotに対して情報を渡してアクションを起こさせることができます。
注意点として、HubotのWebサーバを直接インターネットに晒してリクエストを受け付けると、外部から誰でもHubotにリクエストを送ることができるためセキュリティ上の問題があります。ローカルネットワークからのみリクエストを受け付けるようにするか、外部に対して開く場合は別途認証や検証の仕組みを入れることを検討してください。
本節では、Webサーバ機能の概要と使用例を掲載します。
Webサーバ機能について
Hubotを起動すると、とくに何も設定しなくてもWebサーバ機能が有効になっており、8080番ポートでリクエストを待ち受けている状態になります。しかし、expressにルートを登録していないとリクエストを送っても何も反応しません。
hubot --create
したときに最初から使用可能になっているhttpd.coffeeスクリプトを使うと、Webサーバ機能の動作を簡単に確認することができます。このスクリプトがscriptsディレクトリに配置してある状態でHubotを普通に起動すると、/hubot/version
, /hubot/ping
, /hubot/time
, /hubot/info
, /hubot/ip
のルートが登録されます。
Hubotを起動した状態で、同じサーバ上で次のようにリクエストを送ることで、HTTPリクエストに対して正常にレスポンスが返ってくることが確認できます。
Hubotがデフォルトで待ち受ける8080番ポートが既に使用されている場合は、PORT
オプションを環境変数で指定することで待ち受けるポート番号を変更することができます。
では、httpd.coffeeはどのようにルートを登録しているのでしょうか。httpd.coffeeから/hubot/version
へのリクエストを受け付けるコードを抜粋します。
robot.router
がexpressのオブジェクトです。つまり、このコードは直接expressを使う場合の次のようなコードと同等ということになります。
httpd.coffeeには、他にもHubotからシェルコマンドを実行するサンプルなども含まれるため、一度ソースコードを確認することをお勧めします。
expressの具体的な使い方は、expressの公式サイトを参照してください。
GitHubのリポジトリに対するpushを通知するサンプルコード
実用的な例として、GitHubのリポジトリにpushがあった場合にHubotがチャットルームに通知するスクリプトを作ってみます。
GitHubには、Webhooksというリポジトリへのpushなどをトリガーとして予め設定したURLにHTTPリクエストを送るようにする機能があり、このWebhooksとHubotのWebサーバ機能を組み合せることで実現できます。
サンプルコードを次に示します。
GitHubがイベントごとにどのようなデータを送ってくるかはリファレンスで一覧できます。サンプルでは、pushイベントをhookしてpushされたcommitメッセージを順番にチャットルームに発言するようになっています。
今回のスクリプトは、GitHubからのリクエストを待ち受けるスクリプトなので、試しに動かしてみるためにGitHubのリポジトリ設定画面からWebhooksを有効化します。
リポジトリの設定画面から“Webhooks & Services”を選択すると次のような画面が出てきます。
ここで、“Webhooks”の“Add webhook”をクリックするとwebhookの設定画面に遷移します。
簡単に試すだけなら、Payload URLにリクエストの送り先を指定するだけで設定完了です。今回は、サンプルスクリプトで指定した/github/hookを送り先とします。
では、実際に対象のリポジトリにpushしてみます。
実際に使用する場合は、GitHub以外からのリクエストを受け付けないためにドキュメントを参照して対策を施してください。
Jenkinsのビルドの実行結果を通知するサンプルコード
もう1つの例として、Jenkinsのビルドが完了したときにHubotが発言するようにしてみます。
Jenkinsは、Notification Pluginを導入することでビルドが完了したときにその結果をHTTPリクエストで外部に送信する機能を追加できます。
GitHubのWebhooksと同様に、この機能とWebサーバ機能を組み合わせたサンプルコードを次に示します。
動作を試すには、JenkinsにNotification Pluginを追加し、プロジェクトの設定画面で次のようにHTTPリクエストの送信先を指定する必要があります。
設定が反映されると、ジョブの完了時にHubotが結果を受信して次のようにチャット上に発言するようになります。
まとめ
本連載の最終回となる今回は、定期実行、HTTPリクエストの送信、永続化、Webサーバの使用を例に色々なユースケースに対応したスクリプトの書き方を紹介しました。
本連載では、Hubotの導入からスクリプトの書き方まで一通りの使い方を紹介しました。Hubotにはスクリプトで簡単に様々な機能を追加できるため、Node.jsの豊富なモジュールとHubotの機能を組み合わせて現場ごとに自分達に必要なスクリプトを開発してHubotを育てていくことができます。
本連載はこれにて終了しますが、皆さまの現場に様々なHubotが育っていくことを願っています。ご愛読ありがとうございました。