Railsアプリケーションをデプロイ&ロールバックするCapistranoコマンド

## 環境

```
$ cat /etc/system-release
Amazon Linux AMI release 2018.03

# プロジェクトのディレクトリ内にて
$ vim Gemfile.lock
capistrano (3.11.0)
unicorn (5.5.0)

$ rbenv versions
* 2.6.2 (set by /usr/local/rbenv/version)

$ bin/rails -v
Rails 5.2.3
```

## はじめに

開発環境やステージング環境などデプロイ先によって、設定ファイル名はそれぞれ`staging.rb`や`development.rb`になると思います。
今回は`production.rb`という本番環境の設定ファイルを使用して、デプロイ・ロールバックするという前提で話を進めます。

```production.rb
server 'localhost', user: 'banri', roles: %w{ app web db }
set :rails_env, :production
set :unicorn_rack_env, "#{fetch(:rails_env)}"
set :deploy_to, '/var/www/hogehoge（アプリケーション名）/production'
set :repo_url, 'git@github.com:banri/hogehoge.git'
set :branch, :master
```

## デプロイ🚀

### デプロイの疎通確認🔎

```
$ bundle exec cap production deploy:check
```

以下のような結果になれば、デプロイ疎通OKです。

```
$ bundle exec cap production deploy:check
00:00 git:wrapper
      01 mkdir -p /tmp
    ✔ 01 banri@localhost 0.751s
      Uploading /tmp/git-ssh-Hogehoge-local-banri.sh 100.0%
      02 chmod 700 /tmp/git-ssh-Hogehoge-local-banri.sh
    ✔ 02 banri@localhost 0.754s
00:02 git:check
      01 git ls-remote git@github.com:banri/hogehoge.git HEAD
      01 Warning: Permanently added 'github.com,XX.XX.XXX.XX' (RSA) to the list of known hosts.
      01 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx	HEAD
    ✔ 01 banri@localhost 2.833s
00:05 deploy:check:directories
      01 mkdir -p /var/www/hogehoge/production/shared /var/www/hogehoge/production/releases
    ✔ 01 banri@localhost 0.706s
00:05 deploy:check:linked_dirs
      01 mkdir -p /var/www/hogehoge/production/shared/log /var/www/hogehoge/production/shared/tmp/pids /var/www/hogehoge/production/shared/tmp/cache /var/www/hogehoge/production/shared/tmp/sockets /var/www/hoge…
    ✔ 01 banri@localhost 0.745s
00:06 deploy:check:make_linked_dirs
      01 mkdir -p /var/www/hogehoge/production/shared/config
    ✔ 01 banri@localhost 0.760s
```

CapistranoのデプロイはSSHを使用します。接続ができずデプロイの疎通に失敗した場合は、以下のようなエラーを吐きます。

```
cap aborted!
SSHKit::Runner::ExecuteError: Exception while executing as banri@localhost: Authentication failed for user banri@localhost

Caused by:
Net::SSH::AuthenticationFailed: Authentication failed for user banri@localhost
```

SSHのセットアップなどに関しては、[Connecting to GitHub with SSH](https://help.github.com/en/articles/connecting-to-github-with-ssh)を参考にしてください。

### デプロイの実行🚀🚀🚀

```
$ bundle exec cap production deploy
```

[Capistranoの公式ドキュメント](https://capistranorb.com/documentation/getting-started/flow/)によると、上記コマンド1発で以下のコマンドが順番に実行されているそうです。

```
$ bundle exec cap production deploy:starting     - デプロイスタート+全てのデプロイ準備ができているかの確認
$ bundle exec cap production deploy:started      - custom tasksへのデプロイフックの作成開始
$ bundle exec cap production deploy:updating     - 新リリースに伴うサーバーのアップデート → ここではcurrentディレクトリに同期されていない状態
$ bundle exec cap production deploy:updated      - デプロイフックのアップデート
$ bundle exec cap production deploy:publishing   - 新リリースの公開
$ bundle exec cap production deploy:published    - デプロイフックの公開
$ bundle exec cap production deploy:finishing    - デプロイ完了
$ bundle exec cap production deploy:finished     - デプロイフック作成完了
```

`deploy:updating`のコマンド入力後、`/releases`以下を確認するとアプリケーションのバージョンが変わっていないことが分かります。
変わっていない場合は、本日の日付が入ったソースコードのディレクトリが存在しません。

```
$ cd /var/www/hogehoge/production/releases
$ ls -tl
total 20
drwxrwxr-x 16 banri banri 4096 Mar 15 05:57 20190315033559     - 最終更新のファイル名が本日の日付になっていないことを確認
drwxrwxr-x 15 banri banri 4096 Jan 12 03:58 20190112061458
drwxrwxr-x 14 banri banri 4096 Aug  3  2018 20180803054816
drwxrwxr-x 15 banri banri 4096 Jul  4  2018 20180704091354
drwxrwxr-x 14 banri banri 4096 Jul  4  2018 20180704082634
```

## ロールバック🌀

### 1つ前のリリース状態へロールバック🌀

```
$ bundle exec cap production deploy:rollback
```

ロールバックも同様に、上記コマンド1発で以下のコマンドが順番に実行されているそうです。

```
$ bundle exec cap production deploy:starting
$ bundle exec cap production deploy:started
$ bundle exec cap production deploy:reverting              - 旧リリースへサーバーの巻き戻し
$ bundle exec cap production deploy:reverted               - デプロイフックの巻き戻し
$ bundle exec cap production deploy:publishing
$ bundle exec cap production deploy:published
$ bundle exec cap production deploy:finishing_rollback     - ロールバック完了
$ bundle exec cap production deploy:finished
```

### 特定のリリース状態にロールバック🌀🌀🌀

`ROLLBACK_RELEASE=`の後に、リリースのディレクトリ名を指定するだけです。

```
$ bundle exec cap production deploy:rollback ROLLBACK_RELEASE=リリースのディレクトリ名（日付）

例えば以下のような感じです。
$ bundle exec cap production deploy:rollback ROLLBACK_RELEASE=20190112061458
```


## 参考

- [Flow](https://capistranorb.com/documentation/getting-started/flow/)
- [Rollbacks](https://capistranorb.com/documentation/getting-started/rollbacks/)
- [Connecting to GitHub with SSH](https://help.github.com/en/articles/connecting-to-github-with-ssh)