#はじめに
Railsでアプリを作っている初学者です。
アプリ内にCircleCIを使った自動テストを入れたい!と思い、導入してみましたので、その時に詰まったことをまとめました。
同じようにアプリにCircleCIを入れたいなと思っている方の参考になれば嬉しいです!!
また、間違い等がありましたらご指摘いただけますと幸いです。
##バージョン
Ruby:2.6.6
Rails:5.2.4
Mysql:5.7
環境構築にDocker使用
##前提
以下は題名のことをしたい場合&CircleCIを理解する上で必要です!
・Dockerを使用したことがある
・Rspecを導入済
・Rubocopを導入済
・Githubアカウントがある
まず、CircleCIの公式入門ガイドをすることをおすすめします!自分は実際の挙動があまりイメージ出来なかったのですが、これでざっくり理解することができました。
CircleCI入門ガイド:https://circleci.com/docs/ja/2.0/getting-started/
そして入門ガイドをしたところで、CircleCIをアプリに加えてみます。
ルートディレクトリに .circleci フォルダを作成してコンフィグを作る。
そしてデータベースを作る、とできるはず!
#うまくいかなかったパターン
参考:CircleCIでSystemSpec(RSpec)とRubocopを走らせる
https://qiita.com/YK0214/items/bbed63ea7ca5367dae2f
まず、こちらのQiitaの記事を参考にしましたが、自分の環境ではうまくいきませんでした。
ですが、こちらの経緯も記録しておきます。
config.ymlを作る
.circleci\config.yml
version: 2.1
orbs:
ruby: circleci/ruby@1.1.0
jobs:
build:
docker:
- image: circleci/ruby:2.6.6-node-browsers
environment:
BUNDLER_VERSION: 2.1.4
steps:
- checkout
- ruby/install-deps
test:
parallelism: 3
docker:
- image: circleci/ruby:2.5.1-node-browsers
environment:
DB_HOST: 127.0.0.1
RAILS_ENV: test
BUNDLER_VERSION: 2.1.4
- image: circleci/mysql:5.7
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
MYSQL_ROOT_HOST: '%'
steps:
- checkout
- ruby/install-deps
- run: mv config/database.yml.ci config/database.yml
- run:
name: Wait for DB
command: dockerize -wait tcp://localhost:3306 -timeout 1m
- run: bundle exec rake db:create
- run: bundle exec rake db:schema:load
# Run rspec in parallel
- ruby/rspec-test
- ruby/rubocop-check
workflows:
version: 2
build_and_test:
jobs:
- build
- test:
requires:
- build
>引用:CircleCIでSystemSpec(RSpec)とRubocopを走らせる
https://qiita.com/YK0214/items/bbed63ea7ca5367dae2f
database.yml.ciを作る
すでにconfig内にdatabase.ymlがあるけど、それとは別で新規で作ります。
新規のDockerfileを使うのでデータベースも新しくなります。
>```ruby:config\database.yml.ci
test:
adapter: mysql2
encoding: utf8
pool: 5
username: 'root'
port: 3306
host: '127.0.0.1'
database: ci_test
引用:CircleCIでSystemSpec(RSpec)とRubocopを走らせる
https://qiita.com/YK0214/items/bbed63ea7ca5367dae2f
Githubへプッシュして、マージするとCircleCIで自動でBuildされます
失敗している!!!
Bundleのバージョンが違うみたい。
ちょっと変更
version: 2.1
orbs:
ruby: circleci/ruby@1.1.0
jobs:
build:
docker:
- image: circleci/ruby:2.6.6-node-browsers
environment:
BUNDLER_VERSION: 1.17.2
steps:
- checkout
- ruby/install-deps
test:
parallelism: 3
docker:
- image: circleci/ruby:2.5.1-node-browsers
environment:
DB_HOST: 127.0.0.1
RAILS_ENV: test
BUNDLER_VERSION: 2.1.4
- image: circleci/mysql:5.7
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
MYSQL_ROOT_HOST: '%'
steps:
- checkout
- ruby/install-deps
- run: mv config/database.yml.ci config/database.yml
- run:
name: Wait for DB
command: dockerize -wait tcp://localhost:3306 -timeout 1m
- run: bundle exec rake db:create
- run: bundle exec rake db:schema:load
# Run rspec in parallel
- ruby/rspec-test
- ruby/rubocop-check
workflows:
version: 2
build_and_test:
jobs:
- build
- test:
requires:
- build
BUNDLER_VERSION: 1.17.2
に変更して再Push
これでできた!!!と思ってshow all checkをクリックして確認すると、
途中でbuildが止まっています...!
よくよく見たらこんな記載が。
これは有料枠にしろということですね!?
無料枠ではコンテナ1つでないと動かないのですが、このコードは2つのDockerを起動させようとしています。
なので途中で止まっていたんだなあということがわかりました...
というわけで修正を行います
#うまくいったパターン
今度はこちらの記事を参考に、config.ymlを作成します。
エラーがいくつか出たので最終的には細かく修正を加えています。
参考:CicleCIでRspecとRubocop通すまでにつまずいたところとその解決法
https://qiita.com/naota7118/items/056770bcf53136e94788
.circleci/config.yml
CircleCIのバージョンのことで、「2」、「2.0」、「2.1」のうちのどれかを指定します。
version: 2.1
orbs:
ruby: circleci/ruby@1.1.0
jobsは、実行処理の単位です。
jobs:
build:
# DockerでRubyのイメージを作成します。Dockerfileもしくはローカル環境とVersionは合わせること。
docker:
- image: circleci/ruby:2.6.6-node-browsers
environment:
# Dockerで作った、circleCI上で'bundle install'します
BUNDLER_VERSION: 1.17.2
steps:
- checkout
- ruby/install-deps
test:
parallelism: 3
docker:
- image: circleci/ruby:2.5.1-node-browsers
environment:
DB_HOST: 127.0.0.1
RAILS_ENV: test
BUNDLER_VERSION: 2.1.4
- image: circleci/mysql:5.7
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
MYSQL_ROOT_HOST: '%'
steps:
- checkout
- ruby/install-deps
- run: mv config/database.yml.ci config/database.yml
- run:
name: Wait for DB
command: dockerize -wait tcp://localhost:3306 -timeout 1m
- run: bundle exec rake db:create
- run: bundle exec rake db:schema:load
# Run rspec in parallel
- ruby/rspec-test
- ruby/rubocop-check
workflows:
version: 2
build_and_test:
jobs:
- build
- test:
requires:
- build
>引用:CicleCIでRspecとRubocop通すまでにつまずいたところとその解決法
https://qiita.com/naota7118/items/056770bcf53136e94788
公式:CircleCI-Public/circleci-demo-ruby-rails
https://github.com/CircleCI-Public/circleci-demo-ruby-rails/blob/master/config/database.yml
参考:【CircleCI】Railsアプリに導入(設定ファイルについて)
https://qiita.com/Daiki-Abe/items/d90599d904c2b1370d10
というわけで修正
##①bundle exec rake:db migrateを追加
マイグレーションされていないというエラーが出ているので、上記のファイルの中に
`bundle exec rake:db migrate`を追加します
##②細かすぎるgemまで見ているのでRubocopを編集
migrateが無事されましたが、今度はRubocopでエラーがでました。
エラー文は以下。
For more information: https://docs.rubocop.org/rubocop/versioning.html
vendor/bundle/ruby/2.6.0/gems/msgpack-1.3.3/.rubocop.yml: Lint/Eval has the wrong namespace - should be Security
Error: RuboCop found unsupported Ruby version 2.3 in TargetRubyVersion
parameter (in vendor/bundle/ruby/2.6.0/gems/msgpack-1.3.3/.rubocop.yml). 2.3-compatible analysis was dropped after version 0.81.
Supported versions: 2.4, 2.5, 2.6, 2.7, 3.0
Rubocop.ymlでrubyバージョンの指定をすることで解決しました
AllCops:
Rubyバージョン指定
TargetRubyVersion: 2.6
参考:原因と対応「Error: RuboCop found unsupported Ruby version 2.1」
https://blog.mothule.com/ruby/rubocop/ruby-rubocop-found-unsupported-ruby-version
buildには失敗してるけどRubocopは通っています!
次はRSpecですがここでもエラーが出ています。
##③RSpecのmysql2::Error::ConnectionError:を解消する
②のエラーを直したあとにrspecを実行すると、エラーがでるようになりました
rspecの実行結果は以下です。
```terminal
PS C:\Users\> rspec
An error occurred while loading ./spec/features/toppage_spec.rb.
Failure/Error: ActiveRecord::Migration.maintain_test_schema!
Mysql2::Error::ConnectionError:
Unknown MySQL server host 'db' (0)
# ./spec/rails_helper.rb:28:in `<top (required)>'
# ./spec/features/toppage_spec.rb:1:in `<top (required)>'
Top 0 slowest examples (0 seconds, 0.0% of total time):
Finished in 0.00009 seconds (files took 3 minutes 27 seconds to load)
0 examples, 0 failures, 1 error occurred outside of examples
databese.ymlに以下を加えることで解決しました。
test:
<<: *default
database: Music-record_test
host: <%= ENV['MYSQL_ROOT_HOST'] || '127.0.0.1' %>
参考:ローカル環境のCircleCIでMysql2::Error::ConnectionError: Unknown MySQL server host 'db' (-2)が出る
https://qiita.com/mitsu1208g/questions/c9681d1204a1b878f987
##④RSpecのエラー LoadError: cannot load such file -- rspec_junit_formatterの解消
次はCircleCIでのRSpecでエラーがでました。
Error reading historical timing data: file does not exist
Requested weighting by historical based timing, but they are not present. Falling back to weighting by name.
No examples found.
bundler: failed to load command: rspec (/home/circleci/repo/vendor/bundle/ruby/2.6.0/bin/rspec)
LoadError: cannot load such file -- rspec_junit_formatter
/home/circleci/repo/vendor/bundle/ruby/2.6.0/gems/rspec-core-3.9.3/lib/rspec/core/formatters.rb:235:in `require'
/home/circleci/repo/vendor/bundle/ruby/2.6.0/gems/rspec-core-
・
・
・
/home/circleci/repo/vendor/bundle/ruby/2.6.0/gems/rspec-core-3.9.3/lib/rspec/core/runner.rb:45:in `invoke'
/home/circleci/repo/vendor/bundle/ruby/2.6.0/gems/rspec-core-3.9.3/exe/rspec:4:in `<top (required)>'
/home/circleci/repo/vendor/bundle/ruby/2.6.0/bin/rspec:23:in `load'
/home/circleci/repo/vendor/bundle/ruby/2.6.0/bin/rspec:23:in `<top (required)>'
Exited with code exit status 1
CircleCI received exit code 1
Uploading test results
0s
Uploading artifacts
0s
LoadError: cannot load such file -- rspec_junit_formatter
この1文がエラーの原因のようです。
rspec_junit_formatter
がないということで以下の記事を参考にGemを追加します。
参考:CI/CD環境を作った時に起きたエラー備忘録[Rails + CircleCI +Capistrano +AWS]
https://qiita.com/orangeupup90027/items/6f83850d1842adf3c09a
① rspec_junit_formatterがないと言われる
テストを走らせた時に出たエラー
Error reading historical timing data: file does not exist
Requested weighting by historical based timing, but they are not present. Falling back to >weighting by name.
No examples found.
bundler: failed to load command: rspec (/home/circleci/circleci-demo-ruby->rails/vendor/bundle/ruby/2.5.0/bin/rspec)
LoadError: cannot load such file -- rspec_junit_formatter
結論としてはrspec_junit_formatterをgemfileに追加する。
Gemfileにrspec_junit_formatter
を追加します。
group :test do
# Adds support for Capybara system testing and selenium driver
gem 'capybara', '>= 2.15'
gem 'selenium-webdriver'
# Easy installation and use of chromedriver to run system tests with Chrome
# gem 'chromedriver-helper'
gem 'rspec_junit_formatter' #追加
gem 'webdrivers', '~> 3.0'
end
これでGithubにプッシュするとCircleCIの画面はこのようになりました。
長くなりましたが、これでCircleCIでBuildができました!
#最終的なコード
細かな修正を入れた結果が以下です。
※CircleCIはインデントに厳しい&文字列のブロックの別れ方がシビアなので、実際にコードをコピー・記載するときはコメントなしの方が良いです。
# CircleCIのバージョンのことで、「2」、「2.0」、「2.1」のうちのどれかを指定します。
version: 2
jobs:
build:
docker:
- image: circleci/ruby:2.6.6-node-browsers
environment:
- RAILS_ENV: 'test'
- MYSQL_HOST: 127.0.0.1
- MYSQL_USERNAME: 'root'
- MYSQL_PASSWORD: ''
- MYSQL_PORT: 3306
- image: circleci/mysql:5.7
environment:
- MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
- MYSQL_ROOT_HOST: '%'
working_directory: ~/repo
steps:
- checkout
- restore_cache:
keys:
- v1-dependencies-{{ checksum "Gemfile.lock" }}
- v1-dependencies-
- run:
name: install dependencies
command: |
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: bundle exec rake db:create
- run: bundle exec rake db:migrate
- run: bundle exec rake db:schema:load
- run:
name: RuboCop
command: bundle exec rubocop
- 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 \
--format progress \
$TEST_FILES
- store_test_results:
path: /tmp/test-results
- store_artifacts:
path: /tmp/test-results
destination: test-results
test: &default
adapter: mysql2
encoding: utf8
pool: 5
username: <%= ENV.fetch("MYSQL_USERNAME") %>
password: <%= ENV.fetch("MYSQL_PASSWORD") %>
host: <%= ENV.fetch("MYSQL_HOST") %>
port: <%= ENV.fetch("MYSQL_PORT") %>
database: ci_test
ここまでお付き合いいただきありがとうございます!
#参考
【circleCI】Railsアプリでgithubと連携してrubocopとrspecテストを走らせる
https://qiita.com/AK4747471/items/b2161784065f21cd1645
CicleCIでRspecとRubocop通すまでにつまずいたところとその解決法
https://qiita.com/naota7118/items/056770bcf53136e94788
【CircleCI】Railsアプリに導入(設定ファイルについて)
https://qiita.com/Daiki-Abe/items/d90599d904c2b1370d10#databaseymlci%E3%82%92%E4%BD%9C%E6%88%90
【初心者向け】deviseのユーザー登録をRSpecでテストする
https://qiita.com/HiMinmeg/items/37a59cd266c63330797a#%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B32!