この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
オフィスの休憩室にある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で公開していますので、よろしければそちらも参照してみてください。