##やりたいこと
- Slackと連携できるHubotを立てる
- デプロイ方法は、Github -> CircleCI -> AWSとする
- slackへのAccess Tokenなどは環境変数で渡す(誰でも利用しやすいように)
- scriptsは誰でも追加しやすいように、localレポジトリのをDockerへ持っていくようにする
##まずはHubotに必要なものを揃える
- node.js
- npm
Mac環境ならどちらもbrew install
で簡単に用意できる
YeomanとYeomanのgenerator-hubot
を用意する。
-g
をつけずにbundle的なのりでローカルにインストールしたかったが、実行にあたってのパス設定が面倒そうなので諦めた。
% npm install -g yo generator-hubot
% yo hubot
% bin/hubot
これでhubotとの対話インターフェースが立ち上がる。
-
scripts
ディレクトリ以下にスクリプトを置くと、機能追加ができる。 -
hubot-scripts
ディレクトリ以下には、hubot-scripts.json
に定義したscriptsがインストールされる。利用できるscriptsはこちら -
package.json
に利用したいthird-party npm packageを追記すると、external-scripts.jsonに値が追加される。 -
ERROR hubot-heroku-alive included, but missing HUBOT_HEROKU_KEEPALIVE_URL
というメッセージが表示されてしまうので、external-scripts.jsonからheroku packageを削除。
##Dockerの用意
- Dockerfileを書く
- hubotの実行にnode.jsが必要なので、Docker registryからnode:latestを持ってくる。-> https://registry.hub.docker.com/u/library/node/
- あとは、ローカル側に用意したhubotの構成をDockerインスタンス上に移設して起動する設定をDockerfileに書く。
##Dockerを起動してみる
####まずはbuild
% docker build -t hubot .
そうすると、イメージが作成される。
% docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
hubot latest 663c24a4b22a 54 seconds ago 717.4 MB
作成されたイメージ上で、hubotを起動してみる
% docker run -it hubot bin/hubot
hubot> hubot ping
PONG
##Slackの用意
Integration Settings
- Hubotを有効に。
- API Tokenを得られる
- Iconのカスタマイズ、Nameのカスタマイズもできる
##Dockerの起動
% docker run -e HUBOT_SLACK_TOKEN=${HUBOT_SLACK_TOKEN} -e HUBOT_SLACK_TEAM=${HUBOT_SLACK_TEAM} -e PORT=${PORT} -d -p 9999:9999 -v "$(pwd)":/hubot hubot
これでチームにhubotが参加してくる。
##CircleCIの用意
machine:
services:
- docker
dependencies:
cache_directories:
- "~/docker"
pre:
- if [[ -e ~/docker/hubot.tar ]]; then docker load --input ~/docker/hubot.tar; fi
- docker build -t hubot .
- mkdir -p ~/docker
- docker save hubot > ~/docker/hubot.tar
test:
override:
- docker run -p 9999:9999 -v "$(pwd)":/hubot hubot
- circleCI上でDockerコンテナを起動するときは、services: dockerが必要
- dependenciesのところは、dockerのイメージを毎回registryからダウンロードしなくてよいようにキャッシュしている
##Hubotへスクリプトの追加
# Description:
# A way to interact with the Stamp URI.
#
# Commands:
# hubot stamp me <keyword> - The Original. Queries Stamp Images for <keyword> and returns a stamp image.
# hubot stamp list - Show a list of keywords.
stamps = JSON.parse(process.env.HUBOT_STAMPS)
module.exports = (robot) ->
robot.respond /stamp me (.*)/i, (msg) ->
keyword = msg.match[1]
msg.send stamps[keyword] ? "No stamp for #{keyword}"
robot.respond /stamp list/i, (msg) ->
keys = for key, value of stamps
key
msg.send keys.join('\n')
scripts
以下に配置するとhubotの起動時に読み込んでくれる。
決められたフォーマットでコメントを書いておくと、hubot help
したときにコマンドの説明を表示してくれる。このscriptでは環境変数HUBOT_STAMPS
にJSONを登録しておくと、keyに紐付いたimageのURLを返してくれる。
##AWSへAnsibleを使ってデプロイする
- hosts: aws
user: ec2-user
vars_files:
- vars/env.yml
- vars/private.yml
tasks:
- git: repo=https://github.com/osamunmun/hubot.git dest=/home/ec2-user/hubot accept_hostkey=yes
- file: path=/home/ec2-user/cache state=directory
- shell: cd /home/ec2-user/hubot; sudo ./docker-build.sh
- shell: sudo docker stop $(sudo docker ps -a -q)
- shell: cd /home/ec2-user/hubot; sudo docker run -e HUBOT_STAMPS={{ HUBOT_STAMPS }} -e HUBOT_SLACK_TOKEN={{ HUBOT_SLACK_TOKEN }} -e HUBOT_SLACK_TEAM={{ HUBOT_SLACK_TEAM }} -e PORT={{ PORT }} -p 9999:9999 -d -v $(pwd):/hubot hubot/slack
##CircleCIからデプロイする
- circleCIの環境変数に以下の値を登録しておく
- ANSIBLE_VAULT
- AWS_ACCESS_KEY_ID
- AWS_DEFAULT_REGION
- AWS_SECRET_ACCESS_KEY
- AWS_SECURITY_GROUP_ID
- HUBOT_SLACK_TEAM
- HUBOT_SLACK_TOKEN
- circleCIのSSH Permissionsにデプロイ先のEC2インスタンスへアクセスできる秘密鍵を登録しておく
machine:
services:
- docker
dependencies:
cache_directories:
- "~/cache"
pre:
- ./docker-build.sh
- npm install
- sudo pip install awscli
- sudo pip install ansible
- echo "${ANSIBLE_VAULT}" > ~/vault.txt
test:
override:
- ./node_modules/.bin/gulp mocha
- docker run -e HUBOT_SLACK_TOKEN=${HUBOT_SLACK_TOKEN} -e HUBOT_SLACK_TEAM=${HUBOT_SLACK_TEAM} -e PORT=${PORT} -d -p 9999:9999 -v "$(pwd)":/hubot hubot/slack
deployment:
production:
branch: master
commands:
- sh ./deploy.sh
#!/bin/sh
set -ex
IP=`curl -s ifconfig.me`
trap "aws ec2 revoke-security-group-ingress --group-id ${AWS_SECURITY_GROUP_ID} --protocol tcp --port 22 --cidr ${IP}/32" 0 1 2 3 15
aws ec2 authorize-security-group-ingress --group-id ${AWS_SECURITY_GROUP_ID} --protocol tcp --port 22 --cidr ${IP}/32
cd ansible; ansible-playbook -i hosts hubot.yml --vault-password-file ~/vault.txt
- hosts: aws
user: ec2-user
vars_files:
- vars/env.yml
- vars/private.yml
tasks:
- git: repo=https://github.com/osamunmun/hubot.git dest=/home/ec2-user/hubot accept_hostkey=yes
- file: path=/home/ec2-user/cache state=directory
- shell: cd /home/ec2-user/hubot; sudo ./docker-build.sh
- shell: sudo docker stop $(sudo docker ps -a -q)
- shell: cd /home/ec2-user/hubot; sudo docker run -e HUBOT_STAMPS={{ HUBOT_STAMPS }} -e HUBOT_SLACK_TOKEN={{ HUBOT_SLACK_TOKEN }} -e HUBOT_SLACK_TEAM={{ HUBOT_SLACK_TEAM }} -d -v $(pwd):/hubot hubot/slack