#概要
Slack / Hubot / GitHub / CircleCI などをつかってChatOpsにチーム開発できるフローをつくったので、ChatOpsによるデプロイ方法を中心にその方法をまとめてみます。
ChatOpsの主役であるチャットアプリには今回Slackを使いました。
HipChatでも同じように出来ますが、Slackの方がUIが優れていており、外部サービスとの連携も洗練されていたのでこちらを選択しました。
#ChatOpsな環境の概要
- SlackとHubot(PaaSであるheroku上にデプロイ)を連携させる
- SlackからHubot経由でGitHubにプルリクエストをつくる
- GitHub上の変更を監視し、CircleCIでテストを実施
- デプロイ用のブランチに変更があった場合(GitHubのWEBコンソールでデプロイ用ブランチへのプルリクエストをマージした場合)、CircleCI上でCapistranoを実行し、デプロイ実施
- デプロイが完了したらCircleCIからSlackに通知
#環境構築手順
##Hubotを動かしてみる
まずは、ローカルでHubotを動かすところまでを説明します。
実際にはローカルではなく、herokuでHubotを動かすことになりますが、Hubotの追加スクリプトの作成などの際にローカルで動作検証できた方がよいのでローカルにもHubotが動く環境を作ります。
まずは、Hubot / CoffeScript / redis をインストールします
sudo npm install -g hubot coffee-script redis
Hubotディレクトリを作成します。ここではwankoという名前で作成。
hubot --create wanko
cd wanko
Redisを立ち上げます。Redisはデータの永続化の為に使います。
redis-server
Hubotを立ち上げます
bin/hubot
Hubotが立ち上がり、デフォルドで用意されているコマンドにちゃんと反応すればOKです。
Hubot> hubot ping
Hubot> PONG
Hubot> hubot time
Hubot> Server time is: Sat Sep 06 2014 17:47:03 GMT+0900 (JST)
Hubot> hubot pug me
Hubot> http://25.media.tumblr.com/tumblr_mcqpch4QbC1qb08qmo1_500.jpg
##SlackとHubotを連携させる
hubot-slack( https://github.com/tinyspeck/hubot-slack )をnpmでインストールします
sudo npm install hubot-slack --save
Procfileに以下を追記します
web: bin/hubot --adapter slack
ここまでを、GitHub上にpush。予めGitHub側にwankoという名前でレポジトリを作っておきます
git init
git add -A
git commit -m "initial commit"
git remote add origin git@github.com:qwintet-dev/wanko.git#任意で置き換え
git push origin master
###Hubotをheroku上にデプロイさせる
チーム開発のため、ローカルでHubotをデプロイするわけにはいないので、PaaSであるheroku上にデプロイします。
heroku create wanko-bot --stack cedar #wanko-botは任意のアプリ名 指定しないと自動で名前が割り振られる
herokuのコンソールにwanko-botが追加されているので、Add-onsからRedisCludo(RedisToGoやOpenRedisでもたぶん大丈夫)を選んでインストール(事前にクレジットカード情報の入力が必要)
Add-onsの追加はコマンドラインからも以下のようにして可能
heroku addons:add rediscloud
herokuにSlackとの連携で必要な環境変数を設定してあげます。
この値はSlackのWEBコンソールから[Integration] > [add new Integration] からHubotを選択してインストールすると表示されます
この値をそれぞれheroku側のWEBコンソールより設定してあげます。
コマンドラインから設定したい場合は以下のようにします。
heroku config:add HUBOT_SLACK_BOTNAME=wanko#任意(Slack上に表示される名前)
heroku config:add HUBOT_SLACK_TEAM=qwintet
heroku config:add HUBOT_SLACK_TOKEN=xxxxxxxxx
最後に、gitでherokuにHubotをデプロイしてあげます。
git push heroku master
これで、herokuにHubotがデプロイされました。
###herokuで割り振られたURLをSlack側に登録する
今度は、herokuにデプロイしたアプリのURLをSlack側に登録します。
SlackのWEBコンソールから[Integration] > [Exsisting Integration] からさきほど作ったHubotのIntegrationを選択し、herokuアプリのURLを入力します。
###SlackからHubotを呼んでみる
SlackとHubotの連携の準備が整ったので、いよいよSlackからHubotを呼び出してみます。
適当にChannelを作って、wanko time などとメッセージを送ってみましょう。このwankoの部分はさきほどherokuに指定したHUBOT_SLACK_BOTNAMEに合わせて置き換えてください。
以下のように、hubotから返事がこれば成功です。
ちなみに、デフォルトではロボットのアイコンになってしまうので、今回はかわいいワンコのアイコンに変えています(SlackのWEBコンソールから変更可能)
##SlackからHubot経由でGitHub上にプルリクエストを作る
ここまでで、Slackからheroku上にデプロイされたhubotを呼び出すことができました。
次は、SlackからHubotに指令をだして、GitHubにあるレポジトリに対してプルリクエストを作ることができるようにしていきます。
###プルリクエストを送るレポジトリをGitHub上に用意する
ここではプルリクエストを送るテスト用として、READMEしかないレポジトリ(my-test-app
)をつくります。
プルリクが作れるようにmasterブランチの他にdeployment/productionブランチをつくって、masterブランチ上でREADME.mdを直接編集しておきます(両者のブランチに差分がないとプルリクエストがつくれない為)。
これでGitHubのWEBコンソール画面よりmasterブランチからdeployment/productionブランチに対するプルリクエストを作れる状態になりましたが、今回はChatOpsなので、このプルリクエストの作成をSlackからHubot経由で行っていきます。
###GitHubにHubot用のアカウントとアクセストークンの作成
GitHubにHubot用(HubotからGitHubAPIを叩く用)のアカウントを作成します。今回はwanko-qwtという名前で作成しました。
このアカウントにも、先につくったmy-test-app
レポジトリを操作できる権限をGitHub上から与えておく必要があります。
次に、GitHubの[Setting] > [Applications] > [Personal access tokens] からアクセストークンを生成します。権限を細かく設定できますが、今回は後のことも考えフルアクセスのadmin権限を付与しました。ここで生成されたアクセストークンをメモっておきます(一度しか表示されないので注意)。
###HubotにGitHubAPIを利用したスクリプトを用意する
Hubotのスクリプトカタログ( https://hubot-script-catalog.herokuapp.com/ ) に色々サンプルがあり、GitHub関連のも多数ありましたが、プルリクエストを作るものは無かったので、サンプルを参考にしながら実装しました。
Hubotレポジトリのscriptsディレクトリ以下にgithub-create-pull.coffeeのような適当な名前のスクリプトを追加します(scripts以下に置いておくだけでHubotが勝手に読み込んでくれます)。
実際のコードは以下のようにしました。
ただし、このスクリプトはgithubot(https://github.com/iangreenleaf/githubot )というプラグインに依存しているので、こちらをHubotレポジトリにインストールしておく必要があります。
npm install githubot --save
また、環境変数のHUBOT_GITHUB_TOKENを設定しておく必要があるので、Hubotレポジトリのbin/hubotに以下を追記します(execコマンドを発行している部分より上に書くこと!)。
export HUBOT_GITHUB_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxx" # 先ほど生成したGitHubのアクセストークン
###herokuに変更分をデプロイしなおす
ここまでのHubotレポジトリへの変更をherokuにデプロイします
git add -A
git commit -m "install githubot & add github-create-pull scripts"
git push heroku master
###Slackからプルリクエストを作ってみる
いよいよSlackからHubotを経由してGitHubのAPIでmy-test-app
レポジトリにプルリクエストを作る準備が整ったので、実際に実行してみます。以下のようになれば大成功です。
deploy my-test-app/master into deployment/production #Slackに打ったコマンド
GitHub側にもプルリクエストがちゃんとできているか確認してみましょう。
ちゃんとできていますね。
余談ですが、このプルリクエストをつくったワンコ(wanko-qwt)とSlack上で返事してくれるワンコ(wanko)の実態は全く別物です。それを分かりやすくするため、ここではあえてアイコン画像を変えていますが、実際には同じアイコンに設定し、同じワンコが頑張ってチームのために働いてくれている感じにしています。
##CircleCIの設定
ここまでSlack上からHubotを経由してGitHub上にプルリクエストをつくるところまでを行ってきました。
続いては、CircleCIの設定を行っていきます。
CircleCIのWEBコンソール画面で[Add Project]からCI対象のプロジェクトを選びます(今回は先ほどつくったmy-test-app
)。
プロジェクトを追加すると最初のテストが実行されますが、今はテストがないので「No Test」となりビルドが失敗してしまいます。
今回はダミーのテストを追加してビルドを成功させます。
my-test-app
レポジトリ直下にcircle.yml
というファイルをつくり、以下のようにします。
test:
override:
- ./dummy_test_script.sh
dummy_test_script.sh
という空ファイルも実行権限を付けて追加しておきます。
touch dummy_test_script.sh
chmod a+x dummy_test_script.sh
この変更をレポジトリにpushすると自動でビルドが走り、今度は成功するはずです。
##CircleCI上でCapistranoを実行し、デプロイ実施
ここまでで、CircleCIでmy-test-app
への更新を監視し自動でテストが走るようになりました。
次は、デプロイ用のブランチに更新があったタイミングで、CircleCI上でCapistranoを実行し対象ホストにデプロイする設定を行っていきます。
「デプロイ用のブランチに更新があったタイミング」というのは、実際の運用ではGitHubのWEBコンソール画面において、Slackから作られたデプロイ用のブランチへのプルリクエストをマージしたタイミングとなります。
###Capistranoの設定
つぎにCapistranoの設定を行っていきます。
my-test-appにGemfileを追加し、以下のように指定します。
source 'https://rubygems.org'
gem 'capistrano'
gem 'capistrano-rails'
gem 'capistrano-bundler'
gem 'capistrano-rbenv'
Capistranoをインストールします。
bundle install --path vendor/bundle
今回はVersion3.2.1です。
bundle exec cap -V
> Capistrano Version: 3.2.1 (Rake Version: 10.3.2)
これでCapistranoのインストールは完了したので、次にデプロイの設定を行っていきます。
bundle exec cap install
で設定ファイル一式が自動で作成されるので、config/deploy/staging.rb
とconfig/deploy.rb
を自分のデプロイしたい環境に合わせて書き換えます。
server 'host_name', user: 'user_name', roles: %w{web}
set :application, 'my-test-app'
set :scm, :git
set :repo_url, 'git@github.com:qwintet-dev/my-test-app.git'
set :deploy_to, "/www/my-test-app"
set :branch, ENV["BRANCH_NAME"] || "master"
これで以下を実行してデプロイが実行されれば成功です。認証等でうまく動かない場合はこちらの記事を参考にしてください。http://qiita.com/s-kiriki/items/08d500893c0764510e43
bundle exec cap production deploy
###CircleCIでのデプロイの設定
my-test-app
のcircle.yml
に以下を追記します。
deployment:
production: #これはただのラベルで何でもよい
branch: deployment/production #ここでブランチを指定。
commands:
- deployment-to-production.sh #new file
#!/bin/bash
bundle exec cap production deploy BRANCH_NAME=deployment/production
これで deployment/productionブランチのビルドの際にのみ、Capistranoによるデプロイが実施されるようになります。
次に、CircleCI上からデプロイ先のホストに対してCapistranoを実行するために必要な鍵を登録します。
my-app-testの設定ページの「SSH keys」で公開鍵と秘密鍵のペアを登録してあげます。
###動作確認
準備が整ったので、きちんと動くか確認してみます。
my-test-app
への変更をpushし、Slackからプルリクエストをつくり、それをGitHubのWEBコンソールでマージしてみましょう。
ちゃんとCircleCIのビルドが走り、以下のようにCapistranoが実行され、ビルドが成功すればOKです。
##CircleCIからSlackへデプロイ通知を送る
最後に、デプロイが完了した旨をSlackに通知してあげる設定を行います。
まずはSlackのSlackのWEBコンソールから[Integration] > [add new Integration] で「Incoming WebHooks」をインストールします。
ここでchannelを選択する必要がありますが、ここで指定した以外のchannelにも通知を送ることが可能なので適当に選んでも問題ないです。
インストールすると通知に必要なトークンが発行されます。
次に、my-test-app
内の前に作ったdeployment-to-production.shに通知の命令を追加します。
#!/bin/bash
bundle exec cap production deploy BRANCH_NAME=deployment/production
#これを追記
curl -X POST --data-urlencode 'payload={"channel": "#wanko-room", "username": "wanko(deploy)", "text": "production環境へのデプロイ完了しました。"}' https://qwintet.slack.com/services/hooks/incoming-webhook?token=xxxxxxxxxxxx#先ほど得た通知用トークン
これで準備完了です。ここまでの内容をpushし、先ほどと同じように、Slackからプルリクエストをつくり、それをGitHub上でマージしてみましょう。
CircleCIによる自動テスト、デプロイの後に以下のようにSlackに通知がくれば成功です。