Help us understand the problem. What is going on with this article?

DockerでRailsチュートリアルのローカル開発環境構築 - RSpec導入 & CircleCIでHerokuデプロイ-

はじめに

前回の記事
DockerでRailsチュートリアルのローカル開発環境構築(Rails 6 + PostgreSQL + Webpack) - Qiita

個人開発アプリ
mdClip <オンラインmarkdownエディタ>

前回の記事に続いて、Railsチュートリアルのローカル開発環境構築を行っていきます。

  • Railsチュートリアル最新版(2020.8.6現在)に対応のRails 6

  • Dockerを使用し、開発環境の再現が可能

  • なるべくローカル環境にインストールしない

Docker環境で操作する場合はターミナルのコマンドを適宜

$ docker-compose run app ...

もしくは

$ docker-compose exec app ...

で置き換えてください。

Rspec導入

minitestでも問題ないです
後述のCircleCIでもminitestを走らせる事もできました。

Gemfile

必要に応じて以下のgemを追加
(不要ならminitest関連のgemを削除する)

Gemfile

  # Test enviroment: Rspec
  gem 'rspec-rails'
  gem 'spring-commands-rspec'
  gem 'guard'
  gem 'guard-rspec', require: false

  # Test enviroment: Fake date generator
  gem 'factory_bot_rails'
  gem 'faker'
  gem 'forgery_ja'

bundle install

Gemfileを編集したのでdocker-compose buildが必要です

$ docker-compose build

初期ファイル生成

$ rails g rspec:install

レポートフォーマット

.rspec

--require spec_helper
--format documentation

Guard初期化

$ bundle exec guard init

spring boot対応

$ bundle exec spring binstub --all

Guardの自動テスト時にもspringが有効になるように
Guardfile

guard :rspec, cmd: "bundle exec spring rspec" do

CircleCI設定

事前準備

ここでは説明しませんが事前に以下の手順が必要だと思います

  • GitHub & CircleCI & Herokuのアカウント登録
  • SSH接続設定(GitHub - CircleCI)
  • CircleCIへのproject登録および環境変数定義(Heroku APIキー, app名)

設定概要

  • git push -> 自動test (RSpec) -> 自動デプロイ(Heroku)
  • Orbを使うとconfig.ymlの内容を簡略化できる(キャッシュ利用のための記述が不要)
  • Orbを使うためにversion: 2.1指定
  • Docker imageのRuby versionはRailsチュートリアルに合わせて2.6.3
  • Node.jsが必要なので-nodeのついたimageを指定

メモ: Node.js バリアントの Docker イメージ (-node で終わるタグ) に対しては、Node.js の LTS リリースがプリインストールされています。 独自に特定のバージョンの Node.js/NPM を使用する場合は、.circleci/config.yml 内の run ステップで設定できます。 Ruby イメージと共に特定のバージョンの Node.js をインストールする例については、以下を参照してください。

公式サンプルを踏襲しています

CircleCI公式doc - Ruby
Language Guide: Ruby - CircleCI

CircleCI公式doc - Heroku Deploy
デプロイの構成 - CircleCI

現時点で最新のHeroku-orbは1.2.0ですがバグがあるようで
pull requestされています

deploy-via-git bash script error · Issue #13 · CircleCI-Public/heroku-orb

config.yml

.circleci/config.yml

version: 2.1

orbs:
  ruby: circleci/ruby@1.0
  node: circleci/node@2
  heroku: circleci/heroku@1.1.0

# setupでまとめる
commands:
  setup:
    steps:
      - checkout
      - ruby/install-deps
      - node/install-packages:
          pkg-manager: yarn
          cache-key: "yarn.lock"

jobs:
  build:
    docker:
      - image: circleci/ruby:2.6.3-node
    steps:
      - setup
  test:
    docker:
      - image: circleci/ruby:2.6.3-node
      - image: circleci/postgres:11.6-alpine
        environment:
          POSTGRES_USER: postgres
          POSTGRES_DB: myapp_test
          POSTGRES_PASSWORD: ""
    environment:
      BUNDLE_JOBS: "4"
      BUNDLE_RETRY: "3"
      PGHOST: 127.0.0.1
      PGUSER: postgres
      PGPASSWORD: ""
      RAILS_ENV: test
    steps:
      - setup
      - run:
          name: Wait for DB
          command: dockerize -wait tcp://localhost:5432 -timeout 1m
      - run:
          name: Database setup
          command: bundle exec rails db:schema:load --trace
      - run:
          name: Rspec
          command: bundle exec rspec

  deploy:
    executor: heroku/default
    steps:
      - checkout
      - heroku/install
      - heroku/deploy-via-git:
          maintenance-mode: true
      - run:
          name: DB migrate
          command: heroku run rails db:migrate --app $HEROKU_APP_NAME

workflows:
  version: 2
  test_and_deploy:
    jobs:
      - build
      - test:
          requires:
            - build
      - deploy:
          requires:
            - build
            - test
          filters:
            branches:
              only: master

動作確認

HTMLを書き換える

app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  def hello
    render html: "Bye, world!"
  end
end

変更をgit pushして、CircleCIのpipelineがsuccessに変われば
ブラウザから見た内容が上記を反映するはずです

簡単なテスト

仮のrequest_specを作成

rails g rspec:request test

spec/requests/tests_spec.rb

require 'rails_helper'

RSpec.describe "Tests", type: :request do
  describe "GET /" do
    it "Bye, world!が表示されること" do
      get root_path
      expect(response.body).to include "Bye, world!"
    end
  end
end

CircleCI上でも上記テストがpassするはずです

Troubleshoot

CircleCIのtestが以下のエラーで失敗する

rails aborted!
PG::ConnectionBad: could not translate host name "db" to address: Name or service not known

database.ymlの記述が原因です

test環境ではdefaultを引き継いでhost: dbが適応されているはずです

config/database.yml
以下のように書き換えて環境変数がある場合はそちらを優先するようにしました
(ymlのなかでもerbが使えるという学びでした)

test:
  <<: *default
  host: <%= ENV['PGHOST'] || 'db' %>
  database: myapp_test

ERROR IN CONFIG FILE:

インデント、フォーマットの間違いが多いと思います

最後に

  • 意地でローカル環境をきれいに保つことに注力した結果、デプロイやdb:migrateを自動化することで、Heroku CLIすらインストールすることを回避しましたが、素直にHeroku CLIくらいは入れておいた方が今後のエラー解決に役立つ気もします。
  • 難易度は上がりますが、ローカル環境でDocker, CICDを取り入れてのRailsチュートリアル、学べることも多いと思いますので腰を据えて取り組むことのできる方はぜひトライしてみてください。
  • 今後も未知のエラーに遭遇することが予想されますが、おおよそココまでが大変なところかとおもっていますので、この記事がお役に立てれば幸いです。
naokit-dev
Interest: クラウドインフラ / DevOps / AWS / Docker / Ruby on Rails | 2020.05 - 2020.10 30代未経験から5ヶ月間独学にて学び、2020.11からWeb開発エンジニアへ 学習内容を残しています(40投稿, 53LGTM) | Twitterお気軽にフォローください ヒト型のエンジニアらしき人と繋がりたい
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away