Rails6の環境構築を自動でしてくれるシェルスクリプトを作ってみた (2) ~CircleCI導入編~

#はじめに

この記事は以前、私が書いた以下記事の改良版となります。

[Rails6の環境構築を自動でしてくれるシェルスクリプトを作ってみた (1) ~ローカル起動編~](https://qiita.com/watanavi/items/17523ace7d425e192607)

前回は開発環境構築まででしたが、今回はCircleCIによる自動テストまでをできるようにしました。

私の環境は以下の通りです。

| OS                         | 環境  
| ---------------------------|------
| Windows 10 Home 64bit      | Ubuntu 18.04(WSL2)


#構築する環境

前回から重複する部分が多いですが、構築する環境は以下の通りです。
GitHubにプッシュ → CircleCIで自動テストができるようになることをゴールとします。

| 項目　　　   | 使用したもの  | バージョン  
|-------------| ------------ |----------
|言語         | ruby         | 2.6.6    
|Webフレームワーク| rails        | 6.0.2   
|テストフレームワーク|rspec|3.9
|データベース　| MySQL        | 8.0      
|Webサーバ    | Nginx        | 1.17.10  
|APサーバ     | puma         |  4.3.5

コンテナ構成は以下の通りです。

| appコンテナ                 
| ---------------------------
| ruby
| rails
| puma

| dbコンテナ                 
| ---------------------------
| MySQL

| webコンテナ                 
| ---------------------------
| Nginx

#できること

GitHubへコードをpushしたら、CircleCIがそれを検知して、自動的にテストを実行してくれます。

![circleci.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626975/527a1f7c-752f-cfc6-636a-3a61b7a2bd81.jpeg)


今回作成したシェルは以下の通りです。

[今回作成したシェルスクリプト](https://github.com/watanavi/rails_on_docker/blob/master/docker_rails_template_ver2.2.sh)

まずこちらをローカルに落としてきて、`sudo`で実行します。
実行権限が付与されていない場合は`chmod`で実行権限を付与してあげてください。

１０分ほど待って、以下状態になったら実行完了です。

```
app_1  | * Listening on tcp://0.0.0.0:3000
app_1  | * Listening on unix:///myapp/tmp/sockets/puma.sock
app_1  | Use Ctrl-C to stop
```

↑↑↑↑↑↑↑↑↑前回はここまで↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑


自動テストをするために　CircleCI ⇔　GitHub のプロジェクト連携が必要です。
CircleCIのアカウントからポチポチすれば簡単に連携できます。

GitHub へ pushするとCIrcleCI側で自動テストを実行してくれます。

<img width="601" alt="2020-06-06 (1).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626975/899aac26-0aa4-2a93-4eba-cad85f0e84f3.png">



#シェルの内容

###CircleCIの自動テストをする上で変更した点
[前回記事](https://qiita.com/watanavi/items/17523ace7d425e192607)と同様の部分が多いですが、自動テストをする上で変更した点を重点的に記載していきたいと思います。


主な変更点としては以下の通りです。

- CircleCI用のコンフィグファイルを作成
- rspecを導入
- webpacker のコンフィグファイルを編集
- public/packs-test への考慮

###フォルダ構成
ホスト側のファルダ構成もほぼ変わっておりません。
CircleCI用フォルダが追加された程度です。

``` ホスト側
sample
├── docker
│   ├── app
│   │   └── Dockerfile
│   └── web
│       └── Dockerfile
├── docker-compose.yml
├── src
└── .circleci
    └── config.yml
```

###CircleCI用のコンフィグファイルを作成

CircleCI用コンフィグファイルを作成している部分が以下です。

```docker_rails_template.sh
# .circleci/config.yml 作成
echo "make .circleci/config.yml"
mkdir -p .circleci
cat << EOF > .circleci/config.yml
version: 2
jobs:
  test:
    machine:
      image: circleci/classic:edge
    working_directory: ~/repo
    steps:
      - checkout
      - run:
          name: Install Docker Compose
          command: |
            curl -L https://github.com/docker/compose/releases/download/1.19.0/docker-compose-`uname -s`-`uname -m` > ~/docker-compose
            chmod +x ~/docker-compose
            sudo mv ~/docker-compose /usr/local/bin/docker-compose
      - run:
          name: docker-compose up --build -d
          command: docker-compose up --build -d
      - run: sleep 30
      - run:
          name: docker-compose run app rails db:create
          command: docker-compose run app rails db:create
      - run:
          name: docker-compose run app rails db:migrate
          command: docker-compose run app rails db:migrate
      - run:
          name: docker-compose run app bundle exec rspec spec
          command: docker-compose run app bundle exec rspec spec
      - run:
          name: docker-compose down
          command: docker-compose down
 
workflows:
  version: 2
  workflows:
    jobs:
      - test
EOF
```

CircleCIでは、.circleci/config.ymlを読み込んでその通りに処理を実行しています。

今回はCircleCI環境上で`docker-compose`をインストールして、それを元にテストを実行していく形を取っています。

これにより、開発環境 ⇔ テスト環境の差異ほほとんどなくなるので
「開発環境では問題なかったのにテスト環境ではうまく動かない～～～」
といったことが減るのではないかなと思います。

設定ファイル上でやっていることは、

イメージビルド → コンテナ立ち上げ → テスト用データベース作成 → 初回マイグレーション → テスト実行

といった形です。

ローカル環境で`docker-compose`を操作するのと変わらない形でコマンド実行できるので、イメージしやすいかと思います。

###rspecを導入

今回、テストフレームワークとしてrspecを導入します。
railsではminitestが初期導入されていますが、rspecの方が一般的に使われているそうなので、こちらを採用しました。
また、テストデータを作ってくれるFactoryBotも導入しています。

rspecを導入するためにGemfileに追加します。

追加行

- gem "rspec-rails"
- gem "factory_bot_rails"

```Gemfile
group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem "rspec-rails"
  gem "factory_bot_rails"
end
```

###webpacker のコンフィグファイル編集

以下処理で、webpackerのコンフィグファイルを編集します。

```docker_rails_template.sh
# webpacker.yml を編集
echo "edit webpacker.yml"
cat src/config/webpacker.yml |
    sed 's/check_yarn_integrity: true/check_yarn_integrity: false/' > __tmpfile__
cat __tmpfile__ > src/config/webpacker.yml
rm __tmpfile__
```

ここでは、`check_yarn_integrity`の設定を無効にしています。

`check_yarn_integrity`というのは、railsを起動する時などに`yarn`が最新バージョンかどうかをチェックしてくれる機能を有効 or 無効にする設定です。

これが有効になっていると、CircleCI上で`yarn`のバージョンチェックが入り、最新であるのにもかかわらずエラーを吐かれてしまいます。

そのため、この設定を無効にする必要があります。


###public/packs-test への考慮

`public/packs-test`はWebpackerで生成するアセットの配置場所らしいのですが、こちらがないとCircleCI上でテストが実行できません。

そのため、GitHubへのpush対象として含める必要があります。

シェルスクリプト上で以下処理を実行していますが、これをするとsrc配下に`.gitignore`というファイルが自動生成されます。

```
docker-compose run app rails new . --force --database=mysql --bundle-skip
```

`.gitignore`はその名の通りgit管理しない対象を記載するものですが、デフォルトだと`public/packs-test`が記載されているので、これを削除する必要があります。

また、別方法としてCircleCI上で以下コマンドを実行し、プリコンパイルすれば`public/packs-test`が生成されるので、こちらの手段もありだと思います。

```
rails assets:precompile RAILS_ENV=test
```


以上になりますが、何かの参考にしていただければ幸いです。

# 参考記事

以下記事を参考にさせて頂きました。ありがとうございましたm(_ _)m

[丁寧すぎるDocker-composeによるrails5 + MySQL on Dockerの環境構築(Docker for Mac)](https://qiita.com/azul915/items/5b7063cbc80192343fc0)

[いまさらだけどCircleCIに入門したので分かりやすくまとめてみた](https://qiita.com/gold-kou/items/4c7e62434af455e977c2)

[CircleCIでdocker-composeは最強](https://qiita.com/walkers/items/352057493c7c8907b83f)

[RailsアプリへのRspecとFactory_botの導入手順](https://qiita.com/Ushinji/items/522ed01c9c14b680222c)

[使えるRSpec入門・その1「RSpecの基本的な構文や便利な機能を理解する」](https://qiita.com/jnchito/items/42193d066bd61c740612)