edy hub

プログラミングやライフスタイルについて書き綴っています

個人開発しているRailsプロジェクトにCircleCIを導入する

はじめに

職場でCircleCIによるRspec及びrubocopの自動実行をしているので個人開発しているサービスにも導入してみようと思いました。

CircleCIのファイル編集とかは職場でもやったことが無かったので調査から始めてみます。

CircleCIの本家を当たってみる

作っているサービスは Ruby on Rails で運用しているため、CircleCiのRubyのガイドを読み進めてみます。

言語ガイド:Ruby - CircleCI

version: 2 # CircleCI 2.0 を使用します
jobs: # ステップの集合
  build: # Workflows を使用しない実行では、エントリポイントとして `build` ジョブが必要
    parallelism: 3 # このジョブのインスタンスを 3つ並列実行します
    docker: # Docker でステップを実行します
      - image: circleci/ruby:2.4.2-jessie-node # このイメージをすべての `steps` が実行されるプライマリコンテナとして使用します
        environment: # プライマリコンテナの環境変数
          BUNDLE_JOBS: 3
          BUNDLE_RETRY: 3
          BUNDLE_PATH: vendor/bundle
          PGHOST: 127.0.0.1
          PGUSER: circleci-demo-ruby
          RAILS_ENV: test
      - image: circleci/postgres:9.5-alpine # データベースイメージ
        environment: # データベースの環境変数
          POSTGRES_USER: circleci-demo-ruby
          POSTGRES_DB: rails_blog
          POSTGRES_PASSWORD: ""
    steps: # 実行可能コマンドの集合
      - checkout # ソースコードを作業ディレクトリにチェックアウトする特別なステップ

      # Bundler のバージョンを指定します

      - run:
          name: Bundler を指定
          command: bundle -v

      # バンドルキャッシュを復元します
      # 依存関係キャッシュについては https://circleci.com/docs/ja/2.0/caching/ をお読みください

      - restore_cache:
          keys:
            - rails-demo-bundle-v2-{{ checksum "Gemfile.lock" }}
            - rails-demo-bundle-v2-

      - run: # Ruby の依存関係をインストールします
          name: バンドルインストール
          command: bundle check || bundle install

      # Ruby の依存関係のバンドルキャッシュを保存します

      - save_cache:
          key: rails-demo-bundle-v2-{{ checksum "Gemfile.lock" }}
          paths:
            - vendor/bundle

      # アプリケーションで Webpacker または Yarn を他の何らかの方法で使用する場合にのみ必要です

      - restore_cache:
          keys:
            - rails-demo-yarn-{{ checksum "yarn.lock" }}
            - rails-demo-yarn-

      - run:
          name: Yarn をインストール
          command: yarn install --cache-folder ~/.cache/yarn

      # Yarn または Webpacker のキャッシュを保存します

      - save_cache:
          key: rails-demo-yarn-{{ checksum "yarn.lock" }}
          paths:
            - ~/.cache/yarn

      - run:
          name: DB を待機
          command: dockerize -wait tcp://localhost:5432 -timeout 1m

      - run:
          name: データベースをセットアップ
          command: bin/rails db:schema:load --trace

      - run:
          name: 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)

      # タイミング解析のテスト結果を保存します

      - store_test_results: # テストサマリー (https://circleci.com/docs/ja/2.0/collect-test-data/) に表示するテスト結果をアップロードします
          path: test_results
      # デプロイコンフィグの例については https://circleci.com/docs/ja/2.0/deployment-integrations/ を参照してください

現状、開発しているプロダクトの構成は下記のとおりです。 - Dockerでweb, webpacker, dbコンテナをビルドする仕組み - ruby 2.6.6 - rails 6.0.0 - mysql 5.7

それぞれ対応するように修正していきます。

実際にファイルを作成してみた

version: 2
jobs:
  build:
    working_directory: ~/Hookah
    docker:
      - image: circleci/ruby:2.6.6-node-browsers
        environment:
          RAILS_ENV: test
          DATABASE_HOST: 127.0.0.1
      - image: mysql:5.7
        environment:
          MYSQL_ALLOW_EMPTY_PASSWORD: yes

    steps:
      - checkout
      - restore_cache:
          keys:
            - v1-dependencies-{{ checksum "Gemfile.lock" }}
            - v1-dependencies-

      - run:
          name: Install bundle dependencies
          command: bundle install --path=vendor/bundle --jobs 4 --retry 3

      - run:
          name: Install yarn
          command: |
            yarn install

      - save_cache:
          paths:
            - ./vendor/bundle
            - ./node_modules
          key: v1-dependencies-{{ checksum "Gemfile.lock" }}

      - run:
          name: Database Setup
          command: |
            bundle exec rake db:create db:schema:load

