LoginSignup
11
3

More than 5 years have passed since last update.

CircleCIのconfig.ymlをリファクタリングする

Last updated at Posted at 2018-12-15

概要

  • CircleCI2.1のcommandsとexecutorsは便利なので使ってないなら使いましょう
  • CircleCIというよりはYAMLの記法にあるアンカー(&)、エイリアス(*)、マージ(<<)をうまいこと使いましょう

commandsとexecutorsについて

commands (requires version: 2.1)

よく使うパターンのstepsをパラメータ指定で使い回せる。

sample
commands:
  sayhello:
    description: "A very simple command for demonstration purposes"
    parameters:
      to:
        type: string
        default: "Hello World"
    steps:
      - run: echo << parameters.to >>

ちなみに弊社で実際使ってる例はこのくらいでした (パラメータは結局使っていなかった :innocent:

利用例
commands:
  xxxxxx_checkout: # 共通のチェックアウト
    steps:
      - checkout:
          path: /xxxxxx
  go_mod_download: # go moduleのdownloadとcache
    steps:
      - restore_cache:
          name: Restore go modules cache
          keys:
            - mod-{{ .Environment.COMMON_CACHE_KEY }}-{{ checksum "../go.mod" }}
      - run: go mod download
      - save_cache:
          name: Save go modules cache
          key: mod-{{ .Environment.COMMON_CACHE_KEY }}-{{ checksum "../go.mod" }}
          paths:
            - /xxxxxx/server/pkg/mod/cache

executors (requires version: 2.1)

dockerイメージ、環境変数、workingDirectoryを1セットにして使い回せる感じです。

sample
version: 2.1
executors:
  my-executor:
    docker:
      - image: circleci/ruby:2.5.1-node-browsers

弊社だとMonorepoにしてるので、色々なbuildが存在しているのですがgolangのbuildは、同じexecutorを使いまわせたりできています。

利用例
executors:
  lambda-build-executor:
    docker:
      - image: kyokomi/docker-golang
        environment:
          <<: *env-xxxxxx-go-path
    working_directory: /xxxxxx/server/src/cluster/lambda

  lambda-deploy-executor:
    docker:
      - image: hashicorp/terraform:latest
        environment:
          <<: *env-aws-key-zzzzzz-foobar-deploy

  yyyyyy-build-executor:
    docker:
      - image: kyokomi/docker-golang
        environment:
          APP_NAME: yyyyyy
          <<: *env-xxxxxx-go-path
    working_directory: /xxxxxx/server/src/cluster/yyyyyy

  aws-ecr-deploy-executor:
    docker:
      - image: kyokomi/docker-golang

  aws-ecs-deploy-executor:
    docker:
      - image: hashicorp/terraform:latest

アンカー(&)、エイリアス(*)、マージ(<<

アンカーとエイリアス

たとえばこんな感じにmysqlが起動しているか確認する run があるとして、 &run-waitmysql というアンカーを設定すると run: *run-waitmysql で同じ内容を実行してくれます。


...

      - run: &run-waitmysql
          name: Waiting for MySQL to be ready
          command: |
            i=0
            while true; do
              if exec 3<> /dev/tcp/127.0.0.1/3306; then
                exit 0
              else
                ((i++))
                echo $i
                [ $i -gt 30 ] && exit 1
              fi
              sleep 1
            done
          shell: /bin/bash

      - run: *run-waitmysql # run: &run-waitmysql と同じ内容を実行してくれます

アンカーをマージ

AWS_ACCESS_KEY_IDやAWS_SECRET_ACCESS_KEYをそのままベタッと書くとあとで見たときにこのkeyって何のkeyだっけ?となることが多く。referencesに定義してアンカーを設定してマージを使うと整理できて便利です。

整理しておく
references:
  # とある権限をもつaws keyその1
  env-aws-key-xxxxxx-ci: &env-aws-key-xxxxxx-ci
    AWS_DEFAULT_REGION:    ap-northeast-1
    AWS_ACCESS_KEY_ID:     AKIAIxxxxxxxxxxxxxx
    AWS_SECRET_ACCESS_KEY: xxxxxxxxxxxxxxxxxxxxxxxxxxxxx

  # とある権限をもつaws keyその2
  env-aws-key-zzzzzzz-foobar-deploy: &env-aws-key-zzzzzz-foobar-deploy
    AWS_DEFAULT_REGION:    ap-northeast-1
    AWS_ACCESS_KEY_ID:     AKIxxxxxxxxxxxxxxx
    AWS_SECRET_ACCESS_KEY: fffffffffffffffffffffffffffffffff

  # 全buildでGOPATHは共通、GO111MODULEはデフォルトでONにしたい環境変数
  env-go-path: &env-xxxxxx-go-path
    GOPATH:      "/xxxxxx/server:/go"
    GO111MODULE: "on"
マージする
executors:
  lambda-build-executor:
    docker:
      - image: kyokomi/docker-golang
        environment:
          <<: *env-xxxxxx-go-path # ここでマージしている
    working_directory: /xxxxxx/server/src/cluster/lambda

  lambda-deploy-executor:
    docker:
      - image: hashicorp/terraform:latest
        environment:
          <<: *env-aws-key-zzzzzz-foobar-deploy # ここでマージしている
マージ後のイメージ
executors:
  lambda-build-executor:
    docker:
      - image: kyokomi/docker-golang
        environment:
          GOPATH:      "/xxxxxx/server:/go"
          GO111MODULE: "on"
    working_directory: /xxxxxx/server/src/cluster/lambda

  lambda-deploy-executor:
    docker:
      - image: hashicorp/terraform:latest
        environment:
          AWS_DEFAULT_REGION:    ap-northeast-1
          AWS_ACCESS_KEY_ID:     AKIxxxxxxxxxxxxxxx
          AWS_SECRET_ACCESS_KEY: fffffffffffffffffffffffffffffffff

ちなみに、この辺をうまいこと使えば実は commandsexecutors もなくてもなんとかなっていました。
が、使い方をミスるとわけわからないDSLみたいになるので一定のルールを決めておくといいと思います。
(prefix env-xxxxなら 環境変数をマージする用、 run-xxxx なら run:でエイリアスする等など)

おわり

.circleci/config.yml なかなかリファクタせずにコピペで済ませてしまうことが多く、いざ編集するときメンテナンスが大変でしたが、こうやって整理していくことでプログラムぽくしていくことで1000step超えのymlでも見渡しがいいようしていけるといいですね。
(config.yml分割したい...)

参考

11
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
3