Slack / Hubot / GitHub / CircleCI によるChatOpsなデプロイ方法

  • 550
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

概要

Slack / Hubot / GitHub / CircleCI などをつかってChatOpsにチーム開発できるフローをつくったので、ChatOpsによるデプロイ方法を中心にその方法をまとめてみます。

ChatOpsの主役であるチャットアプリには今回Slackを使いました。
HipChatでも同じように出来ますが、Slackの方がUIが優れていており、外部サービスとの連携も洗練されていたのでこちらを選択しました。

ChatOpsな環境の概要

Untitled (1).png

  1. SlackとHubot(PaaSであるheroku上にデプロイ)を連携させる
  2. SlackからHubot経由でGitHubにプルリクエストをつくる
  3. GitHub上の変更を監視し、CircleCIでテストを実施
  4. デプロイ用のブランチに変更があった場合(GitHubのWEBコンソールでデプロイ用ブランチへのプルリクエストをマージした場合)、CircleCI上でCapistranoを実行し、デプロイ実施
  5. デプロイが完了したら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に以下を追記します

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

スクリーンショット 2014-09-06 18.13.49.png
herokuのアプリ管理画面

スクリーンショット 2014-09-06 18.14.18.png
Add-onsリスト

herokuにSlackとの連携で必要な環境変数を設定してあげます。
この値はSlackのWEBコンソールから[Integration] > [add new Integration] からHubotを選択してインストールすると表示されます

sk-スクリーンショット_2014-09-06_18_30_10.png

この値をそれぞれheroku側のWEBコンソールより設定してあげます。

zz_スクリーンショット_2014-09-06_18_49_21.png

コマンドラインから設定したい場合は以下のようにします。

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を入力します。

zz_スクリーンショット_2014-09-06_19_02_12.png

SlackからHubotを呼んでみる

SlackとHubotの連携の準備が整ったので、いよいよSlackからHubotを呼び出してみます。
適当にChannelを作って、wanko time などとメッセージを送ってみましょう。このwankoの部分はさきほどherokuに指定したHUBOT_SLACK_BOTNAMEに合わせて置き換えてください。
以下のように、hubotから返事がこれば成功です。
ちなみに、デフォルトではロボットのアイコンになってしまうので、今回はかわいいワンコのアイコンに変えています(SlackのWEBコンソールから変更可能)

スクリーンショット 2014-09-06 19.22.54.png

SlackからHubot経由でGitHub上にプルリクエストを作る

ここまでで、Slackからheroku上にデプロイされたhubotを呼び出すことができました。
次は、SlackからHubotに指令をだして、GitHubにあるレポジトリに対してプルリクエストを作ることができるようにしていきます。

プルリクエストを送るレポジトリをGitHub上に用意する

ここではプルリクエストを送るテスト用として、READMEしかないレポジトリ(my-test-app)をつくります。
プルリクが作れるようにmasterブランチの他にdeployment/productionブランチをつくって、masterブランチ上でREADME.mdを直接編集しておきます(両者のブランチに差分がないとプルリクエストがつくれない為)。

スクリーンショット 2014-09-06 20.33.40.png

これで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権限を付与しました。ここで生成されたアクセストークンをメモっておきます(一度しか表示されないので注意)。

zz_スクリーンショット_2014-09-06_20_16_29.png

HubotにGitHubAPIを利用したスクリプトを用意する

