Circle CI 2.0 の設定・アップグレード方法 with Rails

## 概要

Circle Ci 2.0 の設定やアップグレードの方法を紹介していきます。具体的な設定内容は、Ruby on Rails を例にしています。

![Screen Shot 2018-01-13 at 11.02.07.png](https://qiita-image-store.s3.amazonaws.com/0/100997/43aa1595-b79c-29c0-1b53-03b6e3c0f5ee.png)

## Version 2.0 の特徴

Version 2.0 の主な変更点を簡単に紹介します。

- スピードがアップした
    - ビルドが早くなった
    - ビルドサイクルが早くなった
- Docker 環境上でテストを実行するようになった
- ローカルで実行できるようになった
- [ワークフロー](https://circleci.com/docs/2.0/workflows/)が導入された

ref. [Launching Today: CircleCI 2.0 Reaches General Availability | CircleCI Blog](https://circleci.com/blog/launching-today-circleci-2-0-reaches-general-availability/)
ref. [CircleCI 2.0 が正式リリースされたので早速移行しました
 | SmartHR Tech Blog](http://tech.smarthr.jp/tech/705)

## 設定方法

### 設定ファイル

Version 1.0 では `circleci.yml` に設定を書いていましたが、2.0 では `.circle/config.yml` に書くことになっています。

※ インデントの数によってエラーが起こるので注意してください。本記事記載のコードをコピペすれば問題なし。

すでに Circle CI を利用されている方は、この設定ファイルを作ることによって、2.0 にアップグレードすることができます。

### Jobs key を指定

では、具体的に設定ファイルの書き方を紹介していきます。設定内容は、[Launching Today: CircleCI 2.0 Reaches General Availability | CircleCI Blog](https://circleci.com/blog/launching-today-circleci-2-0-reaches-general-availability/)を参考にしています。

最初に Jobs key を設定します。これは、テストのビルドプロセスを表しています。
job には build key と Job を実行するためにディレクトリを指定する必要があります。

コードで言うと以下のような感じになります。

```yaml:.circle/config.yml
version: 2
jobs:
  build:
    parallelism: 1 # 並行に実行する数を指定。無料プランだと 1 じゃないと実行できない
    working_directory: ~/circleci-demo-ruby-rails # ディレクトリを指定
```

### Docker コンテナイメージを指定

Docker コンテナイメージを指定します。
environment にて、環境変数を指定しておくのがポイントです。

```yaml:.circle/config.yml
version: 2
# ...
    docker:
      - image: circleci/ruby:2.5.0-node
        environment:
          RAILS_ENV: test
      - image: circleci/postgres:9.5-alpine
        environment:
          POSTGRES_USER: circleci-demo-ruby # DB の User 名を決める
          POSTGRES_DB: rails_blog # データベースを指定
          POSTGRES_PASSWORD: ""
```

※ ブラウザテストを行う場合は、 `ruby:2.5.0-node` ではなくて `ruby:2.5.0-node-browsers` を指定しましょう！！
ref. [CircleCI 2.0 Capybara feature specs - Selenium webdriver with Chrome headless](http://docs.knapsackpro.com/2017/circleci-2-0-capybara-feature-specs-selenium-webdriver-with-chrome-headless)

### Steps を設定していく

Steps を設定していきます。Steps とは 「Job の中で何を実行していくのか」という手順を作るようなものです。
Steps ではまず Checkout を実行します。

> [Checkout] tells our build to checkout our project code into the working directory.

```
steps:
  - checkout
```

### 依存ライブラリをキャッシュしておく

checkout 後は、具体的な step を指定していきましょう。Rails 環境を動かすには、ライブラリをインストールしないといけないので、これをやりましょう。

```
steps:
  # ...
  - run:
      name: Bundle Install
      command: bundle install --path vendor/bundle

```

これだけでもいいのですが、キャッシュを利用したほうが早いので、以下のように変更しましょう。

```yaml:.circle/config.yml
steps:
  # ...

  # キャッシュを使う
  - restore_cache:
      keys:
        - rails-demo-bundle-v2-{{ checksum "Gemfile.lock" }}
        - rails-demo-bundle-v2-

  - run:
      name: Bundle Install
      command: bundle install --path vendor/bundle

  # キャッシュを保存
  - save_cache:
      key: rails-demo-bundle-v2-{{ checksum "Gemfile.lock" }}
      paths:
        - vendor/bundle
```

※ 初回実行時や Gemfile.lock に変更があった場合はキャッシュは利用されません。

webpacker や yarn 使っている場合は、以下も追加しておきましょう。

```yaml:.circle/config.yml
steps:
  # ...

  - restore_cache:
      keys:
        - rails-demo-yarn-{{ checksum "yarn.lock" }}
        - rails-demo-yarn-

  - run:
      name: Yarn Install
      command: yarn install --cache-folder ~/.cache/yarn

  - save_cache:
      key: rails-demo-yarn-{{ checksum "yarn.lock" }}
      paths:
        - ~/.cache/yarn
```

### データベースをセットアップ

これでライブラリはいろいろ入ったので、次はデータベースの設定をしましょう。

```yaml:.circle/config.yml
steps:
  # ...

  # Database setup
  - run:
      name: Wait for DB
      command: dockerize -wait tcp://localhost:5432 -timeout 1m

  - run:
      name: Database setup
      command: bundle exec rake db:create db:schema:load --trace
```

### テストを実行

ライブラリが入って、データベースが出来たので、いよいよテストを実行してあげましょう！
今回は、rspec と rubocop を実行してあげました。

```yaml:.circle/config.yml

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

```

#### assets:precompile

feature spec にて最初のテストが落ちることがあったのですが、assets compile が終わっていないのが原因でした。なので、rspec 実行前に以下を追加しました。

```yaml:.circle/config.yml
steps:
  # ...
      - run:
          name: Precompile assets
          command: bundle exec rake assets:precompile
```

### Push して終了

以上で設定は終了です。Push して、CircleCI 上で確認しましょう。
※ 2.0 からローカルでも確認できるようになりました。

### 全コード

```yaml:.circle/config.yml

version: 2
jobs:
  build:
    parallelism: 3
    working_directory: ~/circleci-demo-ruby-rails
    docker:
      - image: circleci/ruby:2.5.0-node
        environment:
          RAILS_ENV: test
      - image: circleci/postgres:9.5-alpine
        environment:
          POSTGRES_USER: circleci-demo-ruby
          POSTGRES_DB: rails_blog
          POSTGRES_PASSWORD: ""
    steps:
      - checkout

      # Restore bundle cache
      - restore_cache:
          keys:
            - rails-demo-bundle-v2-{{ checksum "Gemfile.lock" }}
            - rails-demo-bundle-v2-

      - run:
          name: Bundle Install
          command: bundle install

      # Store bundle cache
      - save_cache:
          key: rails-demo-bundle-v2-{{ checksum "Gemfile.lock" }}
          paths:
            - vendor/bundle

      # Only necessary if app uses webpacker or yarn in some other way
      - restore_cache:
          keys:
            - rails-demo-yarn-{{ checksum "yarn.lock" }}
            - rails-demo-yarn-

      - run:
          name: Yarn Install
          command: yarn install --cache-folder ~/.cache/yarn

      # Store yarn / webpacker cache
      - save_cache:
          key: rails-demo-yarn-{{ checksum "yarn.lock" }}
          paths:
            - ~/.cache/yarn

      - run:
          name: Wait for DB
          command: dockerize -wait tcp://localhost:5432 -timeout 1m

      - run:
          name: Database setup
          command: bundle exec rake db:create db:schema:load --trace

      # Run rspec in parallel
      - run:
        command: |
          bundle exec rspec --profile 10 \
                            --out test_results/rspec.xml \
                            --format progress \
                            $(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)

```


## 参考文献

[Launching Today: CircleCI 2.0 Reaches General Availability | CircleCI Blog](https://circleci.com/blog/launching-today-circleci-2-0-reaches-general-availability/)
[CircleCI 2.0 が正式リリースされたので早速移行しました
 | SmartHR Tech Blog](http://tech.smarthr.jp/tech/705)=
[Language Guide: Ruby | CircleCI 2.0](https://circleci.com/docs/2.0/language-ruby/)
[CircleCI 2.0 Capybara feature specs - Selenium webdriver with Chrome headless](http://docs.knapsackpro.com/2017/circleci-2-0-capybara-feature-specs-selenium-webdriver-with-chrome-headless)