【Rails】GithubとCircleCIを連携してcommit時にrspecとrubocopを動かす

# 概要
* 表題まま
 * CircleCIとGithubを連携
 * rspecとrubocopのインストール
 * CircleCIでrspecとrubocopを動かすための設定

# 前提
* githubのアカウントをもっていること
* 既にrailsのプロジェクトがあること
    * Postgresqlをつかった例を説明します
    * Mysqlの場合は適宜読みかえてください。

# 手順
## CircleCIとGithubを連携
こちらを参考に。GitHubのアカウントを既に持っていればポチポチするだけです。

* [Sign Up and Try CircleCI](https://circleci.com/docs/2.0/first-steps/)
* [Enabling GitHub Checks](https://circleci.com/docs/2.0/enable-checks/)
*  [【CircleCI】CircleCI 2.0からはじめる個人での簡単なCI導入方法 - githubとの連携まで](http://tweeeety.hateblo.jp/entry/2018/02/09/195345)

## rspecとrubocopのインストール
* [rubocop](https://github.com/rubocop-hq/rubocop)は静的にコードを解析してくれるのと、コードの整形も見てくれます。また、今回は説明しませんが、 `rubocop -a` と書くとrubocopの設定に従って整形をしてくれます。
* [rspec](https://github.com/rspec/rspec) はrailsのテスト環境です。 rails用のは [rspec-rails](https://github.com/rspec/rspec-rails)です。

まずはインストールします。Gemfileに以下を追加します。

```Gemfile
group :development, :test do
  gem 'rspec-rails'
  gem 'rubocop'
end
```

bundle installします。

```console
bundle install
```

次に rspec-railsのセットアップ

```console
rails generate rspec:install
```

rubocopに必須のセットアップは、特にないです。ただ、 `.rubocop.yml` は必須です。もし、迷うなら、 railsの [.rubocop.yml](https://github.com/rails/rails/blob/master/.rubocop.yml) をコピペ or 参考に作るといいです。

なお、自分のは以下の通りです。

```.rubocop.yml
AllCops:
  Exclude:
    - "tmp/**/*"
    - "config/initializers/*"
    - "vendor/**/*"
    - "db/schema.rb"
    - "node_modules/**/*"
    - "db/migrate/*.rb"
    - "bin/*"
  DisplayCopNames: true
  TargetRubyVersion: 2.6.0

Rails:
  Enabled: true

Style/AndOr:
  EnforcedStyle: conditionals

Style/AsciiComments:
  Enabled: false

Style/Documentation:
  Enabled: false

Style/NumericLiterals:
  Enabled: false

Style/ClassAndModuleChildren:
  Enabled: false

Bundler/OrderedGems:
  Enabled: false

Lint/ShadowedException:
  Enabled: false
```

## CircleCIでrspecとrubocopを動かすための設定
__CircleCIとGithubを連携__ の時点でgithubにcommitと同時にCircleCIのjobが走るようになっています。ただ、当然ながら何もしてないので、 失敗します。（failしましたのメールがgithubのアカウントのメールアドレスに届いているはず）
正常にrspecとrubocopを動かすためには  `.circleci/config.yml` を新規追加/編集します。

CircleCI公式のrailsの例は[こちら](https://circleci.com/docs/2.0/postgres-config/#example-circleci-configuration-for-a-rails-app-with-structuresql)にあります。

で、最終的に使っているのは以下の通り。

```config.yml
# Ruby CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-ruby/ for more details
#
version: 2
jobs:
  rubocop:
    docker:
      - image: circleci/ruby:2.6.0-node-browsers-legacy
        environment:
          RAILS_ENV: test
          POSTGRES_HOST: 127.0.0.1
      - image: circleci/postgres:9.4
        environment:
          POSTGRES_USER: postgres
          POSTGRES_DB: app_test
    working_directory: ~/repo
    steps:
      - checkout
      - restore_cache:
          keys:
            - v1-dependencies-{{ checksum "Gemfile.lock" }}
            # fallback to using the latest cache if no exact match is found
            - v1-dependencies-
      - run: bundle install --jobs=4 --retry=3 --path vendor/bundle
      - run: yarn install
      - save_cache:
          paths:
            - ./vendor/bundle
          key: v1-dependencies-{{ checksum "Gemfile.lock" }}
      # Rubocop
      - run:
          name: Rubocop
          command: bundle exec rubocop

  rspec:
    docker:
      - image: circleci/ruby:2.6.0-node-browsers-legacy
        environment:
          RAILS_ENV: test
          POSTGRES_HOST: 127.0.0.1
      - image: circleci/postgres:9.4
        environment:
          POSTGRES_USER: postgres
          POSTGRES_DB: app_test
    working_directory: ~/repo
    steps:
      - checkout
      - restore_cache:
          keys:
            - v1-dependencies-{{ checksum "Gemfile.lock" }}
            # fallback to using the latest cache if no exact match is found
            - v1-dependencies-
      - run: bundle install --jobs=4 --retry=3 --path vendor/bundle
      - run: yarn install
      - save_cache:
          paths:
            - ./vendor/bundle
          key: v1-dependencies-{{ checksum "Gemfile.lock" }}
      - run: bundle exec rake db:create
      - run: bundle exec rake db:schema:load
      # Rspec
      - run:
          name: Rspec
          command: bundle exec rspec

workflows:
  version: 2
  rubocop_rspec:
    jobs:
      - rubocop
      - rspec:
          requires:
            - rubocop
```

まずimageを、 CircleCIの[docker hub](https://hub.docker.com/r/circleci/ruby/tags/)からえらびます。
今回は2.6.0を使いました。
imageの環境変数は [environment key で指定しました](https://circleci.com/docs/2.0/env-vars/#setting-an-environment-variable-in-a-container)。

[Service container image available at host: localhost](https://circleci.com/docs/2.0/postgres-config/#example-circleci-configuration-for-a-rails-app-with-structuresql) とあるので、 hostには、 `127.0.0.1` と指定します。（ `localhost` でもいいかもしれませんが、試していません。）
`RAILS_ENV: test` はtest環境で起ち上げるためです。


```
      - image: circleci/ruby:2.6.0-node-browsers-legacy
        environment:
          RAILS_ENV: test
          POSTGRES_HOST: 127.0.0.1
```

postgresqlのイメージを指定します。違うバージョンを使っている場合は[こちら](https://hub.docker.com/r/circleci/postgres) から適宜選んでください。
`POSTGRES_USER` と `POSTGRES_DB` はご自分の `config/database.yml` の記載にあわせてください。

```
      - image: circleci/postgres:9.4
        environment:
          POSTGRES_USER: postgres
          POSTGRES_DB: app_test

```

rubocopの実行した後、rspecを実行します。circle ci時間の節約のため、rubocopがfailしたらrspecをやらないように `requires` で rubocopを指定しています。

```
workflows:
  version: 2
  rubocop_rspec:
    jobs:
      - rubocop
      - rspec:
          requires:
            - rubocop
```

databaseの設定は以下の通りです。 `app_xxxx` のところは各自の環境にあわせてください。

```config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: postgres
  password:
  host: <%= ENV['POSTGRES_HOST'] %>

development:
  <<: *default
  database: app_development

test:
  <<: *default
  database: app_test

```

開発環境での `POSTGRES_HOST` は環境変数で指定してあげます。環境変数は[dotenv](https://github.com/bkeepers/dotenv) を使い、開発環境構築にはdockerをつかっていて、 `db` という名前でpostgresqlが起動しているので下記のようにしています。

```.env
POSTGRES_HOST=db
```


あとは、これをcommitしてあげると、CircleCIが動くことを確認して下さい。

* commitすると自動でcheckしてくれます。
[![Image from Gyazo](https://i.gyazo.com/c15741260dfc2004aa699232522cdb3c.png)](https://gyazo.com/c15741260dfc2004aa699232522cdb3c)

* タブ `Checks` にテストの詳細が表示されます。 

[![Image from Gyazo](https://i.gyazo.com/0e462cf87ef6712dc1f30737f3491c31.png)](https://gyazo.com/0e462cf87ef6712dc1f30737f3491c31)


以上、