Capistrano3におけるRailsのデプロイタスクの内部実装

[Capistrano](http://www.capistranorb.com/)はRailsアプリケーション専用のデプロイツールとして生まれたという歴史的な背景から、今までRails用の機能がCoreモジュールに組み込まれていましたが、昨年リリースされたCapistrano3からはそういった特定のドメインに特化した機能がCoreから排除されて別のRubygemsとして提供されるようになりました。

本稿では、それらRailsデプロイまわりの機能について見ていきたいと思います。

### 参考

Capistrano3のデプロイフレームワークについては下記の記事を参照してください。

* [Capistrano3のデプロイフレームワークの使い方 - Qiita](http://qiita.com/yuku_t/items/01c0ec4389db143e27f5)

## capistrano/railsとcapistrano/bundler

具体的にはRailsまわりの機能は[capistrano-rails](https://github.com/capistrano/rails)と[capistrano-bundler](https://github.com/capistrano/bundler)というRubygemsに分割されています。

とりあえずGemfileに入れときましょう。

```rb:Gemfile
group :development do
  gem 'capistrano', '~> 3.0'
  gem 'capistrano-bundler'
  gem 'capistrano-rails'
end
```

そしてCapfileで `require` します。

```rb:Capfile
require 'capistrano/setup'   # おまじない
require 'capistrano/deploy'

require 'capistrano/rails'  # 内部でcapistrano/bundlerをrequireしてる

# 個別に書く場合
require 'capistrano/bundler'  # rails使う場合はbundlerは必須、、ですよね？
require 'capistrano/rails/assets'  # asset:precompileとかが定義されてる
require 'capistrano/rails/migrations'  # db:migrateとかが定義されてる
```

capistrano/railsによってdeploy:compile_assetsとdeploy:migrateが、capistrano/bundlerによってbundler:installがそれぞれ追加されます。

タスク | 内容 | タイミング
----|----|----
[deploy:compile_assets](https://github.com/capistrano/rails/blob/5f112183dad808078a56c8558046d84d182eddf6/lib/capistrano/tasks/assets.rake#L21-L25) | Assetsを1つのファイルにまとめて圧縮する | [deploy:updatedの後](https://github.com/capistrano/rails/blob/5f112183dad808078a56c8558046d84d182eddf6/lib/capistrano/tasks/assets.rake#L48)
[deploy:normalize_assets](https://github.com/capistrano/rails/blob/5f112183dad808078a56c8558046d84d182eddf6/lib/capistrano/tasks/assets.rake#L9-L19) | Assetsのタイムスタンプを更新する | [deploy:compile_assetsの直後](https://github.com/capistrano/rails/blob/5f112183dad808078a56c8558046d84d182eddf6/lib/capistrano/tasks/assets.rake#L51)
[deploy:migrate](https://github.com/capistrano/rails/blob/5f112183dad808078a56c8558046d84d182eddf6/lib/capistrano/tasks/migrations.rake#L5-L14) | DBのmigrationを実行する | [deploy:updatedの後](https://github.com/capistrano/rails/blob/5f112183dad808078a56c8558046d84d182eddf6/lib/capistrano/tasks/migrations.rake#L16)
[bundler:install](https://github.com/capistrano/bundler/blob/f1b70e2f6ff565f377eee851a597ff89fe9d9c4d/lib/capistrano/tasks/bundler.cap#L2-L31) | Bundlerを実行する | [deploy:updatedの後](https://github.com/capistrano/bundler/blob/f1b70e2f6ff565f377eee851a597ff89fe9d9c4d/lib/capistrano/tasks/bundler.cap#L45)

と、こんな感じでcapistrano/railsやcapistrano/bundlerを `require` すると自動的にcapistrano/frameworkのフックに必要なタスクがぶら下がって、デプロイプロセスが動くようになっています。

## Unicornをリロードする

後はこうしてサーバ上に展開された新しいアプリケーションが動作するようにUnicornをリロードするだけです。Unicornのタスクを記述する際は @satococoa さんの投稿が参考になります。

* [unicorn + rails 用 Capistrano 3 の設定ファイル - Qiita](http://qiita.com/satococoa/items/9b0cc416ffc042680b9b)

仮にこちらの記事のようにunicorn:restartタスクを作ったのなら、あとはこれをdeployタスクの中で実行するだけです。v3.0まではdeployタスクを実行後に自動的にdeploy:restartというタスクが実行されるので、そこの中で`invoke`します。v3.1移行は実行されないので、publishingタスクの後で実行されるように設定します。

```rb:config/deploy.rb
namespace :deploy do
  after :publishing, :restart

  desc 'Restart application'
  task :restart do
    invoke 'unicorn:restart'
  end
end
```

これで `cap staging deploy` を実行すればデプロイ完了後にUnicornが自動的に再起動されるようになります。