CircleCIを初めて導入する【CI編：Rails6, Ruby2.7, MySQL8】

# はじめに

Dockerで仮想環境の構築を学んだので、次はCircleCIを使って
自動テスト（自動ビルドも含む）を実装しました。

CI/CDパイプラインのCD部分は未実装のため、当記事では触れない事とします。

私の場合は、.circleci/config.ymlの設定で複数回失敗しましたが
git pushコマンド後に出るエラー文から一つ一つ修正していけば
問題なく通るようになりました。

ビビらず、仮説を立てながら実装すれば大丈夫です！
以降、実装に入っていきます。

なお、本記事では
　テスト：RSpec
　コード解析ツール：rubocop
を使用してます。


# １：　CircleCIとGitHubを紐付ける

まず、前提として以下準備は完了しているものとします。
・GitHubに実装しているアプリのリポジトリ作成している
・CircleCIのアカウント作成している（GitHubを使ってサインイン）

では、GitHubの対象リポジトリをCircleCIに紐付けしていきます。

CircleCIログイン後の画面から図解します。

前提作業でGitHub上にリポジトリを作成していれば、
CircleCIサイト側にも参照されるようになっています。

そのため、`Projectタブ`をクリックした上で
対象リポジトリの右側にある`Set Up Projectボタン`を押して進めます。


![スクリーンショット 2021-09-08 14.00.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/86d6dd00-dca3-e2b9-15b5-0f5234dd8dcf.png)


するとポップアップ表示が出現します。
そこで選択肢を選び、`Let's Goボタン`をクリックします。
（ここではCircleCI側で用意しているデフォルト設定のファイルを選択しています。）

![スクリーンショット 2021-10-14 17.52.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/53589ab4-b4e9-6dd9-0687-abcf1c43d834.png)


画面遷移された後、デフォルトの設定ファイル（config.yml）が準備されていることが分かります。
ここでは何も編集せずに、右上`Commit and Runボタン`を押して、前に進めます。

ボタンをクリック後、GitHub側では、masterブランチではなく
異なるブランチからプルリクエストが飛んでいますので、確認しておきましょう。

![スクリーンショット 2021-09-08 14.06.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/5fe8a67f-d4c4-127b-78a5-b355b6d41352.png)

なお、しばらくすると下記のようにCircleCI画面が切り替わり、CIが失敗していることが分かります。
（デフォルト設定から何も修正していないので、想定済みです。）

![スクリーンショット 2021-09-08 13.59.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/e56e3d7e-c3d3-f257-b7fe-f266a6e3fb37.png)

CircleCI側での作業は以上です。

最後に下記２つの手順でローカルで
**`.circleci/config.yml`**が編集できる状態にします。

作業 1 
`GitHub画面に移って、`
`先ほどプルリクエストされたブランチのコードをmasterブランチにマージして`
`GitHub上にコードを反映させます。`
（対象リポジトリにconfig.ymlが作成されている状態）

作業 2
`ローカル環境（ターミナル）で、`
`masterブランチでgit pullコマンドをして`
`GitHub上のコードとローカルのmasterブランチのコードを一致させます。`
（ローカルにconfig.ymlが作成されている状態）


これでローカル内に**`.circleci/config.yml`**が生成されている状態となります。



# ２：　config/database.yml.ciを新規作成する

あえて、設定が重ためな`.circleci/config.yml`は後述とします。
先に一つ目の準備として`config/database.yml.ci`から新規で作成します。
シンプルなのでご安心を。


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

test:
  # データベースをMySQLとした際のデフォルト設定
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

  # 接続するユーザー
  username: 'root'
  # 接続するポート番号
  port: 3306
  # 接続するホスト(ローカルPC)
  host: '127.0.0.1'
  # 各自でデータベース名称を決める
  database: テスト用のデータベース名称

