CircleCI 2.0におけるGitタグ・ジョブ実行
CircleCI 1.0では正常動作したGitタグ・ジョブ実行が、CircleCI 2.0ではうまく動きませんでした。どうにかしようと四苦八苦したログをここに残します。
結論
GitタグをpushしてもCircleCIジョブが起動しませんでした。なので、masterブランチにpushされたときに最後のGitタグを取得してデプロイ処理を実行するようにしました。
動作確認用にu6k/sample-circleci-2.0リポジトリを作成しましたので、こちらの.circleci/config.yml
をご覧ください。
Gitタグ・ジョブ実行の関連スレッド
CircleCIコミュニティや公式ドキュメントの関連スレッドを挙げます。
このスレッドによると、2017/8にGitタグ・ジョブ実行が有効になったとのこと。
「Git Tag Job Execution」にジョブ(というかワークフロー)の設定方法が説明されていますが、この通りに設定してもそもそもGitタグのpushでCircleCIジョブが起動しませんでした。
config.yml
の説明
GitタグのpushでCircleCIジョブが起動しないので、しかたないのでmasterブランチのpushで必要な処理を実行するようにしました。以下のconfig.yml
が設定例です。
version: 2
jobs:
build:
docker:
- image: docker:17.07.0-ce-git
steps:
- checkout
- setup_remote_docker:
version: 17.07.0-ce
- run:
name: Build docker image
command: docker build -t u6kapps/sample-circleci-2.0 .
- run:
name: Test docker image
command: docker run u6kapps/sample-circleci-2.0
- run:
name: Save docker image
command: |
mkdir -p ~/caches
docker save u6kapps/sample-circleci-2.0 -o ~/caches/image.tar
- save_cache:
key: docker-{{ .Revision }}
paths:
- ~/caches/image.tar
push:
docker:
- image: docker:17.07.0-ce-git
steps:
- checkout
- setup_remote_docker:
version: 17.07.0-ce
- restore_cache:
key: docker-{{ .Revision }}
paths:
- ~/caches/image.tar
- run:
name: Load docker image
command: docker load -i ~/caches/image.tar
- run:
name: Push docker image
command: |
TAG=`git describe --abbrev=0`
docker login -u ${DOCKER_USER} -p ${DOCKER_PASS}
docker tag u6kapps/sample-circleci-2.0 u6kapps/sample-circleci-2.0:${TAG}
docker push u6kapps/sample-circleci-2.0
workflows:
version: 2
build-and-push:
jobs:
- build
- push:
requires:
- build
filters:
branches:
only: master
要所を説明します。
docker:
- image: docker:17.07.0-ce-git
ジョブで使用するDockerイメージを指定します。この時、-git
のイメージを使用しないと、git
コマンドが使用できません。
- setup_remote_docker:
version: 17.07.0-ce
setup_remote_docker
ステップは隔離されたDocker環境を構築するためのステップです。ここでバージョンを指定しない場合、docker image
で指定したバージョンとは異なるデフォルトのバージョン(17.03?)が割り当てられ、multi stage buildが使えません。
なので、無難にdocker image
で指定したバージョンと同じバージョンを指定しておきます。
- run:
name: Save docker image
command: |
mkdir -p ~/caches
docker save u6kapps/sample-circleci-2.0 -o ~/caches/image.tar
- save_cache:
key: docker-{{ .Revision }}
paths:
- ~/caches/image.tar
- restore_cache:
key: docker-{{ .Revision }}
paths:
- ~/caches/image.tar
- run:
name: Load docker image
command: docker load -i ~/caches/image.tar
ジョブをまたいだファイルの使用は、キャッシュを経由する必要があります。なので、ビルド・ジョブでDockerイメージをtarに出力してキャッシュを保存、pushジョブでキャッシュからtarを取得してDockerイメージを復元します。
- run:
name: Push docker image
command: |
TAG=`git describe --abbrev=0`
docker login -u ${DOCKER_USER} -p ${DOCKER_PASS}
docker tag u6kapps/sample-circleci-2.0 u6kapps/sample-circleci-2.0:${TAG}
docker push u6kapps/sample-circleci-2.0
CircleCI 1.0では${CIRCLE_TAG}
という環境変数にGitタグが設定されていましたが、env
コマンドで確認したところGitタグのような環境変数はありませんでした。しかたないのでgit describe
で最後のGitタグを取得して、それをDockerタグに設定します。
workflows:
version: 2
build-and-push:
jobs:
- build
- push:
requires:
- build
filters:
branches:
only: master
pushジョブをmasterブランチの時のみ実行するように設定しています。CircleCI 1.0の時はGitタグがpushされた時のみ、という設定ができましたが。
実際の動作
developブランチとmasterブランチでファイルを修正してGit pushしたところ、CircleCIでは以下のように実行されました。
developブランチのビルドではbuildジョブだけ動作していることに対して、masterブランチの場合はbuildジョブとpushジョブが動作しました。
pushジョブでは最後のGitタグを取得してdocker push
が成功していることが分かります。
おわりに
CircleCI 2.0にするだけでビルドが早くなった!という記事をよく見ますが、まだ落とし穴が多く、移行はもう少し様子を見てからにします。