LoginSignup
6
7

More than 3 years have passed since last update.

【CircleCI】CircleCIの自動テストでハマった(rails + mysql)【メモ】

Last updated at Posted at 2020-10-16

はじめに

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の設定メモ

config/database.yml
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
environments/db.env
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での自動テストではこちらを使います。

config/database.yml.ci
test:
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: 'root'
  port: 3306
  host: '127.0.0.1'
  database: webapp_test

config.yml

肝心のCircleCIの設定ファイル。
参考はこちら。
CircleCIでテストを自動化

circleci/config.yml
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のサンプルは多くの方がアップしておられますが、詳細まで解説されているものが少ない印象です。
よって、自分が理解できていない部分でエラーとなればまたハマる可能性が大ですね…

6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7