8
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Rails5.2] CircleCI × Capistrano でテスト成功後にAWSへ自動デプロイする

Last updated at Posted at 2020-06-20

概要

以下の2つの機能を実装するための方法を記載しています。

  • CircleCIを使用してプッシュと同時にRuboCop, Rspecを走らす。
  • テスト成功後にCapistranoによってAWSに自動デプロイする

前提

  • Rails5.2
  • Capistranoによる自動デプロイを実装している

実装に当たって、以下の記事を大変参考にさせていただきました。
rails5.2/Capistrano/CICD環境によるAWSへの自動デプロイ

上記記事の内容だけでも、テスト→デプロイの処理は実現できます。
この記事は、上の参考記事の補足として、workflowによる処理を追加することで、テストが成功した場合のみデプロイを実行する方法を解説しています。

補足部分のみ記事にしているため、そこに到るまでの過程については上の参考記事をご覧下さい。

実装

早速ですが、最終形のコードは以下のようになりました。
後でいくつかのブロックに分けながら解説していきます。

circleci/config.yml
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コンテナに当たります。

circleci/config.yml
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 という名前のコマンド群にまとめ、呼び出すようにしています。

circleci/config.yml
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に応じた処理を実行させます。

circleci/config.yml
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の時のみ実行させます。

circleci/config.yml
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でデプロイを自動化

8
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?