[Rails] CircleCIでRubocop・RSpecを実施しCapistranoを走らせAWS(EC2)に自動でプロイする方法

#はじめに

CircleCIをポートフォリオに組み込みデプロイの自動化はしたものの、テストの自動化は行なっていなかったので、そちらの実装ができたので、記事にしていこうと思います。

#前提

- テストを実装済み(RSpec)
- Rubocop導入済み
- EC2にデプロイ済み
- 開発環境にDockerを用いている

#開発環境

- Ruby 2.6.5
- Rails6
- MySQL 5.6.50
- Docker
- docker-compose
- Capistrano(自動デプロイツール)

#完成コード

```ruby:.circleci/config.yml
version: 2.1

orbs:
  ruby: circleci/ruby@1.1.0

jobs:
  build:
    docker:
      - image: circleci/ruby:2.6.5-node-browsers
        environment:
          BUNDLER_VERSION: 2.1.4
    steps:
      - checkout
      - ruby/install-deps

  test:
    parallelism: 3
    docker:
      - image: circleci/ruby:2.6.5-node-browsers
        environment:
          DB_HOST: 127.0.0.1
          RAILS_ENV: test
          BUNDLER_VERSION: 2.1.4
      - image: circleci/mysql:8.0
        command: --default-authentication-plugin=mysql_native_password
        environment:
          MYSQL_ALLOW_EMPTY_PASSWORD: "true"
          MYSQL_ROOT_HOST: "%"

    steps:
      - checkout
      - ruby/install-deps
      - run: yarn install
      - run: mv config/database.yml.ci config/database.yml
      - run:
          name: Wait for DB
          command: dockerize -wait tcp://localhost:3306 -timeout 1m
      - run: bundle exec rake db:create
      - run: bundle exec rake db:schema:load
      - run:
          name: RuboCop
          command: bundle exec rubocop
      - run: bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
      - run: mkdir ~/rspec
      - run:
          command: bundle exec rspec --format progress --format RspecJunitFormatter -o ~/rspec/rspec.xml
          when: always
      - store_test_results:
          path: ~/rspec

  deploy:
    docker:
      - image: circleci/ruby:2.6.5-node-browsers
        environment:
          BUNDLER_VERSION: 2.1.4
    steps:
      - checkout
      - ruby/install-deps
      - add_ssh_keys:
          fingerprints: "xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx"
      - deploy:
          name: Capistrano deploy
          command: bundle exec cap production deploy

workflows:
  version: 2
  build_accept_deploy:
    jobs:
      - build
      - test:
          requires:
            - build
      - deploy:
          requires:
            - test
          filters:
            branches:
              only: master


```

解説をすると、環境を指定するところでは`test`環境を指定します。
そして、DBも`test`環境に合わせるため`configディレクトリ`に`database.yml.ciファイル`を作成します。

作成したら以下のように編集しましょう。

```config/database.yml.ci

test:
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: 'root'
  port: 3306
  host: '127.0.0.1'
  database: ci_test

```

このように`test`環境用のDBを設定できればCircleCIでの環境構築は終了です。

ここからは実際にテストをするための準備に取り掛かります。コードでいうと`test`(`testジョブ`)の部分に当たります。
主に公式を参考にして作業しましたので、公式も参考にしてください。