```



# ３：　Gemfileを編集する

二つ目の準備として、Gemfileにrspec_junit_formatterを加えます。
テスト結果をXML形式で表示させる為に、同gemをインストールさせます。
git pushコマンドで自動テストが走った後、CircleCIサイトで閲覧できます。

```ruby:Gemfile

〜〜省略〜〜

group :development, :test do
  gem 'byebug', platforms: %i[mri mingw x64_mingw]
  gem 'factory_bot_rails'

　## rspec_junit_formatter を加える
  gem 'rspec_junit_formatter'

  gem 'rspec-rails'
  gem 'shoulda-matchers'
end

〜〜省略〜〜

```



# ４：　.circleci/config.ymlを編集する

設定箇所が多めの.circleci/config.ymlがやってきました。

文字通り、CircleCIの設定ファイルです。
できるだけ各所コメントを入れています。
各自のアプリに応じて、適宜で変更してください。


```yml:.circleci/config.yml

# CircleCIの設定ファイルのフォーマット指定
# (2 or 2.1 を選択)
version: 2.1

jobs:
  # stepをまとめるjobに名称をつける(1つの場合はbuildとする)
  build:

    # 使用する環境(ここではdockerを選択)
    docker:

      # rubyのdockerイメージ(DockerHubから自身のアプリに合うイメージを選択)
      - image: circleci/ruby:2.7.3-node-browsers
        # railsの実行環境をテスト環境とし、タイムゾーンを東京に指定する
        environment:
          RAILS_ENV: 'test'
          TZ: 'Asia/Tokyo'

      # mysqlのdockerイメージ(同じくDockerHubから適宜選ぶ)
      - image: circleci/mysql:8.0
        # mysql8より認証方式が変更されたので、以前の方式に戻すコマンド
        command: mysqld --default-authentication-plugin=mysql_native_password
        # パスワードなしでも接続を許す
        # ワイルドカード(%)でipアドレス制限をなくす
        environment:
          MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
          MYSQL_ROOT_HOST: '%'

    # イメージをもとにコマンドを実行していく
    steps:
      # GitHubの対象リポジトリからコードを取得
      - checkout

      # キャッシュの読み込み
      # (過去にgemインストールをしていれば、キャッシュを使用して高速起動する)
      - restore_cache:
          keys:
            - v1-dependencies-{{ checksum "Gemfile.lock" }}
            - v1-dependencies-

      # お馴染みのbundle installコマンド
      # (オプションで並列処理して読込を高速化している)
      - run:
          name: install dependencies
          command: |
            bundle install --jobs=4 --retry=3 --path vendor/bundle

      # キャッシュの保存
      # (保存されたキャッシュは次回以降restoreから読み込まれる)
      - save_cache:
          paths:
          - ./vendor/bundle
          key: v1-dependencies-{{ checksum "Gemfile.lock" }}

      # font-awesome(アイコン)をyarn経由でインストール
      # (font-awesomeを使用していない場合、当コマンド不要)
      - run: yarn add @fortawesome/fontawesome-free

      #　config/database.ymlをconfig/database.yml.ciに変更
      # config/database.yml.ciをもとにデータベースを作成
      - run: mv config/database.yml.ci config/database.yml
      - run: bundle exec rake db:create
      - run: bundle exec rake db:schema:load

      # コード解析ツールのrubocopを起動
      - run:
          name: Rubocop
          command: bundle exec rubocop

      # RSpecの設定（コメントアウトではなく別途後述）
      - run:
          name: 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 --format RspecJunitFormatter \
              --out /tmp/test-results/rspec.xml \
              $TEST_FILES

      # テスト結果をCircleCI画面の「TESTS」に表示
      - store_test_results:
          path: /tmp/test-results
      # テスト結果をCircleCI画面の「ARTIFACTS」に表示
      - store_artifacts:
          path: /tmp/test-results
          destination: test-results
      ## (参考)　capybaraスクリーンショットを「ARTIFACTS」に表示
      ## - store_artifacts:
      ##    path: tmp/screenshots
      ##    destination: test-screenshots

