CircleCIのconfig.ymlの重複コードを減らす


yamlにはアンカーとエイリアスという値を再利用するための仕組みがあり、それを利用することでconfig.ymlの重複コードを減らしDRYにできます。
実際の設定値の中にアンカー定義があると読みにくいので、私はanchors要素としてアンカーの定義をまとめています。

全体像はこんな感じ。

./circleci/config.yml
version: 2
anchors:
  job_base: &job_base
    docker:
      - image: circleci/android:api-28-node
    working_directory: ~/repo
    environment:
      JVM_OPTS: -Xmx3200m
      TERM: dumb
  restore_gradle_cache:  &restore_gradle_cache
    - restore_cache:
        keys:
          - v1-dependencies-{{ checksum "build.gradle" }}
          - v1-dependencies-
  resolve_gradle: &resolve_gradle
    - run: ./gradlew dependencies
  save_gradle_cache: &save_gradle_cache
    - save_cache:
        paths:
          - ~/.gradle
        key: v1-dependencies-{{ checksum "build.gradle" }}
  resolve_gradle_dependencies_with_cache: &gradle_cache
    - restore_cache:
        keys:
          - v1-dependencies-{{ checksum "build.gradle" }}
          - v1-dependencies-
    - run: ./gradlew dependencies
    - save_cache:
        paths:
          - ~/.gradle
        key: v1-dependencies-{{ checksum "build.gradle" }}
jobs:
  fabric_debug:
    <<: *job_base
    steps:
      - checkout
      - run: bundler install
      - <<: *restore_gradle_cache
      - <<: *resolve_gradle
      - <<: *save_gradle_cache
      - run: fastlane betaDebug
  fabric_release:
    <<: *job_base
    steps:
      - checkout
      - run: bundler install
      - <<: *restore_gradle_cache
      - <<: *resolve_gradle
      - <<: *save_gradle_cache
      - run: fastlane betaRelease
  release:
    <<: *job_base
    steps:
      - checkout
      - run: bundler install
      - <<: *restore_gradle_cache
      - <<: *resolve_gradle
      - <<: *save_gradle_cache
      - run: fastlane deploy
workflows:
  version: 2
  fabric:
    jobs:
      - fabric_debug:
          filters:
            branches:
              ignore:
                - master
      - fabric_release:
          filters:
            branches:
              ignore:
                - master
  release:
    jobs:
      - release:
          filters:
            branches:
              only:
                - master
            tags:
              only:
                - /^.*$/

job_base

job_base で各ジョブに共通する設定を定義しています。
これによって、実際のジョブ定義では主にstepsだけ設定するだけで済むようになります。

キャッシュ関連

restore_gradle_cache resolve_gradle save_gradle_cache をまとめて1つの定義にしたいかもしれませんが、yamlのアンカーとエイリアスではそれは実現できないようです。
(配列を配列の要素として展開することができないっぽい?)
いつかできるといいなぁ。

デプロイ設計

この設定ファイルでは以下のルールでジョブを実行しています
- master以外のブランチにプッシュされた時は、fabric_debugジョブとfabric_release ジョブを並列で実行
- masterにタグがついた時は、 release ジョブを実行

注意

コマンドラインツールでのローカル実行(circleci cli execute foo) だと、このアンカーが正常に解析されずにエラーになってしまった。