概要
以下の2つの機能を実装するための方法を記載しています。
- CircleCIを使用してプッシュと同時にRuboCop, Rspecを走らす。
- テスト成功後にCapistranoによってAWSに自動デプロイする
前提
- Rails5.2
- Capistranoによる自動デプロイを実装している
実装に当たって、以下の記事を大変参考にさせていただきました。
rails5.2/Capistrano/CICD環境によるAWSへの自動デプロイ
上記記事の内容だけでも、テスト→デプロイの処理は実現できます。
この記事は、上の参考記事の補足として、workflowによる処理を追加することで、テストが成功した場合のみデプロイを実行する方法を解説しています。
補足部分のみ記事にしているため、そこに到るまでの過程については上の参考記事をご覧下さい。
実装
早速ですが、最終形のコードは以下のようになりました。
後でいくつかのブロックに分けながら解説していきます。
version: 2.1
executors:
default:
working_directory: ~/repo
docker:
- image: circleci/ruby:2.5.1-node-browsers
environment:
- BUNDLER_VERSION: 2.1.4
- image: circleci/mysql:5.7
environment:
- MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
- MYSQL_ROOT_HOST: '%'
commands:
setup:
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" }}
jobs:
test:
executor: default
environment:
RAILS_ENV: test
steps:
- setup
- run: mv config/database.yml.ci config/database.yml
- run: bundle exec rake db:create
- run: bundle exec rake db:schema:load
- run:
name: Rubocop
command: bundle exec rubocop
- run:
name: run tests
command: |
mkdir /tmp/test-results
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | \
circleci tests split --split-by=timings)"
bundle exec rspec \
--format progress \
--format RspecJunitFormatter \
--out /tmp/test-results/rspec.xml \
--format progress \
$TEST_FILES
- store_test_results:
path: /tmp/test-results
- store_artifacts:
path: /tmp/test-results
destination: test-results
deploy:
executor: default
steps:
- setup
- add_ssh_keys:
fingerprints:
- "XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX"
- deploy:
name: Capistrano deploy
command: bundle exec cap production deploy
workflows:
test_and_deploy:
jobs:
- test
- deploy:
requires:
- test
filters:
branches:
only: master
コンテナ定義
executor = 執行者という意味ですが、テストやデプロイを誰に行わせるかをここで定義しています。
ここでのexecutorはDockerコンテナに当たります。
executors:
default:
working_directory: ~/repo
docker:
- image: circleci/ruby:2.5.1-node-browsers
environment:
- BUNDLER_VERSION: 2.1.4
- image: circleci/mysql:5.7
environment:
- MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
- MYSQL_ROOT_HOST: '%'
作成するDockerコンテナにdefaultという名前をつけ、後のjob部分で呼び出すようにしています。
共通コマンドの定義
先ほど作成したコンテナが、この後 test・deploy の2つのjobを実行します。
このそれぞれのjob内で共通して実行させたい内容を setup という名前のコマンド群にまとめ、呼び出すようにしています。
commands:
setup:
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" }}
jobの実行
test・deploy の2つのjobの実行部分を定義しています。
それぞれのjobのはじめに、defaultと名付けたコンテナを呼び出し、共通コマンド setup を実行します。
その後に、各jobに応じた処理を実行させます。
jobs:
test:
executor: default
environment:
RAILS_ENV: test
steps:
- setup
- run: mv config/database.yml.ci config/database.yml
- run: bundle exec rake db:create
- run: bundle exec rake db:schema:load
# rubocopの実行
- run:
name: Rubocop
command: bundle exec rubocop
# rspecの実行
- run:
name: run tests
command: |
mkdir /tmp/test-results
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | \
circleci tests split --split-by=timings)"
bundle exec rspec \
--format progress \
--format RspecJunitFormatter \
--out /tmp/test-results/rspec.xml \
--format progress \
$TEST_FILES
- store_test_results:
path: /tmp/test-results
- store_artifacts:
path: /tmp/test-results
destination: test-results
# デプロイ
deploy:
executor: default
steps:
- setup
- add_ssh_keys:
fingerprints:
- "XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX"
- deploy:
name: Capistrano deploy
command: bundle exec cap production deploy
workflow
最後にworkflowの定義です。
test成功後にデプロイ処理に移行するようにします。
また、デプロイはブランチがmasterの時のみ実行させます。
workflows:
test_and_deploy:
jobs:
- test
- deploy:
requires:
- test
filters:
branches:
only: master
最後に
以上で、workflowを用いてテスト成功後に自動デプロイする処理を実装できました。
もっと効率的に書けそうな感じもしますが、そういった点があればご指摘頂けると助かります。
最後までご覧いただき、ありがとうございました。
参考記事
rails5.2/Capistrano/CICD環境によるAWSへの自動デプロイ
RailsにcircleCIを構築し、githubと連携してrubocopとrspecテストを走らせる
CircleCIでデプロイを自動化