概要
CircleCI 2.0でtagからのビルド&デプロイをできるようにします。
主に使う機能としては
- workflow
- cache
です。workflowはビルドパイプラインのようなもので、実行ジョブを細かく分けて順に実行させることができます。

上の例ではmasterブランチにマージ後、testジョブが実行されてからdeploy_devというdev環境にデプロイするジョブが実行されています。
ジョブ毎に分かれているお陰で、以下のように途中から(失敗したジョブから)実行することも可能です。

基本的な使い方
直列実行のworkflow

ref: Using Workflows to Schedule Jobs - CircleCI
この図のように幾つかのジョブを直列で実行したい場合は
workflows: version: 2 build-test-and-deploy: jobs: - build - test1: requires: - build - test2: requires: - test1 - deploy: requires: - test2
のように書きます。deployを実行したい場合、requiresという依存関係を見ると
- deployはtest2を必要とする
- test2はtest1を
- test1はbuildを
となり、結果として
build -> test1 -> test2 -> deploy
の順に実行されます。
※deployの発火条件はこの例では書かれていませんので注意
並列実行のworkflow

ref: Using Workflows to Schedule Jobs - CircleCI
並列に実行したい場合は
workflows: version: 2 build_accept_deploy: jobs: - build - acceptance_test_1: requires: - build - acceptance_test_2: requires: - build - acceptance_test_3: requires: - build - acceptance_test_4: requires: - build - deploy: requires: - acceptance_test_1 - acceptance_test_2 - acceptance_test_3 - acceptance_test_4
こんな感じになります。
buildジョブ後にacceptance_test_1~acceptance_test_4が並行に実行され、それらがすべて完了するとdeployジョブが実行されます。
※deployの発火条件はこの例では書かれていませんので注意
特定のブランチで発火させる
ブランチ毎に発火条件を変えたい要件があると思います。その場合
workflows: version: 2 dev_stage_pre-prod: jobs: - test_dev: filters: branches: only: - dev - /user-.*/ - test_stage: filters: branches: only: stage - test_pre-prod: filters: branches: only: /pre-prod(?:-.+)?$/
このようにfilters:、branches:の組み合わせで特定のジョブを実行できます。
この例だと
devブランチ、user-xxxブランチに変化があったらtest_devを実行stageブランチに変化があったらtest_stageを実行pre-prodブランチに変化があったらtest_pre-prodを実行
と言った感じです。
gitのtagに連動させる
gitのtagを発行したらデプロイしたいという要件は多いと思います。この場合
workflows: version: 2 build-n-deploy: jobs: - deploy: filters: tags: only: /^release-v.*/ branches: ignore: /.*/
のようにfilters:のtags:セクションを設定すれば発火します。この例だとrelease-v1.0.0といったtagで発火します。
またbranches:セクションでignore: /.*/としていることでブランチの変化(マージやプルリク)に反応しないようにしています。
ただtagの場合注意が必要で、require:に設定しているジョブも同じtags:セクションの設定が必要という点です。
例えば
build -> test -> deploy
と実行するworkflowの場合、
workflows: version: 2 build-n-deploy: jobs: - build: filters: tags: only: /^config-test.*/ - test: requires: - build filters: tags: only: /^config-test.*/ - deploy: requires: - test filters: tags: only: /^config-test.*/ branches: ignore: /.*/
このように、どのジョブにもtags:セクションにonly: /^config-test.*/という設定をしなくてはいけません。
実際の業務でのyaml
以下の要件を満たすyamlを用意します。
- プルリク時はtestを実行
- マージされたらtestを実行、その後
dev環境へビルド - tagが発行されたらtestを実行し、その後
stg環境へビルド
それでは設定を紹介します。
defaults: &defaults working_directory: /go/src/github.com/jun06t/sample-api environment: TZ: "/usr/share/zoneinfo/Asia/Tokyo" version: 2 jobs: test: <<: *defaults docker: - image: circleci/golang:1.9 steps: - checkout - restore_cache: key: vendor-{{ checksum "Gopkg.lock" }} - run: name: Setup For Test command: | if [ ! -e vendor ]; then dep ensure fi - run: name: Run Tests command: | make test - save_cache: key: vendor-{{ checksum "Gopkg.lock" }} paths: - vendor deploy_dev: <<: *defaults docker: - image: circleci/golang:1.9 steps: - checkout - restore_cache: key: vendor-{{ checksum "Gopkg.lock" }} - setup_remote_docker - run: name: Build docker image command: | make build - deploy: name: Deploy container command: | ./scripts/deploy.sh dev latest deploy_stg: <<: *defaults docker: - image: circleci/golang:1.9 steps: - checkout - restore_cache: key: vendor-{{ checksum "Gopkg.lock" }} - setup_remote_docker - run: name: Build docker image command: | make build - deploy: name: Deploy container command: | ./scripts/deploy.sh stg ${CIRCLE_TAG} workflows: version: 2 test_and_deploy: jobs: - test: filters: branches: only: /.*/ tags: only: /.*/ - deploy_dev: requires: - test filters: branches: only: master - deploy_stg: requires: - test filters: branches: ignore: /.*/ tags: only: /^v[0-9](\.[0-9]){2}$/
workflowの説明
testジョブ
- test: filters: branches: only: /.*/ tags: only: /.*/
テストはプルリクやマージで発火するようにしています。またtagに連動する際にrequire:しているので、tags:セクションも書いています。
deploy_devジョブ
- deploy_dev: requires: - test filters: branches: only: master
masterブランチにマージされたら発火するようにしています。testジョブをrequire:しているので、テスト後に実行されます。
deploy_stgジョブ
- deploy_stg: requires: - test filters: branches: ignore: /.*/ tags: only: /^v[0-9](\.[0-9]){2}$/
v1.0.0といったgit tagが発行されたら発火するようにしています。testジョブをrequire:しているので、テスト後に実行されます。
save_cache
golangはvendorディレクトリに依存ライブラリを保持します。test時は良いのですが、その後のdeployフローでは再取得するのは無駄です。なので
- save_cache: key: vendor-{{ checksum "Gopkg.lock" }} paths: - vendor
でキャッシュします。key名をlockファイルのハッシュベースで管理することで、lockファイルが更新されたら新しいキャッシュを作成&利用できます。
利用する際は
- restore_cache: key: vendor-{{ checksum "Gopkg.lock" }}
でできます。
またvendorディレクトリの有無でdep ensureを実行するか判断します。
- run: name: Setup For Test command: | if [ ! -e vendor ]; then dep ensure fi
tag名を利用
- deploy: name: Deploy container command: | ./scripts/deploy.sh stg ${CIRCLE_TAG}
${CIRCLE_TAG}という環境変数でtag名を利用できます。workflowでジョブが分けられていてもちゃんと参照できます。
環境変数の一覧は
Using Environment Variables - CircleCI
で確認できます。