#はじめに
CircleCIを使ってRailsアプリの自動テストをやろうとしてハマったのでメモ。
特にmysqlコンテナとの接続が上手くいきませんでした。
各種設定ファイルの内容や、エラーへの対策を備忘録として残すことに。
#環境
CircleCI 2.1
Bundler 2.1.4
Rails 6.0.3.4
ruby 2.6.5
MySQL 5.7
開発環境はDocker-composeで構築。
サービス名とコンテナ名の関係は以下のよう。
サービス名 | コンテナ名 |
---|---|
web | webapp_web_1 |
db | webapp_db_1 |
app | webapp_app_1 |
#設定ファイル
アプリ名はwebappとする。
database.ymlとdb.env
データベースの設定ファイル。
この設定がCircleCI側で上手く使えなかったので、今回は以下の記事を参考にCircleCI用のデータベース設定ファイルを作成することにしました。
よって、ここの設定はCircleCIとは関係ないです。
CircleCI 2.0の設定メモ
default: &default
adapter: mysql2
encoding: utf8
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: <%= ENV.fetch('MYSQL_USER') { 'root' } %>
password: <%= ENV.fetch('MYSQL_PASSWORD') { 'rootpass' } %>
port: 3306
host: db
development:
<<: *default
database: webapp_development
test:
<<: *default
database: webapp_test
MYSQL_ROOT_USER=root
MYSQL_ROOT_PASSWORD=rootpass
MYSQL_USER=kagamiya
MYSQL_PASSWORD=kagamiya
ポートの設定は要らないかも。
host: dbはDocker-composeのサービス名です。
ENV.fetchの{ 'root' }とかも要らないと思います。
##database.yml.ci
CI用のデータベース設定ファイル。
CirclCIでの自動テストではこちらを使います。
test:
adapter: mysql2
encoding: utf8
pool: 5
username: 'root'
port: 3306
host: '127.0.0.1'
database: webapp_test
##config.yml
肝心のCircleCIの設定ファイル。
参考はこちら。
CircleCIでテストを自動化
version: 2.1 # バージョン指定
executors:
default:
working_directory: ~/webapp
docker:
- image: circleci/ruby:2.6.5-node
environment:
BUNDLER_VERSION: 2.1.4
RAILS_ENV: test
DB_HOST: 127.0.0.1
DB_USERNAME: 'root'
DB_PASSWORD: ''
- image: circleci/mysql:5.7
environment:
MYSQL_ROOT_HOST: '%'
MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
commands:
setup:
steps:
- checkout
- run:
name: Update bundler # bundlerのバージョン2へのアップデート
command: gem update bundler
- run:
name: Which bundler? # バージョン確認
command: bundle -v
- restore_cache: # キャッシュを読み込む
keys:
- gem-cache-v1-{{ checksum "Gemfile.lock" }}
- gem-cache-v1-
- run:
name: Bundle Install
command: bundle check --path vendor/bundle || bundle install --deployment
- save_cache: # キャッシュを保存する
key: gem-cache-v1-{{ checksum "Gemfile.lock" }}
paths:
- vendor/bundle
# 以下はRails6でWebpackerを使う場合は必須
- restore_cache:
keys:
- yarn-cache-v1-{{ checksum "yarn.lock" }}
- yarn-cache-v1-
- run:
name: Yarn Install
command: yarn install --cache-folder ~/.cache/yarn
- save_cache:
key: yarn-cache-v1-{{ checksum "yarn.lock" }}
paths:
- ~/.cache/yarn
jobs:
test:
executor: default
environment:
RAILS_ENV: test
steps:
- checkout
- setup
- run:
name: Wait for DB
command: dockerize -wait tcp://127.0.0.1:3306 -timeout 90s
- run:
name: Use specific database.yml # CircleCI用のデータベース設定を使う
command: mv config/database.yml.ci config/database.yml
- run:
name: Database setup
command: |
bin/rails db:create
bin/rails db:schema:load --trace
- run: # 普通のテストとシステムテストを実行する
name: Rails Test
command: |
bin/rails test
bin/rails test:system
workflows:
build_and_test:
jobs:
- test
(MySQLの8系を使う場合は記述の追加が必要なようで、5.7を使うことにしました。
また、rubyのイメージはnodeがついていないとyarnコマンドが使えませんでした。)
特にデータベース周りの設定でハマりました。
というのも、私がMySQLの仕様をあまり理解できていなかった(というか今も理解できていない)からで…
当初は参考記事にならって、
DB_USER: 'kagamiya'
DB_PASSWORD: 'kagamiya'
MYSQL_USER: 'kagamiya'
MYSQL_PASSWORD: 'kagamiya'
としていました。
しかし、そもそもkagamiyaなんていうユーザーはCircleCIのMySQLイメージには登録されていません。(開発環境のdbコンテナにはもちろんありますが)
そこで必然的にrootを使うことになるので、以下のようにしました。
DB_USER: 'root'
DB_PASSWORD: 'rootpass'
MYSQL_USER: 'root'
MYSQL_PASSWORD: 'rootpass'
しかし、上手くいきませんでした。
というのは、rootユーザーのデフォルトのパスワードは設定されていないからです(多分)。
そういうわけで、パスワードを空にしても上手くいきません。
DB_USER: 'root'
DB_PASSWORD: ''
MYSQL_USER: 'root'
MYSQL_PASSWORD: ''
というわけで、ユーザーはroot、パスワードはMYSQL_ALLOW_EMPTY_PASSWORD: 'true'として(空を許可?)で接続しなければならないようです。
- image: circleci/ruby:2.6.5-node
environment:
BUNDLER_VERSION: 2.1.4
RAILS_ENV: test
DB_HOST: 127.0.0.1
DB_USERNAME: 'root'
DB_PASSWORD: ''
- image: circleci/mysql:5.7
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
ここでまたまたエラーを吐きました。
Access denied for user 'root'@'127.0.0.1'
ここの理解に苦しんだのですが、どうやら'root'@'127.0.0.1'というユーザーはいないということのようです。
mysqlのユーザー一覧を見てみると、'root'@'%'やら'root'@'localhost'はいますが、'root'@'127.0.0.1'はいません。
mysqlのホスト名(DB_HOST)にlocalhostを使うか127.0.0.1を使うかは、また別の問題として色々あるようです。
しかしながら、今は接続することが最優先なので、rootのホストとして%を指定してやります。
(%は「全てのホスト」という意味だそうですが、よく分かりません)
MYSQL_ROOT_HOST: '%'
MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
理由はどうあれ、これでやっと接続できました。
次に、CircleCIのイメージでは独自のデータベース設定を使うため、database.ymlをdatabase.yml.ciで上書きします。
データベースのセットアップ前に処理を追加します。
- run:
name: Use specific database.yml # CircleCI用のデータベース設定を使う
command: mv config/database.yml.ci config/database.yml
私の環境では、指定したデータベース(webapp_test)が無いと怒られたので、データベースの作成を行いました。
- run:
name: Database setup
command: |
bin/rails db:create
bin/rails db:schema:load --trace
(ここは次回以降の実行でエラーの原因になるかも…?)
#まとめ
MySQLの仕様とconfigの内容は理解しきれていません。
configのサンプルは多くの方がアップしておられますが、詳細まで解説されているものが少ない印象です。
よって、自分が理解できていない部分でエラーとなればまたハマる可能性が大ですね…