とりあえずCIのみで、デプロイとかの処理はしていないです。
CircleCI内にDocker内に環境を作ってRSpecを回すところまでの設定です。
拾い物のconfigファイルを改造してとりあえず動くようにしたものなので、いろいろと足りていないような気はします。そして、ただのメモなので記事として全く整理していません。
環境
CircleCI 2.1
Bundler 2.1.4
Ruby 2.5.3
Rails 5.2.4.2
MySQL 8.0.19
ローカルとDocker内のバージョンは揃えています。
最初の設定
いろいろと不備がある設定です。
version: 2.1
orbs:
ruby: circleci/ruby@0.1.2
jobs:
build:
working_directory: ~/circleci-demo-ruby-rails
docker:
- image: circleci/ruby:2.5.3-node-browsers-legacy
environment:
DB_HOST: 127.0.0.1
RAILS_ENV: test
BUNDLER_VERSION: 2.1.4
- image: circleci/mysql:8.0.19-ram
environment:
MYSQL_USER: root
MYSQL_DB: circle_test
steps:
- checkout
# Restore bundle cache
- restore_cache:
keys:
- rails-demo-{{ checksum "Gemfile.lock" }}
- rails-demo-
- run:
name: Which bundler?
command: bundle -v
- run:
name: bundle install
command: |
bundle install --jobs=4 --retry=3 --path vendor/bundle
# Store bundle cache
- save_cache:
paths:
- ./vendor/bundle
key: v1-dependencies-{{ checksum "Gemfile.lock" }}
# Database setup
- run: cp -v config/database.ci.yml config/database.yml
- run: bundle exec rails db:create
- run: bundle exec rails db:schema:load
# RSpec
- run:
name: run rspec
command: |
bundle exec rspec --profile 10 \
--format RspecJunitFormatter \
--out test_results/rspec.xml \
--format progress \
$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)
# collect reports
- store_test_results:
path: /tmp/test-results
- store_artifacts:
path: /tmp/test-results
destination: test-results
- store_artifacts:
path: tmp/screenshots
destination: test-screenshots
エラー
You must use Bundler 2 or greater with this lockfile.
#!/bin/bash -eo pipefail
bundle install --jobs=4 --retry=3 --path vendor/bundle
You must use Bundler 2 or greater with this lockfile.
Exited with code exit status 20
解決法
# Which bundler?の前に追加
- run:
name: setup bundler
command: |
sudo gem update --system
sudo gem uninstall bundler
sudo rm /usr/local/bin/bundle
sudo gem install bundler
参考:"You must use Bundler 2 or greater with this lockfile" に対応する
Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2 "No such file or directory")
#!/bin/bash -eo pipefail
bundle exec rake db:create
Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2 "No such file or directory")
Couldn't create 'circle_test' database. Please check your configuration.
rake aborted!
Mysql2::Error::ConnectionError: Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2 "No such file or directory")
...
解決法
config/database.ci.yml
を追加する。
default: &default
adapter: mysql2
encoding: utf8mb4
charset: utf8mb4
collation: utf8mb4_general_ci
pool: 5
host: 127.0.0.1
port: 3306
username: root # .circleci/config.yml のMYSQL_USERと揃える。
password:
test:
<<: *default
database: circle_test # .circleci/config.yml のMYSQL_DBと揃える。
Authentication plugin 'caching_sha2_password' cannot be loaded
#!/bin/bash -eo pipefail
bundle exec rails db:create
Authentication plugin 'caching_sha2_password' cannot be loaded: /usr/lib/x86_64-linux-gnu/mariadb18/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory
Couldn't create 'circle_test' database. Please check your configuration.
rails aborted!
Mysql2::Error: Authentication plugin 'caching_sha2_password' cannot be loaded: /usr/lib/x86_64-linux-gnu/mariadb18/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory
解決法
- image: circleci/mysql:8.0.19-ram
command: [--default-authentication-plugin=mysql_native_password] # この行を追加
environment:
MYSQL_USER: root
MYSQL_DB: circle_test
ちなみに、これを変更したcommitでは動かなかったのですが、その後runを独立させてcommitすると動きました。
時差があったからなのか、runを独立させたからなのか、多分前者だと思います。
LoadError: cannot load such file -- rspec_junit_formatter
#!/bin/bash -eo pipefail
bundle exec rspec --profile 10 \
--format RspecJunitFormatter \
--out test_results/rspec.xml \
--format progress \
$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)
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
...
解決法
Gem'rspec_junit_formatter'
を追加する。
group :test do
gem 'rspec_junit_formatter' # 追加
end
参考:CircleCI 2.0 移行時に直面した問題とその解決方法 for Rails Project
CircleCI内でスペックが落ちる
ローカルでは通るが、CircleCIでは落ちる。
"tweetedAt"=>"2020-06-01T00:00:00.000+09:00"
↑こうなってほしいのに、↓こうなっている。
"tweetedAt"=>"2020-06-01T09:00:00.000+09:00"
原因と解決法
タイムゾーンが日本時間になっていないので、Dockerのタイムゾーンを指定する。
jobs:
build:
docker:
- image: circleci/ruby:2.5.3-node-browsers-legacy
environment:
DB_HOST: 127.0.0.1
RAILS_ENV: test
BUNDLER_VERSION: 2.1.4
TZ: "Japan" # 追加する
最終的な設定
version: 2.1
orbs:
ruby: circleci/ruby@0.1.2
jobs:
build:
working_directory: ~/circleci-demo-ruby-rails
docker:
- image: circleci/ruby:2.5.3-node-browsers-legacy
environment:
DB_HOST: 127.0.0.1
RAILS_ENV: test
BUNDLER_VERSION: 2.1.4
TZ: "Japan"
- image: circleci/mysql:8.0.19-ram
command: [--default-authentication-plugin=mysql_native_password]
environment:
MYSQL_USER: root
MYSQL_DB: circle_test
steps:
- checkout
- run:
name: wait for database
command: dockerize -wait tcp://127.0.0.1:3306 -timeout 3m
# Restore bundle cache
- restore_cache:
keys:
- rails-demo-{{ checksum "Gemfile.lock" }}
- rails-demo-
- run:
name: setup bundler
command: |
sudo gem update --system
sudo gem uninstall bundler
sudo rm /usr/local/bin/bundle
sudo gem install bundler
- run:
name: Which bundler?
command: bundle -v
- run:
name: bundle install
command: |
bundle install --jobs=4 --retry=3 --path vendor/bundle
# Store bundle cache
- save_cache:
paths:
- ./vendor/bundle
key: v1-dependencies-{{ checksum "Gemfile.lock" }}
- run:
name: setup database
command: |
cp -v config/database.ci.yml config/database.yml
- run: mysql_config --socket
- run: bundle exec rails db:create
- run: bundle exec rails db:schema:load
- run:
name: run rspec
command: |
bundle exec rspec --profile 10 \
--format RspecJunitFormatter \
--out test_results/rspec.xml \
--format progress \
$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)
# collect reports
- store_test_results:
path: /tmp/test-results
- store_artifacts:
path: /tmp/test-results
destination: test-results
- store_artifacts:
path: tmp/screenshots
destination: test-screenshots