CircleCI 2.0におけるGitタグ・ジョブ実行

Updated: / Reading time: 3 minutes

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では以下のように実行されました。

circleci-001

developブランチのビルドではbuildジョブだけ動作していることに対して、masterブランチの場合はbuildジョブとpushジョブが動作しました。

circleci-002

pushジョブでは最後のGitタグを取得してdocker pushが成功していることが分かります。

おわりに

CircleCI 2.0にするだけでビルドが早くなった!という記事をよく見ますが、まだ落とし穴が多く、移行はもう少し様子を見てからにします。