CircleCI2.0をRailsアプリに導入してみた

## 概要

`CircleCI`の導入について整理していきたいと思います。
事前知識として、[CircleCIの公式チュートリアル](https://circleci.com/docs/ja/2.0/tutorials/)や他に記事がたくさんあるので、学習には困らないかと思いますが、今回は自分なりに学習したことの整理としてコードを見ていきたいと思います。

【追記】 2021-1-16
[JavaScriptに対応している記事はこちら](https://qiita.com/suzu12/items/808daa56a052f5c76e4b)です！

## CircleCIとは

`CircleCI`とはSaas型のCI/CDサービスのことです。
具体的に言うとGitHubのリポジトリへプッシュしたタイミングで、アプリのビルドやテスト、デプロイなどの処理が自動で実行されるようになります。

## 導入手順

1.CircleCIとGitHubを連携
2.CircleCIで現在作成しているリポジトリ(アプリ)を選択
3.ローカル環境で選択したリポジトリのrootディレクトリに`.circleciディレクトリ`とその中に`config.yml`ファイルを作成する。
4.テスト用に`config/database.yml.ci`を作成する
5.`config.yml`の設定が終わったらCircleCIのリポジトリに戻って**Use Existing Configをクリック、build**を選択
6.GitHubのリポジトリへpush

## CircleCIの設定

私はこのような感じに書きました。

```config:.circleci/config.yml

version: 2
jobs:
  build:
    docker:
      - image: circleci/ruby:2.6.6-node-browsers # 自身のRubyのバージョンに合わせてください
        environment: # 環境変数を使用
          - BUNDLER_VERSION: 2.0.2 # 自身のバンドラーのバージョンに合わせてください
          - RAILS_ENV: 'test'
      - image: circleci/mysql:8.0 # 自身のMySQLのバージョンに合わせてください
        command: [--default-authentication-plugin=mysql_native_password]
        environment:
          - MYSQL_USER: root
          - MYSQL_DB: ci_test

    working_directory: ~/myapp
    
    steps: # コンテナにインストールしていくステップ
      - checkout # インストール開始

      - restore_cache: # キーテンプレートに一致するキーを持つキャッシュを検索
          keys:
            - v1-dependencies-{{ checksum "Gemfile.lock" }}
            - v1-dependencies-

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

      - save_cache: # キャッシュを作成
          paths:
            - ./vendor/bundle
          key: v1-dependencies-{{ checksum "Gemfile.lock" }}

      - run: mv config/database.yml.ci config/database.yml 

      - run: yarn install
      # DB作成
      - run: bundle exec rake db:create
      - run: bundle exec rake db:schema:load
      # テストの実行
      - run:
          name: run tests
          command: |
            mkdir /tmp/test-results
            TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | \
              circleci tests split --split-by=timings)"
            sudo gem install bundler
            sudo gem install rspec
            sudo gem install rspec-core
            bundle exec rspec \
              --format progress \
              --format RspecJunitFormatter \
              --out /tmp/test-results/rspec.xml \
              --format progress \
              $TEST_FILES
      # テスト結果を保存
      - store_test_results:
          path: /tmp/test-results
      - store_artifacts:
          path: /tmp/test-results
          destination: test-results

```

```config:config/database.yml.ci

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

```

## 詳細

#### Authentication plugin 'caching_sha2_password' cannot be loaded

`command: [--default-authentication-plugin=mysql_native_password]`この記述を追加しました。

#### Mysql2::Error: Unknown MySQL error
このエラーはMySQLが見つからないというエラーです。ローカルでは通っていたのだけどと思いつつ、設定を見直してみました。

`database.yml.ciのusernameとdatabase`と`config.ymlのMYSQL_USERとMYSQL_DB`の**整合性**を取らないとこのようにエラーが起きます。

#### テストが通らない

`circleci/ruby:2.6.6-node-browsers`nodeが入っているイメージと`run: yarn install`で解消しました。`-タグ` + `-node`とすることで、ビルド コンテナの状態を固定をすることができ、アップストリームからの想定外の変更を防止できるようです。詳しくはcircleciのイメージの[ベストプラクティス](https://circleci.com/docs/ja/2.0/circleci-images/)を御覧ください。<br>**※今回はタグを付けておりません。**（エラーが起きてしまうため、原因を探っております。。）

## 注意点

- インデントに気をつける
- 一か八かのpushをしない

[こちらの記事](https://blog.vtryo.me/entry/circleci-debug-method)が参考になりました。私は気づくのが遅くポジトリを少々荒らしてしまいました。。

`CircleCI CLI`を使ってpushする前にローカルで文法チェックとjobをテストすることができます。詳しくは記事を御覧ください。


- 何をしているのか理解しながら進める

自分もまだ完全に理解はできておりませんが、**何をしているのか、どのような流れでファイルが実行されるのかということを考えながらやると理解が早まる**かもしれません。

## まとめ

- 導入は情報量が多いため比較的容易。
- しかし、理解するのは時間がかかるため、まずは手を動かして流れを掴んでいく。
- Dockerの知識も必要になるので復習し直す必要がある。


## 参考文献

- [CircleCI公式](https://circleci.com/docs/ja/2.0/tutorials/)
- [Configuring CircleCI](https://circleci.com/docs/2.0/configuration-reference/)
- [CircleCI のビルド済み Docker イメージ](https://circleci.com/docs/ja/2.0/circleci-images/)
- [dockerhub](https://hub.docker.com/r/circleci/ruby)
- [まさかPushデバッグしてないよね？ よく使うCircleCIのデバッグ方法](https://blog.vtryo.me/entry/circleci-debug-method)
- [いまさらだけどCircleCIに入門したので分かりやすくまとめてみた](https://qiita.com/gold-kou/items/4c7e62434af455e977c2)
- [いまさらだけどDockerに入門したので分かりやすくまとめてみた](https://qiita.com/gold-kou/items/44860fbda1a34a001fc1)
- [【CircleCI】設定とエラー対処法　自分用メモ](https://qiita.com/aiandrox/items/babfa4aba0ccf923487c)
- [「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word159.html)

【追記】 2021-1-16
[JavaScriptに対応している記事はこちら](https://qiita.com/suzu12/items/808daa56a052f5c76e4b)です！