Hubotのスクリプトカタログ( https://hubot-script-catalog.herokuapp.com/ ) に色々サンプルがあり、GitHub関連のも多数ありましたが、プルリクエストを作るものは無かったので、サンプルを参考にしながら実装しました。

Hubotレポジトリのscriptsディレクトリ以下にgithub-create-pull.coffeeのような適当な名前のスクリプトを追加します(scripts以下に置いておくだけでHubotが勝手に読み込んでくれます)。

実際のコードは以下のようにしました。

https://gist.github.com/s-kiriki/d18fd2be18040e0718d6

ただし、このスクリプトはgithubot(https://github.com/iangreenleaf/githubot )というプラグインに依存しているので、こちらをHubotレポジトリにインストールしておく必要があります。

npm install githubot --save

また、環境変数のHUBOT_GITHUB_TOKENを設定しておく必要があるので、Hubotレポジトリのbin/hubotに以下を追記します(execコマンドを発行している部分より上に書くこと!)。

bin/hubot
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レポジトリにプルリクエストを作る準備が整ったので、実際に実行してみます。以下のようになれば大成功です。

スクリーンショット 2014-09-06 20.44.53.png

deploy my-test-app/master into deployment/production #Slackに打ったコマンド

GitHub側にもプルリクエストがちゃんとできているか確認してみましょう。

スクリーンショット 2014-09-06 20.46.58.png

ちゃんとできていますね。
余談ですが、このプルリクエストをつくったワンコ(wanko-qwt)とSlack上で返事してくれるワンコ(wanko)の実態は全く別物です。それを分かりやすくするため、ここではあえてアイコン画像を変えていますが、実際には同じアイコンに設定し、同じワンコが頑張ってチームのために働いてくれている感じにしています。

CircleCIの設定

ここまでSlack上からHubotを経由してGitHub上にプルリクエストをつくるところまでを行ってきました。
続いては、CircleCIの設定を行っていきます。

CircleCIのWEBコンソール画面で[Add Project]からCI対象のプロジェクトを選びます(今回は先ほどつくったmy-test-app)。

プロジェクトを追加すると最初のテストが実行されますが、今はテストがないので「No Test」となりビルドが失敗してしまいます。

zz_スクリーンショット_2014-09-08_11_35_41.png

今回はダミーのテストを追加してビルドを成功させます。

my-test-appレポジトリ直下にcircle.ymlというファイルをつくり、以下のようにします。

circle.yml
test:
  override:
    - ./dummy_test_script.sh

dummy_test_script.shという空ファイルも実行権限を付けて追加しておきます。

dummy_test_script.sh
touch dummy_test_script.sh
chmod a+x dummy_test_script.sh

この変更をレポジトリにpushすると自動でビルドが走り、今度は成功するはずです。

zz_スクリーンショット_2014-09-08_11_57_14.png

CircleCI上でCapistranoを実行し、デプロイ実施

ここまでで、CircleCIでmy-test-appへの更新を監視し自動でテストが走るようになりました。
次は、デプロイ用のブランチに更新があったタイミングで、CircleCI上でCapistranoを実行し対象ホストにデプロイする設定を行っていきます。

「デプロイ用のブランチに更新があったタイミング」というのは、実際の運用ではGitHubのWEBコンソール画面において、Slackから作られたデプロイ用のブランチへのプルリクエストをマージしたタイミングとなります。

zz_スクリーンショット_2014-09-06_20_46_58.png

Capistranoの設定

つぎにCapistranoの設定を行っていきます。
my-test-appにGemfileを追加し、以下のように指定します。

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.rbconfig/deploy.rbを自分のデプロイしたい環境に合わせて書き換えます。

config/deploy/staging.rb
server 'host_name', user: 'user_name', roles: %w{web}
config/deploy.rb
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に以下を追記します。

circle.yml
deployment:
  production: #これはただのラベルで何でもよい
    branch: deployment/production #ここでブランチを指定。
    commands:
      - deployment-to-production.sh #new file
deployment-to-production.sh
#!/bin/bash
bundle exec cap production deploy BRANCH_NAME=deployment/production

これで deployment/productionブランチのビルドの際にのみ、Capistranoによるデプロイが実施されるようになります。

次に、CircleCI上からデプロイ先のホストに対してCapistranoを実行するために必要な鍵を登録します。
my-app-testの設定ページの「SSH keys」で公開鍵と秘密鍵のペアを登録してあげます。

zz_スクリーンショット_2014-09-08_12_52_45.png

動作確認

準備が整ったので、きちんと動くか確認してみます。
my-test-appへの変更をpushし、Slackからプルリクエストをつくり、それをGitHubのWEBコンソールでマージしてみましょう。
ちゃんとCircleCIのビルドが走り、以下のようにCapistranoが実行され、ビルドが成功すればOKです。

zz_スクリーンショット_2014-09-08_12_55_42.png

CircleCIからSlackへデプロイ通知を送る

最後に、デプロイが完了した旨をSlackに通知してあげる設定を行います。

まずはSlackのSlackのWEBコンソールから[Integration] > [add new Integration] で「Incoming WebHooks」をインストールします。
ここでchannelを選択する必要がありますが、ここで指定した以外のchannelにも通知を送ることが可能なので適当に選んでも問題ないです。
インストールすると通知に必要なトークンが発行されます。

スクリーンショット 2014-09-08 15.00.12.png

次に、my-test-app内の前に作ったdeployment-to-production.shに通知の命令を追加します。

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に通知がくれば成功です。

スクリーンショット 2014-09-08 15.21.56.png