patorashのブログ

方向性はまだない

CircleCI 2.1を使うようにして設定ファイルをリファクタリングした

CircleCIはこの時に書いた設定のまま使ってました。 patorash.hatenablog.com

2018年の後半にバージョン2.1が出たという話は聞いていたものの、なかなか試せていませんでした。隙間時間ができたので、この課題にケリをつける!

CircleCI 2.1の変更点

大きな変更点は、Executors, Commands, Orbだと思います。また、それぞれで引数を設定できるようになりました。

Executors

実行環境の定義を再利用するための仕組みです。名前がつけられるのがありがたい。 基本的には、dockerのイメージを配列で指定していきます。 以下のような感じ。

version: 2.1

executors:
  default:
    working_directory: ~/project
    docker:
      - image: circleci/ruby:2.5.3-node-browsers
        environment:
          RAILS_ENV: test
          RACK_ENV: test
          TZ: "/usr/share/zoneinfo/Asia/Tokyo"
      - image: circleci/postgres:9.5-alpine-postgis-ram
        environment:
          TZ: "/usr/share/zoneinfo/Asia/Tokyo"

Commands

stepsで指定する処理に名前をつけて、まとめることができるようになりました。関数ですね。

version: 2.1

commands:
  save_node_module_cache:
    steps:
      - save_cache:
          key: v1-yarn-{{ checksum "yarn.lock" }}
          paths:
            - ./node_modules
  restore_node_module_cache:
    steps:
      - restore_cache:
          keys:
            - v1-yarn-{{  checksum "yarn.lock" }}
            - v1-yarn-

jobs:
  test:
    executor: default
    steps:
      - checkout
      - restore_node_module_cache
      - run: yarn
      - save_node_module_cache
      # 以降の処理は省略

Orb

Orbはサードパーティが公開したstepsを利用する仕組みです。ansible galaxyみたいに、よく使う設定を再利用できるので助かります!

Orbを使うには、設定のOrganizationのSecurityから、Orbを利用できるようにする必要があります。

f:id:patorash:20190125150835p:plain
CircleCIでOrbを使えるように設定する

こんな感じ。

version: 2.1

orbs:
  ruby-orbs: sue445/ruby-orbs@1.4.1

jobs:
  test:
    executor: default
    steps:
      - checkout
      - ruby-orbs/bundle-install
      # 以降の処理は省略

2.0の頃との違い

以前は設定の再利用をするために、yamlの記法でやっていました。

version: 2

references:
  restore_node_module_cache: &restore_node_module_cache
    restore_cache:
      keys:
        - v1-yarn-{{ checksum "yarn.lock" }}
        - v1-yarn

jobs:
  steps:
    - checkout
    - *restore_node_module_cache

これでも結構短くはなっていましたが、やはり見た目が煩雑…。

2.1からは普通に定義できるようになったのが嬉しいところです。

version: 2.1

commands:
  restore_node_module_cache:
    steps:
      - restore_cache:
          keys:
            - v1-yarn-{{ checksum "yarn.lock" }}
            - v1-yarn-

jobs:
  steps:
    - checkout
    - restore_node_module_cache           

前のやつをリファクタリングしてみる

ということで、yamlのマージを使っていたのをやめて、Executors, Commands, Orbを使うようにしてみました。

OrbはTLで以前に見かけたbundle updateのPRの自動化とbundle installのキャッシュ、リストアなどやってくれるやつを覚えていたので、練習も兼ねてそれを使わせてもらいました。

sue445.hatenablog.com

で、完成版がこちら。ライブラリのキャッシュを一気に行いたくなったので、準備を並列化していたのをやめました。

version: 2.1

orbs:
  ruby-orbs: sue445/ruby-orbs@1.4.1

refefences:
  default_settings: &default_settings
    working_directory: ~/project

  ruby_docker_image: &ruby_docker_image
    image: patorash/circle_ci_ruby:2.5.3-node-browsers
    environment:
      RAILS_ENV: test
      RACK_ENV: test
      TZ: "/usr/share/zoneinfo/Asia/Tokyo"

executors:
  default:
    <<: *default_settings
    docker:
      - *ruby_docker_image

  rspec:
    <<: *default_settings
    docker:
      - *ruby_docker_image
      - image: circleci/postgres:9.6-alpine-postgis
        environment:
          TZ: "/usr/share/zoneinfo/Asia/Tokyo"

commands:
  save_code_cache:
    steps:
      - save_cache:
          key: v1-repo-{{ .Environment.CIRCLE_SHA1 }}
          paths:
            - ~/project

  restore_code_cache:
    steps:
      - restore_cache:
          keys:
            - v1-repo-{{ .Environment.CIRCLE_SHA1 }}

  save_node_module_cache:
    steps:
      - save_cache:
          key: v1-yarn-{{ checksum "yarn.lock" }}
          paths:
            - ./node_modules

  restore_node_module_cache:
    steps:
      - restore_cache:
          keys:
            - v1-yarn-{{ checksum "yarn.lock" }}
            - v1-yarn

  setup_database:
    steps:
      - run: bundle exec rake db:create
      - run: bundle exec rake db:schema:load

jobs:
  prepare_test:
    executor: default
    steps:
      - checkout
      - restore_node_module_cache
      - ruby-orbs/bundle-install
      - run: yarn
      - save_node_module_cache
      - save_code_cache

  test:
    executor: rspec
    parallelism: 4
    steps:
      - restore_code_cache
      - run: bundle --path vendor/bundle
      - setup_database

      # run tests!
      - run:
          name: run tests
          command: |
            mkdir /tmp/test-results
            TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"

            bundle exec rspec --format progress \
                            --format RspecJunitFormatter \
                            --out /tmp/test-results/rspec.xml \
                            --format progress \
                            $TEST_FILES

      # Save artifacts
      - store_test_results:
          path: /tmp/test-results

      - store_artifacts:
          path: /tmp/test-results
          destination: test-results

workflows:
  build:
    jobs:
      - prepare_test
      - test:
          requires:
            - prepare_test

Commandsのおかげで何をしている処理なのかが明確になって読みやすくなりました。あとはOrbが便利ですね。gemのキャッシュとリストアの設定を書かなくて済むようになったし、別のプロジェクトでも使いまわせるのがありがたいです。