😀

[Rails] CircleCIでRubocop・RSpecを実施しCapistranoを走らせAWS(EC2)に自動で

2021/01/21に公開

#はじめに

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

#前提

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

#開発環境

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

#完成コード

.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ファイルを作成します。

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


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

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

CircleCI 公式ドキュメント テスト メタデータの収集

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ジョブ

.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さんに怒られてしまいました。

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

.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

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

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

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

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

プッシュ時にRSpec+Rubocopを自動でするようにCircleCIでbuildする【Rails】

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

CircleCI + Capistrano + AWS(EC2) + Railsで自動デプロイしてみた

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

deployジョブ

.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

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

Workflows

.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

CircleCI 公式ドキュメント テスト メタデータの収集

公式ドキュメント デプロイの構成

初心者向け! Rails6+CircleCI+Capistrano+AWS(EC2)で自動デプロイ

CircleCI + Capistrano + AWS(EC2) + Railsで自動デプロイしてみた

Discussion