```

RSpecコマンド部に関しては以下の通りです。

・テスト結果の保存するディレクトリを作成
・定数TEST_FILESを定義する
　　　1.対象となるRSpecファイルの範囲を指定(例："spec/**/*_spec.rb")
　　　2.テストを分割処理するオプション
・rspecを起動するコマンド
　　　1.形式をprogressとXMLにする
　　　　※別途'rspec_junit_formatter'のgemをインストール
　　　2.出力先を/tmp/test-results/rspec.xmlをする
　　　3.定義したTEST_FILESを実行対象にする

RSpecに関しては、
・CircleCI公式ページ
・RSpecコマンドのオプション
について調べると理解がしやすいかもしれません。

https://circleci.com/docs/ja/2.0/parallelism-faster-jobs/


https://qiita.com/ShunjiKato/items/c95e6cb0fb3523aa693a





# 補足情報：
　.circleci/config.ymlの冒頭で
　dockerのrubyイメージをcircleci/ruby:2.7.3-node-browsersとしてますが
　`-browsers`はブラウザ機能が含まれるものです。

　このイメージを使うと私の場合はRSpecのsystemテストがパスしました。

![スクリーンショット 2021-09-09 14.16.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/bc70585f-3f80-55b3-3e35-70ded4791674.png)

https://page.circleci.com/docs/ja/2.0/circleci-images/



# ５：　GitHubに反映させて、いざ自動テスト！

これで、git pushコマンドをすれば
CircleCIが検知して、RSpecテストが自動で走るようになります。

```zsh:ターミナル

% git status

% git add .

% git commit -m "コメント内容"

% git push origin 現在のブランチ名

```

仮にエラーが出ても、エラー文の中にヒントが隠れていますので
`CircleCIサイトよりGUIで確認して`対処していきます。

■エラーが出ている場合：
`Project => リポジトリ選択　=> Failed => 対象job(buildなど)`
で確認できます。

私の場合は下記のような表示で、RSpecがエラーになっていました。
原因はyarnでfont-awesomeをインストールできていなかった為でした。
(当記事通りにやれば発生しませんが、参考までに載せておきます。)

![スクリーンショット 2021-09-09 13.50.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/c38e628f-d25f-7847-7570-c81a598a7326.png)

また、mysqlコンテナが「ーマーク」は下記参考記事によると
テスト終了後にdockerのセキュリティが働いていてブロックしている為だそうです。

![スクリーンショット 2021-09-09 14.07.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/e1ef0676-e57c-27de-72fd-555c134ed58f.png)


https://qiita.com/ashketcham/items/d870c035feaaac590270



# 参考記事

https://circleci.com/docs/ja/2.0/getting-started/

https://qiita.com/gold-kou/items/4c7e62434af455e977c2

https://qiita.com/spaghetti_man03/items/b2161784065f21cd1645

https://qiita.com/shu1124/items/ed8df69e70bf0b755803



# Dockerで開発環境の構築

なお、Dockerで開発環境を構築する実装は別の下記記事にまとめていますので
参考までに載せておきます。

https://qiita.com/Shuhei_Nakada/items/96bd57c758011bb3c2b4



# CircleCIの自動デプロイ編

CircleCIからcapistranoを介してEC2にデプロイする実装ができましたので、
こちらも参考までに載せておきます。

https://qiita.com/Shuhei_Nakada/items/806fa2986dc60681c964



# 終わりに

~~CircleCIの自動デプロイは未実装なので、これから調査して実装していく予定です。~~
　→簡易的ですが実装できましたので、上記記事で紹介しております。

Dockerであったり、CicleCIであったり仮想環境が概念が出てくると
何が原因でエラーになっているのか難しくなってくるので
Qiitaにアウトプットして自己整理していきます。

最後までお読み頂き、ありがとうございました！