概要
前回の記事 Ruby 3.x, Rails 6.x, MySQL 8.x の Docker 環境構築。 を引き継いで、プロジェクトを CircleCI に設定し、GitHub リポジトリへの push 時に RSpec と Rubocop を自動実施するように設定します。
基本的に以下の CircleCI 公式ドキュメントを参考にしていますので、初期設定の方法などはそちらをご確認ください。
大きく違うのは、Ruby on Rails で MySQL に対応した点です。
前提
下記の環境が準備されていること。
- GitHub のアカウントを持っていること(無料版でも大丈夫)
- 上記の GitHub アカウントに紐づいた CircleCI のアカウントを持っていること(無料版でも大丈夫)
- Docker を利用した Ruby on Rails のプロジェクトが作成されていること
今回は CircleCI の設定が主になるため、Docker や RSpec、Rubocop の細かい説明は省きます。
RSpec と Rubocop の組み込み
Gemfile を編集し、:development と :test 環境に rubocop(ついでに pry-byebug と factory_bot_rails)を、:test 環境に rspec-rails と database_cleaner-active_record を追加します。
gem についてはプロジェクトごと、必要に応じて対応してください。
.Gemfile
group :development, :test do
# 略
gem 'pry-byebug'
gem 'factory_bot_rails'
# https://github.com/rubocop-hq/rubocop
gem 'rubocop', '~> 1.10.0', require: false
end
group :test do
# 略
gem 'rspec-rails', '4.0.2'
gem 'database_cleaner-active_record'
end
設定後、bundle install
と RSpec のインストール rails g rspec:install
、rubocop の設定ファイル作成 bundle exec rubocop --auto-gen-config
を実行します。
前回のプロジェクトは Docker で作成していたため、その場合は以下のように docker-compose を使用します。
なお、minitest 用の test フォルダが不要な場合は削除してください。
$ docker-compose run app bundle install
$ docker-compose run app rails g rspec:install
$ docker-compose run app bundle exec rubocop --auto-gen-config
config/application.rb
Scaffold 実行時に RSpec のスケルトンを自動生成するかどうかの設定を APP::Application クラス内に記入します。自動生成が不要な場合は g.test_framework false
とします。
また、FactoryBot についても書いておきます。
module App
class Application < Rails::Application
config.generators do |g|
g.test_framework :rspec,
feature_specs: true,
fixtures: false,
view_specs: true,
helper_specs: false,
routing_specs: false,
controller_specs: false,
request_specs: true,
system_specs: true
g.factory_bot false
g.factory_bot dir: 'spec/factories'
end
end
end
rubocop ファイル
bundle exec rubocop --auto-gen-config
を実行することで .rubocop.yml と .rubocop_todo.yml ファイルが作成されます。
.
├── rubocop.yml
└── rubocop_todo.yml
実際の rubocop の運用については公式サイトを確認してください。
大まかな手順としては、rubocop --auto-gen-config
実施時にエラーになった箇所が _todo.yml の方に記載されるので、そこから修正するつもりがない設定を .rubocop.yml に移動し、それ以外は _todo.yml からは削除し、エラー要素を実ファイルから修正していくことになります。
CircleCI の設定
本題の CircleCI の設定となります。
.circleci/config.yml
.
└── .circleci/
└── config.yml
.circleci/config.yml は Docker の docker-compose.yml と少し似ています。
今回はリポジトリへの push 時に RSpec と rubocop を自動実施するためのモノなので、設定する環境は test となります。
注意点としては、この設定では MySQL および Docker の仕組み上、CircleCI 実施時に MySQL のコンテナで頻繁に mbind: Operation not permitted
という警告が出ますが、いまのところ無視するしかないようです。
(Docker だけの対応では cap_add: - SYS_NICE
を付加することで警告が非表示になるようですが、CircleCI では設定できません)
cf. circleci コンテナの立ち上げ失敗&ビルドがキャンセルされる?
また、イメージのタグは以下の一覧から 2021/02 現在の安定最新版を探しました。
cf. https://circleci.com/docs/ja/2.0/docker-image-tags.json
version: 2.1
orbs:
ruby: circleci/ruby@1.1.2
node: circleci/node@4.2.0
jobs:
build:
docker:
- image: cimg/ruby:3.0.0-node
steps:
- checkout
- ruby/install-deps
- node/install-packages:
pkg-manager: yarn
test:
docker:
- image: cimg/ruby:3.0.0-node
environment:
RAILS_ENV: test
- image: circleci/mysql:8.0.4
name: db
command: mysqld --default-authentication-plugin=mysql_native_password
environment:
MYSQL_DATABASE: app_test
MYSQL_USER: user
MYSQL_PASSWORD: password
environment:
BUNDLE_JOBS: "3"
BUNDLE_RETRY: "3"
steps:
- checkout
- ruby/install-deps
- node/install-packages:
pkg-manager: yarn
- run:
name: Wait for DB
command: dockerize -wait tcp://db:3306 -timeout 1m
- run:
name: Database setup
command: bundle exec rails db:schema:load --trace
- ruby/rspec-test
- ruby/rubocop-check
workflows:
version: 2
build_and_test:
jobs:
- build
- test:
requires:
- build
ここまで追加したものを登録済みの GitHub に push しておきます。
CircleCI サイトでのプロジェクトの設定
https://app.circleci.com/ にログインし、GitHub と連携したプロジェクト(リポジトリ)を設定します。
詳細な手順は 入門ガイド を確認してください。
GitHub と連携できている場合は Projects ページにリポジトリの一覧が表示されるため、対象となるもので「Set Up Project」ボタンを押下します。
その後、すでに config.yml は設定済みのため、次の画面で「Use Existing Config」ボタンを押下します。
簡単な警告ダイアログが出ますが、「Start Building」ボタンを押下して先に進めます。
この時点で、設定に問題がなければ CircleCI の Dashboard に最初のテスト結果が「Success」として表示されます。
また、GitHub 側のリポジトリにも安心のチェックマークが表示されるようになります。
RSpec の実装
rubocop は書式の問題なのでさておき、RSpec の動作確認だけ簡単に説明します。
前提
前回の最後に scaffold で作成した users テーブルがあることとします。
$ docker-compose run app rails g scaffold user name:string email:string
バリデーション追加
User モデルにバリデーションを追加します。
class User < ApplicationRecord
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :name, presence: true, length: { maximum: 250 }
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false }
before_save { self.email = email.downcase }
end
FactoryBot
ユニットテストで使用するテストデータを事前に設定しておきます。
FactoryBot.define do
factory :user do
sequence(:name) { |n| "test name#{n}" }
sequence(:email) { |n| "test#{n}@example.com" }
trait :empty do
name { nil }
email { nil }
end
trait :invalid_email do
sequence(:email) { |n| "test#{n}" }
end
end
end
モデルテスト
(ごく単純なものとなりますが、)モデルのテストを設定します。
require 'rails_helper'
RSpec.describe User, type: :model do
describe '#valid?' do
let!(:user) { described_class.new(attributes) }
subject { user.valid? }
context 'successful' do
let!(:attributes) { attributes_for(:user) }
it { is_expected.to be true }
end
context 'failure' do
let!(:attributes) { attributes_for(:user, :invalid_email) }
it { is_expected.to be false }
end
end
end
ローカルでの確認
ローカルで RSpec(と rubocop)を実施する場合は、以下のコマンドを実行して下さい。
$ docker-compose run app rspec
$ docker-compose run app rubocop
GitHub へ push
問題がなければ git commit と git push を行います。
これだけで GitHub へ反映されると同時に CircleCI が RSpec と rubocop を自動実行してくれます。
今回は RSpec と rubocop の実施だけですが、エラーがなかった場合にそのまま本番環境へのデプロイなどを行うことも可能です。
少し駆け足となってしまいましたが、今回は以上となります。
参考資料
以下の記事、情報を参考にさせていただきました。
ありがとうございます。