CircleCI経由でRailsアプリをデプロイ


最近[CircleCI](https://circleci.com/)もprivate repoのビルドが無料になった。（1コンテナまで）
せっかくなので使ってみようということで、
Railsアプリのビルド実行に使うサービスを[wercker](http://wercker.com/)から乗り換えてみた。その設定などのメモ。

[Continuous Integration and Deployment on CircleCI just got better: now it’s free. | The Circle Blog](http://blog.circleci.com/continuous-integration-and-deployment-on-circleci-just-got-better-now-its-free/)

# 設定ファイル
他のCIサービスと同じく、基本的にRailsプロジェクトのルートディレクトリに置いたyamlファイル(`circle.yml`)に記述していく。
設定については、ドキュメント見れば詳しく書いている。
[Configuring CircleCI - CircleCI](https://circleci.com/docs/configuration)

凝ったことをする必要がなければ、そんなに設定をいっぱい書かずともビルドとデプロイができる印象。werckerより楽だった。

今のところ、こんな感じの設定にしている。

```yaml:circle.yml
machine:
  timezone:
    Asia/Tokyo
  ruby:
    version: 2.1.3

dependencies:
  pre:
    - sudo pip install awscli

deployment:
  staging:
    branch: deploy-staging
    commands:
      - sh script/deploy-staging.sh:
          timeout: 1500
  production:
    branch: deploy-production
    commands:
      - sh script/deploy-production.sh:
          timeout: 1500
```

CircleCIでのビルドは以下の6つののフェーズに分かれており、それを上記の設定ファイルに書いていくようだ。

- machine
- checkout
- dependencies
- database
- test
- deployment

また、以下のキーワードを書いておくと、
各フェーズでCircleCIが実行してくれるコマンドをオーバーライドしたり、前後に他の作業を差し込んだりすることができる。

- pre
- override
- post

さらに、各コマンドにはオプションのようなものを付けて実行することが可能。

- timeout
- environment

など。（今回はtimeoutのみ利用）

## 各フェーズの超ざっくりした説明

### machine
ビルドに使うVMのセッティング。
VMのタイムゾーンの指定と、利用するRubyのバージョンだけ指定。

### checkout
コードをcheckoutするときの設定。基本的にはデフォルトのままで良さげなので、今回はノータッチ。

### dependencies
VMにデフォルトで入ってるbundlerじゃなくて、最新版を使いたい！とかいうときはここで指定するとヨサソウ。
何も指定しないと`bundle install`のみが実行される。

VMにインストールされているawscliのバージョンがどうやら古い。
後述するが、デプロイ時に新しいバージョンのものを利用するので`pip`でインストールしている。

### database
データベースまわりの設定。
デフォルトでは、テスト環境用の`config/database.yml`を生成し、
`bundle exec rake db:create db:schema:load --trace`を実行してくれる。
ノータッチ。

### test
テスト実行部分。
デフォルトでは`bundle exec rspec --color --require spec_helper spec --format progress`の実行。
そのまま利用。

### deployment
デプロイ実行部分。
staging, productionなどの環境を指定し、どのブランチに`git push`がされるとデプロイを実行するのか書く。
（上記の例なら、deploy-productionブランチにpushされると、production環境へのデプロイが行われる）

デプロイには、`deploy-production.sh`(`deploy-staging.sh`)というシェルスクリプトを利用している。
このとき`rake assets:precompile`などちょっと時間がかかる行程があるので、timeoutを1500sにしている。
※timeoutのデフォルト値は180sで、出力が3分間何も無いと、プロセスが終了されてしまう

# デプロイのスクリプト
CircleCIのdeploymentフェーズで使う、デプロイ用のスクリプト。

```script/deploy-production.sh
#!/bin/sh

set -ex

export AWS_DEFAULT_REGION="ap-northeast-1"

MYSECURITYGROUP=<デプロイ先のセキュリティグループのID>
MYIP=`curl -s ifconfig.me`

aws ec2 authorize-security-group-ingress --group-id $MYSECURITYGROUP --protocol tcp --port 22 --cidr $MYIP/32

bundle exec cap production deploy

aws ec2 revoke-security-group-ingress --group-id $MYSECURITYGROUP --protocol tcp --port 22 --cidr $MYIP/32
```

以下のような流れ。

- どこかのプロセスが失敗した時点でビルド全体が失敗するよう`set`コマンド実行
- `aws`コマンドを使いたいので、環境変数指定
	- AWSのキーペアは、CircleCI側に登録しておく
- ビルドしているコンテナのIPアドレスを取得（`MYIP`）
- SSHログインできるよう、デプロイ先のサーバのセキュリティグループにコンテナのIPアドレスを追加
	- 秘密鍵をCircleCIに登録しておく（渡すのが嫌な人は別の手段が必要ですね...）
	- このとき、元々インストールされてるawscliだとバージョンが古くてコケるぽい
- デプロイ実行
- 先ほど追加したIPアドレスをセキュリティグループから削除

# 通知
Webの設定画面から、チャットアプリと連携できる。SlackやHipchat, Campfireなどは普通に対応している。

ビルドが終わると、こんな通知が来るようになります。

![スクリーンショット 2014-11-27 19.05.41.png](https://qiita-image-store.s3.amazonaws.com/0/1795/04e3d1fc-2a09-e56a-7d58-37f0871cb83b.png "スクリーンショット 2014-11-27 19.05.41.png")

# おわり
（難しいことを全くしていないので当たり前かもしれませんが、）特に躓くことなくデプロイまでできました。コンテナにSSHログインできる機能もあるみたいだし便利ですね。

...werckerに出戻りすることは今のところ全く無さそうです。