.circleci/config.ymlファイル

.circleci/config.ymlが設定ファイル。

Railsプロジェクトでの設定例。

Gemfileのgroup :testgem 'rspec_junit_formatter'を追加しておくこと。

version: 2

jobs:
  # 前準備 ============================================================
  build:
    docker:
      - image: circleci/ruby:2.7.2-node

    steps:
      - checkout

      # Bundle Install
      - restore_cache:
          keys:
            - gem-v1-dependencies-{{ checksum "Gemfile.lock" }}
            - gem-v1-dependencies-
      - run:
          name: bundle install
          command: |
            bundle install --jobs=4 --retry=3 --path vendor/bundle
      - save_cache:
          paths:
            - ./vendor/bundle
          key: gem-v1-dependencies-{{ checksum "Gemfile.lock" }}

      # Yarn Install
      - restore_cache:
          keys:
            - yarn-v1-dependencies-{{ checksum "yarn.lock" }}
            - yarn-v1-dependencies-
      - run:
          name: yarn install
          command: yarn
      - save_cache:
          paths:
            - ./node_modules
          key: yarn-v1-dependencies-{{ checksum "yarn.lock" }}

  # Rubocop ============================================================
  lint:
    docker:
      - image: circleci/ruby:2.7.2-node

    steps:
      - checkout

      # キャッシュしたGemの復元
      - restore_cache:
          keys:
            - gem-v1-dependencies-{{ checksum "Gemfile.lock" }}
            - gem-v1-dependencies-

      # Bundleの参照先変更
      - run:
          name: config bundler
          command: |
            bundle config set path vendor/bundle

      # Rubocop結果をHTMLで出力しアーティファクトに追加
      - run:
          name: Rubocop
          command: |
            mkdir -p /tmp/rubocop-results/
            bundle exec rubocop -f html -o /tmp/rubocop-results/rubocop.html
      - store_artifacts:
          path: /tmp/rubocop-results

  # Rspec ============================================================
  rspec:
    docker:
      - image: circleci/ruby:2.7.2-node

    steps:
      - checkout

      # キャッシュしたGemの復元
      - restore_cache:
          keys:
            - gem-v1-dependencies-{{ checksum "Gemfile.lock" }}
            - gem-v1-dependencies-
      # キャッシュしたnode_modulesの復元
      - restore_cache:
          keys:
            - yarn-v1-dependencies-{{ checksum "yarn.lock" }}
            - yarn-v1-dependencies-

      # Bundleの参照先変更
      - run:
          name: config bundler
          command: |
            bundle config set path vendor/bundle

      # Railsで使うDBの作成
      - run:
          name: create db
          command:  bin/rails db:schema:load

      # Rspecの実行
      # 実行結果をJUnit XMLで出力(/tmp/rspec-results/rspec.xml)
      #  => TESTSタブで利用する
      # profile結果も出力(/tmp/rspec-results/rspec-profile.txt)
      #  => ARTIFACTSタブで表示する
      - run:
          name: run rspec
          command: |
            mkdir -p /tmp/rspec-results/
            bundle exec rspec \
              --profile \
              --format RspecJunitFormatter \
              --out /tmp/rspec-results/rspec.xml \
              $(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings) \
               > /tmp/rspec-results/rspec-profile.txt

      - store_test_results:
          path: /tmp/rspec-results
      - store_artifacts:
          path: /tmp/rspec-results

# ============================================================
workflows:
  version: 2
  build_and_test:
    jobs:
      - build
      - lint:
          requires:
            - build
      - rspec:
          requires:
            - build

jobs.JOB-NAME

ワークフローの単位。

jobs直下のbuildlintなどは任意の文字列を指定可能。workflowsで実行の依存関係などを指定するのに使う。

jobs.JOB-NAME.docker

使用するDockerイメージを指定する。複数指定可能。CircleCIのイメージだけでなく、DockerHubにある他のイメージも指定可能。自作イメージをDockerHubにあげておけば指定することもできる。

jobs.JOB-NAME.working_directory

ステップを実行するディレクトリ。デフォルトは~/project

jobs.JOB-NAME.steps

実行するコマンドなどを指定する。配列。

  • checkout
    • リポジトリからコードを取得する。
  • save_cache
    • pathsのファイルやディレクトリをkeyに紐づけてキャッシュする。
    • 数ヶ月保持される。
  • restore_cache
    • keyに紐づいたキャッシュを復元する(save_cacheと対で指定する)
  • run
    • コマンドの実行
  • store_artifacts
    • pathで指定されたディレクトリにあるファイルをARTIFACTSタブから表示できるようにする
    • destinationに指定した値はARTIFACTSタブで表示される時のabc/file-nameabc部分になる。未指定ならpathのディレクトリ名になる。
  • store_test_results
    • pathで指定されたディレクトリにあるJUnit XML を読み込んでTESTタブに結果を表示する

workflows.WORKFLOW-name.jobs

ジョブの依存関係を指定する。以下の例ならbuildを実行してからlintrspecが並列に実行される(無料版だとコンテナ数が1つなので並列にはならない。Performanceプランだと80並列実行できるっぽい?)。

  build_and_test:
    jobs:
      - build
      - lint:
          requires:
            - build
      - rspec:
          requires:
            - build

早く終わるようにする

コスト削減のために早く終わるようにする

CircleCIは無料プランだと1週間に2500クレジット分利用できる。無料プランで利用できるマシンは10クレジット/分のMediumだけなので、結論としては週250分間(4時間10分)だけ実行できることになる。

Performanceプランにすると25000クレジット単位で購入となるため、利用料金を抑えるためには、やはり実行時間に気をつけなければならない。

コスト削減のために早く終わるようにする方法

  • save_cacherestore_cacheを用いて、bundle installの結果などをキャッシュさせる。
  • 無闇にジョブを分けたり、コンテナを作らない(効果があるか不明)。
    • コンテナの起動やrestore_cacheのオーバーヘッド分時間がかかる。

待機時間削減のために早く終わるようにする

実行時間(コスト)の削減にはならないが、並列でジョブやステップを実行することで完了までの時間を短縮させることができる。

待機時間削減のために早く終わるようにする方法

無料プランでは方法はない。

Performanceプランでは並列実行ができるため、workflowsでジョブの並列化させたり、parallelismを指定してステップの並列化ができる。参考:テストの並列実行