CircleCIでRails+MySQLプロジェクトの自動テストを行うための最低限の設定

#これはなに？
- Rails + MySQLで作成したプロジェクトのRspec自動テストを、CircleCIで行いたい！
- そのために最低限必要な、`.circleci/config.yml`の設定方法を紹介します

###環境
- Ruby 2.5.1
- Rails 5.2.1
- CircleCI 2.0

#`.circleci/config.yml`の設定

##デフォルトの設定ファイル

- CircleCIの「Add Project」から、GitHubのプロジェクトを選択し、Languageの設定から「Ruby」を選ぶと、以下のSample .yml Fileが自動で払い出されます (2018年12月現在)

```yaml:.circleci/config.yml
# Ruby CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-ruby/ for more details
#
version: 2
jobs:
  build:
    docker:
      # specify the version you desire here
       - image: circleci/ruby:2.4.1-node-browsers
      
      # Specify service dependencies here if necessary
      # CircleCI maintains a library of pre-built images
      # documented at https://circleci.com/docs/2.0/circleci-images/
      # - image: circleci/postgres:9.4

    working_directory: ~/repo

    steps:
      - checkout

      # Download and cache dependencies
      - restore_cache:
          keys:
          - v1-dependencies-{{ checksum "Gemfile.lock" }}
          # fallback to using the latest cache if no exact match is found
          - v1-dependencies-

      - run:
          name: install dependencies
          command: |
            bundle install --jobs=4 --retry=3 --path vendor/bundle

      - save_cache:
          paths:
            - ./vendor/bundle
          key: v1-dependencies-{{ checksum "Gemfile.lock" }}
        
      # Database setup
      - run: bundle exec rake db:create
      - run: bundle exec rake db:schema:load

      # run tests!
      - run:
          name: run tests
          command: |
            mkdir /tmp/test-results
            TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"
            
            bundle exec rspec --format progress \
                            --format RspecJunitFormatter \
                            --out /tmp/test-results/rspec.xml \
                            --format progress \
                            $TEST_FILES

      # collect reports
      - store_test_results:
          path: /tmp/test-results
      - store_artifacts:
          path: /tmp/test-results
          destination: test-results
```

##変更した箇所

###MySQLのDockerイメージを追加する

サンプルではpostgresが指定されていますが、MySQLに変更します

```
jobs:
  build:
    docker:
      - image: circleci/mysql:5.7
```


###RailsとDBとの接続を行う

接続を行うために必要な環境変数を追加します

```
jobs:
  build:
    docker:
      - image: circleci/ruby:2.5.1-node-browsers
        environment:
          RAILS_ENV: test
          DB_HOST: 127.0.0.1
          DB_USERNAME: 'root'
          DB_PASSWORD: ''
```

設定した環境変数をRailsに反映するために、`config/database.yml`は以下のように設定しておきます

```yaml:config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  host: <%= ENV.fetch("DB_HOST") { 'localhost' } %>
  username: <%= ENV.fetch("DB_USERNAME") %>
  password: <%= ENV.fetch("DB_PASSWORD") %>
  socket: /tmp/mysql.sock

test:
  <<: *default
  database: your_app_name_test
```

###MySQL Dockerイメージの起動を待つ設定を追加する

何度か自動テストを回していると、MySQLが起動する前にテストが走ってしまい、テストが落ちるケースがあったため、以下の設定を追加します

```
steps:
  - run:
      name: Wait for DB
      command: dockerize -wait tcp://127.0.0.1:3306 -timeout 120s
```


###Rubocopの設定を追加する

自動テストと合わせて、Rubocopで静的解析を行いたかったので、以下の設定を追加します

```
steps:
  # run rubocop
  - run:
      name: run rubocop
      command: bundle exec rubocop
```

## 完成した設定ファイル

`working_directory`をアプリケーションの名前に変更しておきます。最終的に以下のような設定ファイルが完成しました

```yaml:.circleci/config.yml
# Ruby CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-ruby/ for more details
#
version: 2
jobs:
  build:
    docker:
      # specify the version you desire here
      - image: circleci/ruby:2.5.1-node-browsers
        environment:
          RAILS_ENV: test
          DB_HOST: 127.0.0.1
          DB_USERNAME: 'root'
          DB_PASSWORD: ''

      # Specify service dependencies here if necessary
      # CircleCI maintains a library of pre-built images
      # documented at https://circleci.com/docs/2.0/circleci-images/
      - image: circleci/mysql:5.7

    working_directory: ~/your_app_name

    steps:
      - checkout

      # Download and cache dependencies
      - restore_cache:
          keys:
          - v1-dependencies-{{ checksum "Gemfile.lock" }}
          # fallback to using the latest cache if no exact match is found
          - v1-dependencies-

      - run:
          name: install dependencies
          command: |
            bundle install --jobs=4 --retry=3 --path vendor/bundle

      - save_cache:
          paths:
            - ./vendor/bundle
          key: v1-dependencies-{{ checksum "Gemfile.lock" }}

      - run:
          name: Wait for DB
          command: dockerize -wait tcp://127.0.0.1:3306 -timeout 120s

      # Database setup
      - run: bundle exec rake db:create
      - run: bundle exec rake db:schema:load

      # run tests!
      - run:
          name: run tests
          command: |
            mkdir /tmp/test-results
            TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"

            bundle exec rspec --format progress \
                            --format RspecJunitFormatter \
                            --out /tmp/test-results/rspec.xml \
                            --format progress \
                            $TEST_FILES

      # collect reports
      - store_test_results:
          path: /tmp/test-results
      - store_artifacts:
          path: /tmp/test-results
          destination: test-results

      # run rubocop
      - run:
          name: run rubocop
          command: bundle exec rubocop

```