アプリの環境
- rails6.0.3.6
- ruby2.6.5
- bundler2.1.4
- mysql5.6
最初に…僕なりのイメージ
実装してみた感じこういうイメージで捉えておくと良さそう
Docker関係
- Dockerfile…仮想コンテナの環境構築をするファイル。
docker componse build
するとここに書いてあるコマンドが実行される。 - docker-compose.yml…仮想コンテナで使用するDBなど詳細設定を行うファイル。
docker compose up
をするとここに書いてある内容を元にアプリが立ち上がる - entrypoint.sh…仮想環境を立ち上げる際に最初に読み込まれる内容を決めるファイル
CircleCI関係
- config.yml…Githubへのpushが行われた際にここに書いてある内容が順に実行される。手順書的な感じ。雰囲気だけはDockerfileに近い
【Docker編】やったこと
https://qiita.com/Tomohisa_koyama/items/5f2d32fd0677aa244b72
こちらにruby, rails, mysqlともに同じバージョンのものを発見しましたのでこれを参考にしました。
FROM ruby:2.6.5
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
&& echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs yarn
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN gem install bundler # これがないとbundlerがないって言われる
RUN bundle install
COPY . /myapp
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]
参考サイトとの違いは gem install bundler
を実行しているか否か。これは以下サイトを参考にしました。
https://qiita.com/kenz-dev/items/e3d970b59bf106cab19e
docker-compose.yml
参考サイト通りです。
version: "3"
services:
db:
image: mysql:5.6.47
env_file: database.env
ports:
- "3306:3306"
volumes:
- ./db/mysql/volumes:/var/lib/mysql
web:
env_file: web.env
build: .
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
stdin_open: true
tty: true
volumes:
- .:/myapp
- gem_data:/usr/local/bundle
ports:
- "3000:3000"
depends_on:
- db
volumes:
mysql_data:
gem_data:
【追記】
環境変数が読み込めなくてエラーが起こったので以下サイトを参考に外部ファイルから読み込めるよう設定しました。
https://qiita.com/KEINOS/items/518610bc2fdf5999acf2
mysql周りで必要な設定
以下を参考にやりました。
https://qiita.com/nanakenashi/items/180941699dc7ba9d0922
気をつけるべきはMYSQL_ROOT_PASSWORDが必須であることでしょう。
ローカルではパスワードなしでもrootユーザー動かせますがdockerの場合はpasswordなしだと
docker-compose upのときにエラーが出ます。
entrypoint.sh
参考サイト通り
#!/bin/bash
set -e
# Remove a potentially pre-existing server.pid for Rails.
rm -f /myapp/tmp/pids/server.pid
# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"
この時点で
docker compose build
docker compose up
をすると仮想環境が立ち上がるはずです。
【CircleCI編】やったこと
CircleCIはちょっと複雑でした。
どうやら事前にcommandオプションで実行する内容を定義してからstepsを書く、というのもあるみたいですね??
https://qiita.com/AK4747471/items/b2161784065f21cd1645
こちらのサイトがconfig.ymlの記述自体は理解しやすかったのでこれを基準にカスタマイズしました。
config.yml
version: 2.1
orbs:
slack: circleci/slack@4.3.0
jobs:
build:
docker:
- image: circleci/ruby:2.6.5-node-browsers
environment:
- BUNDLER_VERSION: 2.1.4
- RAILS_ENV: 'test'
- image: circleci/mysql:5.6
environment:
- MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
- MYSQL_ROOT_HOST: '127.0.0.1'
working_directory: ~/sample_app
steps:
- checkout
- restore_cache:
keys:
- v1-dependencies-{{ checksum "Gemfile.lock" }}
- v1-dependencies-
- run:
name: install dependencies
command: |
gem install bundler -v 2.1.4
bundle install --jobs=4 --retry=3 --path vendor/bundle
- save_cache:
paths:
- ./vendor/bundle
key: v1-dependencies-{{ checksum "Gemfile.lock" }}
# database setup
- run: mv ./config/database.yml.ci ./config/database.yml
# database setup
- run:
name: setup database
command: |
bundle exec rake db:create
bundle exec rake db:schema:load
# install yarn
- run:
name: install yarn
command: yarn install
#run rubocop
- run:
name: Rubocop
command: |
bundle exec rubocop -a
bundle exec rubocop -A
# run tests
- run:
name: run rspec
command: bundle exec rspec
# collect reports
- store_test_results:
path: /tmp/test-results
- store_artifacts:
path: /tmp/test-results
destination: test-results
- slack/notify:
event: fail
mentions: '@ユーザー名'
template: basic_fail_1
- slack/notify:
event: pass
mentions: '@ユーザー名'
template: basic_success_1
このymlファイルを使うと以下を実行できます。
-
自動コード整形(rubocop)
-
自動テスト(rspec)
-
Slackへの通知
苦労した点
特段難しい箇所はなかったですが、CircleCIからSlackへの通知がなかなか飛ばなくて苦戦しました。
Slackへの通知は以下URLから公式の情報を元にやりましょう。というのも昨年あたりにSlackとCircleCIの連携方法が変更になったこともあり、
古い情報を載せているブログなどもあるためです。簡単に言うと、Webhookを使った連携が昔のやり方で、今はOAuthを使って連携しているようです。
SlackAppでcircleciと検索すると公式のアプリが出てきますが、それはもう使われていない?ようです。
細かいカスタマイズとかは以下URLが詳しいです。最初はとりあえずtemplateでいいと思いますが、jobsが失敗したときだけ通知したいとかそういう場合は別途設定が必要なので徐々にカスタマイズしていきましょう。
あとは、環境変数の設定が必要になるのですがどこからやるのか記載がなくちょっと探しました。
Project Setting→Environment Variablesと進むと環境変数をまとめて設定できます。Rspec実行時に必要な環境変数もここで設定しましょう。
最後に
初めてのCI導入でしたがいざ導入してみると非常に便利で感動しました。もっと早くしっておけばよかったです。
特に感動したポイントは
- 毎回rubocopとテストの実行を自動でやってくれるのでコードの管理の手間が省ける
- rubocopとテストの実行を抜けもれなくやってくれるのであとになってやり直しをしなくて済む
- Circle CIが頑張ってくれている間に他の作業ができる
といったあたりです。チームで開発しているとコードレビューの手間も省けそうですよね!
以上、参考になれば幸いです。