> [CircleCI 公式ドキュメント 言語ガイド: Ruby](https://circleci.com/docs/ja/2.0/language-ruby/)

また、その際にCircleCI用にRSpecの`rspec_junit_formatter`というGemをインストールする必要があります。
こちらも公式に書いてあります。

>[CircleCI 公式ドキュメント テスト メタデータの収集](https://circleci.com/docs/ja/2.0/collect-test-data/#rspec)

```ruby:Gemfile
group :test do
  # Adds support for Capybara system testing and selenium driver
  gem 'capybara', '>= 2.15'
  gem 'selenium-webdriver'
  # Easy installation and use of web drivers to run system tests with browsers

　# rspec_junit_formatterをgroup :test do内に記述
  gem 'rspec_junit_formatter'
  gem 'webdrivers'
end
```

忘れずに`bundle install`をしてサーバーの再起動を行いましょう。


これで準備が整いました。
`test`の部分を見ていきましょう。

## testジョブ

```ruby:.circleci/config.yml
test:
  parallelism: 3
    docker:
      - image: circleci/ruby:2.6.5-node-browsers
        environment:
          DB_HOST: 127.0.0.1
          RAILS_ENV: test
          BUNDLER_VERSION: 2.1.4
      - image: circleci/mysql:8.0
        command: --default-authentication-plugin=mysql_native_password
        environment:
          MYSQL_ALLOW_EMPTY_PASSWORD: "true"
          MYSQL_ROOT_HOST: "%"

    steps:
      - checkout
      - ruby/install-deps
      - run: yarn install
      - run: mv config/database.yml.ci config/database.yml
      - run:
          name: Wait for DB
          command: dockerize -wait tcp://localhost:3306 -timeout 1m
      - run: bundle exec rake db:create
      - run: bundle exec rake db:schema:load
      - run:
          name: RuboCop
          command: bundle exec rubocop
      - run: bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
      - run: mkdir ~/rspec
      - run:
          command: bundle exec rspec --format progress --format RspecJunitFormatter -o ~/rspec/rspec.xml
          when: always
      - store_test_results:
          path: ~/rspec
```

この記述でテストを実行することができます。
ただ、自分の場合はテスト時に以下のエラーが出ました。

`Webpacker::Manifest::MissingEntryError`というエラーが出て、コンパイルができないとRSpecさんに怒られてしまいました。

ということで`steps`で`yarn install`コマンドを実行するように追記しました。

```ruby:.circleci/config.yml
   steps:
      - checkout
      - ruby/install-deps
      - run: yarn install
      - run: mv config/database.yml.ci config/database.yml
      - run:
          name: Wait for DB
          command: dockerize -wait tcp://localhost:3306 -timeout 1m
      - run: bundle exec rake db:create
      - run: bundle exec rake db:schema:load
      - run:
          name: RuboCop
          command: bundle exec rubocop
      - run: bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
      - run: mkdir ~/rspec
      - run:
          command: bundle exec rspec --format progress --format RspecJunitFormatter -o ~/rspec/rspec.xml
          when: always
      - store_test_results:
          path: ~/rspec
```

これでテストが上手く通れば、デプロイが自動で行われます。
成功するとGUI上でこのように表示されます。

![d68ba1f5716b6185acde3f68447f6009.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/879778/3f4daf95-5820-5ed8-19dd-f60050dad8ab.png)

ちなみに、このテスト実行時、Rubocopでのエラーが起こることがあるようです。

その場合は`rubocop.yml`に記述を加えます。

```ruby:rubocop.yml
AllCops:
  TargetRubyVersion: # 自分のRubyのバージョン
```

このように記述するとエラーが解決できるようです。
詳しくは下記の記事を参考にしてみてください。

>[プッシュ時にRSpec+Rubocopを自動でするようにCircleCIでbuildする【Rails】](https://qiita.com/HiMinmeg/items/701c5987ca60c1d46672)

ちなみに、`.circleci/config.yml`の記述などは以下の記事も非常にわかりやすいので参考にしてみてください。

> [CircleCI + Capistrano + AWS(EC2) + Railsで自動デプロイしてみた](https://qiita.com/YK0214/items/98bbdf7ce25c557c77a3)

ということで、残すはデプロイということなので、そこも見ていきましょう。

## deployジョブ

```ruby:.circleci/config.yml
deploy:
    docker:
      # 自分のRubyのバージョンを指定
      - image: circleci/ruby:2.6.5-node-browsers
        environment:
　　　　　　# ローカルでインストールされているbundlerのバージョンを指定
          BUNDLER_VERSION: 2.1.4
    steps:
      - checkout
      - ruby/install-deps
      - add_ssh_keys:
          fingerprints: "xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx"
      - deploy:
          name: Capistrano deploy
          command: bundle exec cap production deploy
```

この辺は僕も記事にしているのでそちらのほうが参考になるかなと思います。ここはほぼ公式どおりなのでそちらを読み進めてもらったほうがいいかなと、下記を参考にしてみてください。

 >- [初心者向け! Rails6+CircleCI+Capistrano+AWS(EC2)で自動デプロイ](https://qiita.com/sc30gsw/items/fa475d22b609600bf7f6)

>- [公式ドキュメント デプロイの構成](https://circleci.com/docs/ja/2.0/deployment-integrations/)

## Workflows

```ruby:.circleci/config.yml
workflows:
  version: 2
  build_accept_deploy:
    jobs:
      - build
      - test:
          requires:
            - build
      - deploy:
          requires:
            - test
          filters:
            branches:
              only: master
```
Gitのmasterブランチにpush・mergeされるたびにCircleCIが走って、CI/CDしてくれるようルールを決めているような感じです。

以上で、RailsとAWSのCI/CDの実装は完了です。
参考になれば幸いです。


#参考文献
[CircleCI 公式ドキュメント 言語ガイド: Ruby](https://circleci.com/docs/ja/2.0/language-ruby/)

[CircleCI 公式ドキュメント テスト メタデータの収集](https://circleci.com/docs/ja/2.0/collect-test-data/#rspec)

[公式ドキュメント デプロイの構成](https://circleci.com/docs/ja/2.0/deployment-integrations/)

[初心者向け! Rails6+CircleCI+Capistrano+AWS(EC2)で自動デプロイ](https://qiita.com/sc30gsw/items/fa475d22b609600bf7f6)

[CircleCI + Capistrano + AWS(EC2) + Railsで自動デプロイしてみた](https://qiita.com/YK0214/items/98bbdf7ce25c557c77a3)