これでリモートリポジトリにプッシュしてみると、、 bundle exec rake db:create db:schema:load

の段階でエラーに。

bundle exec rake db:create db:schema:load
2020-05-23 16:22:30 WARN Selenium [DEPRECATION] Selenium::WebDriver::Chrome#driver_path= is deprecated. Use Selenium::WebDriver::Chrome::Service#driver_path= instead.
DEPRECATION WARNING: Single arity template handlers are deprecated. Template handlers must
now accept two parameters, the view object and the source for the view object.
Change:
  >> Coffee::Rails::TemplateHandler.call(template)
To:
  >> Coffee::Rails::TemplateHandler.call(template, source)
 (called from <top (required)> at /home/circleci/Hookah/Rakefile:6)
Unknown MySQL server host 'db' (-2)
Couldn't create 'hookah_test' database. Please check your configuration.
rake aborted!
Mysql2::Error::ConnectionError: Unknown MySQL server host 'db' (-2)

bundle update slim を実行

エラーメッセージでググってみると、どうやら gem 'slim' が原因になっていそうな。

qiita.com

ただ、bundle update をしても既に最新バージョンになっていた。

別のクエリでググってみると、 coffee-rails が怪しそうに。

github.com

coffee-rails のバージョンを 5.0.0 に上げるのが良さそうだったので変更。

すると、エラーが一つ消えたがさらにMySQL周りでエラーに...(面倒くさそうw)

2020-05-23 16:36:15 WARN Selenium [DEPRECATION] Selenium::WebDriver::Chrome#driver_path= is deprecated. Use Selenium::WebDriver::Chrome::Service#driver_path= instead.
Unknown MySQL server host 'db' (-2)
Couldn't create 'hookah_test' database. Please check your configuration.
rake aborted!
Mysql2::Error::ConnectionError: Unknown MySQL server host 'db' (-2)

省略

この記事を見て、

CircleCIのmysqlイメージを用いるように変更を加えました。

teratail.com

しかし、結果は変わらず。

データベース名を削除

Unknown MySQL server host 'db' (-2)
Couldn't create 'hookah_test' database. Please check your configuration.

ここにある Unknown MySQL server host 'db' (-2) というのが気になったので調べてみると、config/database.ymlhost: db と定義していることを確認しました。 (1年以上前に記述していたので忘れていた・・・)

default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  database: <%= ENV['DATABASE_NAME'] %>
  username: <%= ENV['DATABASE_USERNAME'] %>
  password: <%= ENV['DATABASE_PASSWORD'] %>

development:
  <<: *default
  database: hookah_development
  host: db

test:
  <<: *default
  database: hookah_test
  host: db

production:
  <<: *default
  database: hookah_production
  username: root
  socket: /var/lib/mysql/mysql.sock

そこで、こちらの記事を参考に、hostには localhost を割り当てるように変更しました。 こちらは環境変数DATABASE_HOST として 127.0.0.1 になるようにしました。

qiita.com

変更後

default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  database: <%= ENV['DATABASE_NAME'] %>
  username: <%= ENV['DATABASE_USERNAME'] %>
  password: <%= ENV['DATABASE_PASSWORD'] %>
  host: <%= ENV['DATABASE_HOST'] %>

development:
  <<: *default
  database: hookah_development

test:
  <<: *default
  database: hookah_test

production:
  <<: *default
  database: hookah_production
  username: root
  socket: /var/lib/mysql/mysql.sock

完成版

こちらが初期段階として導入に成功したCircleCIのファイルです。 Ruby on Rails による開発を行うので、rubocopやRspecのjobを今後追加していこうと思います。

version: 2
jobs:
  build:
    working_directory: ~/Hookah
    docker:
      - image: circleci/ruby:2.6.6-node-browsers
        environment:
          RAILS_ENV: test
          MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
          DATABASE_HOST: 127.0.0.1
          DATABASE_USERNAME: root
      - image: circleci/mysql:5.7

    steps:
      - checkout
      - restore_cache:
          keys:
            - v1-dependencies-{{ checksum "Gemfile.lock" }}
            - v1-dependencies-

      - run:
          name: Install bundle dependencies
          command: bundle install --path=vendor/bundle --jobs 4 --retry 3

      - run:
          name: Install yarn
          command: |
            yarn install

      - save_cache:
          paths:
            - ./vendor/bundle
            - ./node_modules
          key: v1-dependencies-{{ checksum "Gemfile.lock" }}

      - run:
          name: Database Setup
          command: |
            bundle exec rake db:create db:schema:load

以上で導入を終了します。 当初予定していたrubocopやRspecは未対応ですが、基盤ができたので一旦これにて完了とします。