CircleCI 2.0とcodedeployでデプロイを自動化する
はじめに
オフィスの休憩室にあるNintendo Switchのマリオカートで遊ぶのが楽しすぎて、自宅にも欲しくなってきました。佐々木です。
最近自分のプロジェクトでCircle CIとAWS CodeDeployを連携させて、デプロイを自動化したので、その時の手順について紹介します。
構成/要件
今回は以下のような構成と条件でセットアップを行いました。
- ソースコードはGithub上に存在する
- AWS CodeDeployを使って、AutoScalingGroup配下のEC2インスタンスへデプロイする
- Circle CIでユニットテストを実行して、成功した時のみデプロイする
- デプロイはビルドが
develop
ブランチに対して実行された時のみ行う
やること
- AWS CodeDeploy上にデプロイメントグループを作成する
- デプロイ用のS3バケットを作成する
- デプロイ用のIAMユーザーを作成して、CircleCI上に認証情報を設定する
- デプロイ用のスクリプトをrake タスクとして作成する
.circleci/config.yml
にビルドジョブを記述する
今回は対象がrailsアプリだったのでデプロイ用のスクリプトはrakeタスクで記述しましたが、シェルスクリプトやpythonなどでも問題ないです。
各言語のaws-sdk
を使えば同じことが実現できるはずです。
上記1〜2の手順は「[公式チュートリアルではじめる]CircleCI+CodeDeployを使ったCD(継続的デプロイ)」で紹介されている手順と同じなので、ここでは省略します。
.circleci/config.yml
にビルドジョブを記述する
circleci/config.yml
は下記のようになります。
この設定ファイルは大きく分けて2つの部分で構成されています。
jobs
: テストとデプロイの各ジョブの詳細を記述するパートworkflows
: 各ジョブの実行順序や条件を記述するパート
Circle CIのドキュメントと合わせて読んでいただくとそれほど難しくないかと思いますが、下記の3点がポイントになります。
deploy
ジョブでは後ほど紹介するデプロイ用のrakeタスクを実行している- テスト成功後にデプロイを実行するために
deploy
ジョブはbuild
ジョブに依存すると宣言している develop
ブランチのみデプロイするためにfilters
でブランチ名のチェックを行なっている
version: 2 jobs: build: #単体テストを実行するジョブ working_directory: ~/my-app docker: - image: ruby:2.4.0 steps: - checkout - run: bundle install --path vendor/bundle - run: name: Run Test command: bundle exec rspec deploy: #デプロイするジョブ working_directory: ~/my-app docker: - image: ruby:2.4.0 steps: - checkout - run: bundle install --path vendor/bundle - run: bundle exec rake deploy workflows: version: 2 build-deploy: jobs: - build - deploy: # deployはbuildのあとに実行 requires: - build filters: # developブランチの場合のみデプロイする branches: only: develop
デプロイ用のスクリプトをrake タスクとして作成する
続いてデプロイ用のrakeタスクです。下記にスニペットを掲載していますが、概ね次のようなことをしています。
git archive
でデプロイするファイルをZIPファイルにまとめる- ZIPファイルをS3へアップロードする
- CodeDeploy上にリビジョンを作成する
- 作成したリビジョンをデプロイする
1でgit archive
を使っているのはvendor/bundle
などの不要なファイルがデプロイするファイルに含まれるのを防ぐためです。
# frozen_string_literal: true require 'aws-sdk-codedeploy' require 'aws-sdk-s3' # Configs for codedeploy APP_NAME = 'app_name' S3_BUCKET = 'mybucket' S3_PREFIX = 'app/versions/' TAG = `git describe --tags`.strip DEPLOY_GROUP_NAME = 'deploy_group_name' desc "Deploy with codedeploy" task :deploy do # upload files to s3 zip_file = "#{APP_NAME}_#{TAG}.zip" s3_key = S3_PREFIX + '/' + zip_file `git archive HEAD --output=#{zip_file}` begin Aws::S3::Client.new.put_object(bucket: S3_BUCKET, key: s3_key, body: File.open(File.basename(zip_file))) ensure File.delete(zip_file) end # register revision revision = { revision_type: 'S3', s3_location: { bucket: S3_BUCKET, key: s3_key, bundle_type: 'zip', }, } codedeploy = Aws::CodeDeploy::Client.new codedeploy.register_application_revision(application_name: APP_NAME, revision: revision) # deploy codedeploy.create_deployment(application_name: APP_NAME, deployment_group_name: DEPLOY_GROUP_NAME, revision: revision, file_exists_behavior: 'OVERWRITE') end
ここまで紹介した手順で環境設定を行って、設定ファイルをなどをgithubにPushすればCircleoCI上でデプロイジョブが実行されるはずです。 ワークフローの経過はCircleCI上からフローチャートで確認できます。
最後に
Circle CI 2.0とAWS CodeDeployを使ってデプロイを自動化するスクリプトと設定を紹介しました。
この記事で紹介したスクリプトや設定はそれほど量が多くないのでコピペですぐに作成できると思いますが、サンプルもgithubで公開していますので、よろしければそちらも参照してみてください。