今さらながら Slack bot を作りたくて、フレームワークは Hubot を選んだ。
Hubot はそのままでは CoffeeScript で書く必要があるんだけど、ES2015 もやっと覚えたばかりなのに CoffeeScript の勉強はしたくない。
ということで、ES2015 で書くための手順をメモ。
デプロイ先は Heroku です。
Hubot のインストール
まずは 公式ドキュメント の通りに Hubot スクリプトのひな形を作成する。
$ npm install -g yo generator-hubot
$ mkdir hubot-es2015
$ cd hubot-es2015
$ yo hubot
_____________________________
/ \
//\ | Extracting input for |
////\ _____ | self-replication process |
//////\ /_____\ \ /
======= |[^_/\_]| /----------------------------
| | _|___@@__|__
+===+/ /// \_\
| |_\ /// HUBOT/\\
|___/\// / \\
\ / +---+
\____/ | |
| //| +===+
\// |xx|
? Owner zaki-yama <shingoyamazaki00@gmail.com>
? Bot name hubot-es2015
? Description A simple helpful robot for your Company
? Bot adapter slack
create bin/hubot
create bin/hubot.cmd
create Procfile
create README.md
create external-scripts.json
create hubot-scripts.json
create .gitignore
create package.json
create scripts/example.coffee
create .editorconfig
_____________________________
_____ / \
\ \ | Self-replication process |
| | _____ | complete... |
|__\\| /_____\ \ Good luck with that. /
|//+ |[^_/\_]| /----------------------------
| | _|___@@__|__
+===+/ /// \_\
| |_\ /// HUBOT/\\
|___/\// / \\
\ / +---+
\____/ | |
| //| +===+
\// |xx|
なんか色々ファイルが作成されました。
$ ls -al
total 64
drwxr-xr-x 13 yamazaki staff 442 7 12 18:23 ./
drwxr-xr-x 5 yamazaki staff 170 7 12 18:22 ../
-rw-r--r-- 1 yamazaki staff 197 5 20 06:45 .editorconfig
drwxr-xr-x 12 yamazaki staff 408 7 12 18:37 .git/
-rw-r--r-- 1 yamazaki staff 39 5 20 06:45 .gitignore
-rw-r--r-- 1 yamazaki staff 24 7 12 18:23 Procfile
-rw-r--r-- 1 yamazaki staff 7904 7 12 18:23 README.md
drwxr-xr-x 4 yamazaki staff 136 7 12 18:23 bin/
-rw-r--r-- 1 yamazaki staff 213 7 12 18:23 external-scripts.json
-rw-r--r-- 1 yamazaki staff 2 7 12 18:23 hubot-scripts.json
drwxr-xr-x 113 yamazaki staff 3842 7 12 18:23 node_modules/
-rw-r--r-- 1 yamazaki staff 662 7 12 18:23 package.json
drwxr-xr-x 3 yamazaki staff 102 7 12 18:23 scripts/
Babel のインストールと設定
ES2015 で書き、ES5 にトランスパイルするため Babel をインストールする。
$ npm install --save babel-cli babel-preset-es2015
通常、Babel などのアプリケーション本体で使われないパッケージは --save-dev
を使ってインストールするが、
Heroku でデプロイしたときに devDependencies は自動的にインストールされない ため、dependencies に保存されるようにしてます。
つづいて、.babelrc
を作り、以下を記述。
{
presets: ["es2015"]
}
さらに package.json
に npm script を定義する。
"scripts": {
"build": "babel src --out-dir build",
}
src, build のフォルダ名は自由です。
準備ができたので、スクリプトを書いていく。
src/index.js
(ファイル名は任意)に以下のように記述する。
module.exports = (robot) => {
robot.hear(/すし/, (res) => {
res.send(':sushi:');
});
}
「すし」と入力したら Slack 上で寿司アイコンを返すだけの単純なスクリプト。
保存したら、先ほどの npm script でビルドする。
$ npm run build
> hubot-es2015@0.0.0 build /Users/yamazaki/workspace/hubot/hubot-es2015
> babel src --out-dir build
src/index.js -> build/index.js
build
ディレクトリ以下にファイルが生成されました。
Bot 起動用のコマンドを編集する
デフォルトでは、bot の起動は
$ ./bin/hubot
だけで済むが、今回は --require
オプションでスクリプトが格納されているディレクトリを指定する。
$ ./bin/hubot --require build
デプロイ先に Heroku を使う場合は Procfile
も編集しておく。
web: bin/hubot -a slack --require build
(-a slack
は Slack と連携するために必要)
bot の動きを Slack から試してみる場合は、事前に Slack の Hubot 設定ページから HUBOT_SLACK_TOKEN
をコピーし
.env
に記述した後、
$ heroku local web
コマンドを実行する。
ちゃんと動いてるようです。
Heroku にデプロイする
最終的に Heroku にデプロイするときは、以下の作業が必要です。
postinstall
という npm script を追加する
参考:https://devcenter.heroku.com/articles/nodejs-support#customizing-the-build-process
postinstall
というスクリプトは、Heroku にデプロイ後に自動的に走るスクリプト。
デプロイ後に Babel によるビルドが実行されるようにする。
"scripts": {
"build": "babel src --out-dir build",
"postinstall": "babel src --out-dir build"
}
本番環境の環境変数にも HUBOT_SLACK_TOKEN
を設定する
画面を開くのが面倒な人は
$ heroku config:set HUBOT_SLACK_TOKEN=...
というコマンドを実行するか、.env
ファイルから設定する以下の方法が便利です。
Herokuで本番環境の環境変数(config vars)を.envファイルで設定する - dackdive's blog
環境変数 HUBOT_HEROKU_KEEPALIVE_URL
(とタイムゾーン)を設定する
external-scripts.json
を見ると、hubot-heroku-keepalive が指定されている。
これは、Free dyno で bot がスリープしないようにするための Hubot スクリプトらしい。
そして、このスクリプトが正しく動作するためには HUBOT_HEROKU_KEEPALIVE_URL
という環境変数が設定されている必要があるそうなので、設定する。
$ heroku config:set HUBOT_HEROKU_KEEPALIVE_URL=https://[your-heroku-app].herokuapp.com/
$ heroku config:set HUBOT_HEROKU_KEEPALIVE_URL=$(heroku apps:info -s | grep web-url | cut -d= -f2)
その他の変数については以下の通り。詳しくは README の Configuration 参照。
HUBOT_HEROKU_WAKEUP_TIME
: Bot を起動する時間。デフォルト 6:00
HUBOT_HEROKU_SLEEP_TIME
: Bot をスリープする時間。デフォルト 22:00
HUBOT_HEROKU_KEEPALIVE_INTERVAL
: Bot を定期的に起こす間隔。デフォルト 5 分間隔
おおむねデフォルト通りで良さそうに見えるが、WAKEUP_TIME
および SLEEP_TIME
は Heroku アプリのタイムゾーン(デフォルト UTC)に従うので、以下のようにタイムゾーンを JST に設定しておいた方がよさそう。
$ heroku config:set TZ=Asia/Tokyo
(2016/08/23 追記) Heroku Scheduler というアドオンを追加する
上述した hubot-heroku-keepalive というスクリプトだけでは不十分だった。
スクリプト自体は dyno が スリープしないように 定期的にアクセスするためのものなので、
HUBOT_HEROKU_SLEEP_TIME
から HUBOT_HEROKU_WAKEUP_TIME
の間で dyno がスリープしてしまうとそれ以降スリープしっぱなしになってしまう。
そのため、HUBOT_HEROKU_WAKEUP_TIME
に合わせて dyno をスリープから復旧させる必要がある。
これには hubot-heroku-keepalive の README に書いてあるとおり、Heroku Scheduler というアドオンを使う。
アドオンは管理画面からインストールするか、ローカルで以下のコマンドを実行する。
$ heroku addons:create scheduler:standard
インストール後に heroku addons:open scheduler
を開くと設定画面が開くので、新規でジョブを追加して以下のように設定する。
中央のスクリプトには
$ curl ${HUBOT_HEROKU_KEEPALIVE_URL}heroku/keepalive
を入力する。
また、NEXT DUE は UTC で入れる必要があるので要注意。(キャプチャだと日本時間の 9:00 に起こす)
その他
1) 起動時のログに
INFO /Users/yamazaki/workspace/hubot-es2015/build/index.js is using deprecated documentation syntax
と出力されている。
調べてみると、Description: などの冒頭のコメントがないとこのログが出力されるそう。
参考:Hubotでusing deprecated documentation syntax - Qiita
というわけで、試しにビルド前の JS にコメントを追記してみたけど
ビルドすると冒頭に 'use strict'
が追加されてしまい、1 行目からコメントがないとこのログは消せないよう。
ビルド前
module.exports = (robot) => {
...
ビルド後
'use strict';
module.exports = function (robot) {
...
今のところ特に困らないので、とりあえず諦める。
2) (解決) 同じく起動時のログに
ERROR hubot-heroku-alive included, but missing HUBOT_HEROKU_KEEPALIVE_URL. `heroku config:set HUBOT_HEROKU_KEEPALIVE_URL=$(heroku apps:info -s | grep web-url | cut -d= -f2)`
と出ている
確認したところ external-scripts.json
に hubot-heroku-keepalive というライブラリが指定されていて、README を読む限り HUBOT_HEROKU_KEEPALIVE_URL
という環境変数を指定する必要があるみたい。
3) デフォルトで作成される scripts
ディレクトリは不要になったので削除した。一緒に、hubot-scripts.json
も deprecated のようなので削除。
(起動時に以下のログが出ていた)
WARNING Loading scripts from hubot-scripts.json is deprecated and will be removed in 3.0 (https://github.com/github/hubot-scripts/issues/1113) in favor of packages for each script.
リファレンス