最近Terraformの勉強をはじめてドキュメントを一通り読んだのでさてコードを書くかというのが今
個人でinfra
というリポジトリを作っていてpacker用のmanifestファイルとかが入っている
特にリポジトリをわける理由もなかったので、このリポジトリにterraform
というディレクトリをほった
こんな感じ↓
. ├── README.md ├── packer └── terraform
問題
CI環境にはCircleCIを使っているのですが、毎回CIを回す時にpacker buildしたりterraform planをするのかということ
出来れば変更したファイルによってきりかえたい
つまりpacker
ディレクトリ内のファイルが変更された時のみpacker build
terraform
ディレクトリ内のファイルが変更された時のみterraform plan
をしたい
準備
まずは今回やりたいことに 特定のディレクトリ内が変更された 時に処理を行う
とあるので、このトリガーを作る必要がある
そこで今回は次のようなスクリプトを用意した
#!/bin/bash if [ "${CIRCLE_BRANCH}" = "master" ]; then # masterはマージコミットなどの場合なので一つ前と比較する DIFF_TARGET="HEAD^ HEAD" else DIFF_TARGET="origin/master" fi DIFF_FILES=(`git diff ${DIFF_TARGET} --name-only --relative=${1}`) if [ ${#DIFF_FILES[@]} -eq 0 ]; then exit 1 else exit 0 fi
is_changed
という名前で保存したとする
使い方はシンプルでterraformディレクトリ配下のコミットがあったかを知りたい時は is_changed "terraform"
とすれば良い
実際は↓のように使う
if is_changed "terraform"; then terraform plan fi
今回はこのファイルをリポジトリ配下の bin/is_changed
に保存する
CircleCIの設定
まずは今回の完成品から
version: 2 common_stepup_commaand: &common_stepup_commaand command: | echo 'export PATH=$PATH:${CIRCLE_WORKING_DIRECTORY}/bin' >> $BASH_ENV jobs: build: docker: - image: busybox steps: - run: echo "これはビルドタスクです" test_terraform: docker: - image: circleci/golang:1.11.1 steps: - checkout - run: <<: *common_stepup_commaand - run: name: Run command: | if is_changed "terraform"; then echo "terraformに変更があったよ" else echo "terraformに変更はなかったよ" fi test_packer: docker: - image: circleci/golang:1.11.1 steps: - checkout - run: <<: *common_stepup_commaand - run: name: Run command: | if is_changed "packer"; then echo "packerに変更があったよ" else echo "packerに変更はなかったよ" fi workflows: version: 2 test: jobs: - build - test_terraform: requires: - build - test_packer: requires: - build
処理としては次のようにbuild jobが成功した後にtest_packerとtest_terraformのjobが実行される
ただtest_packer, test_terraformのどちらのjobも処理の中でさきほど作成した is_changed
を呼出している
これにより特定のファイルが実行された時に処理を行うことが実現できた
実現できた??
本当は指定のディレクトリ配下にコミットされた時のみjobを実行したかったが、
今回はjob自体は実行されて、そのstep内のcommandで実行するかどうかを分岐させている
なのでちょっとこれじゃない感が出てしまっている
CircleCIは任意のjobを実行することの出来るAPIが提供されているのでこれをbuild job内で分岐させてリクエストすることも考えた
ただこれを使うとworkflowにはのらなくなり、それぞれが単独のjobとして実行されてしまう
そのためbuild jobが成功すればAPIでリクエストしたjobが失敗したとしてもworkflow自体は成功という判定になってしまう
ということでこんな形になった
もっと良い方法思いついたらupdateしていきたい