CircleCIの書き方ノウハウまとめ 2019


CircleCIの設定が避けて通れないスキルになってきたのでここいらでざっくりまとめて置きます。
CircleCI 2.0 Dockerを利用します。コピペではなくてある程度は理解しながら進みたいと思います。
cronなどの設定もできるのでjenkinsや他のjobサーバーの代替としても利用できるはずです。
また、CircleCIAPIを利用して特定のworkflowをトリガーする事も可能なのでこれからいろいろなユースケースに対応できます。Dockerで開発環境を作成してCircleCIでもDockerImageごと活用するなど一石二鳥。ただし。。。遅いというのは言うまでもないです。

CircleCIの設定

検証環境: macOS Mojave / Rails 5.2.2 / Ruby 2.5.1

1. ファイルの設置場所

.circleci/config.yml

2. 書き方いろいろ

configファイルの中で定義済みの変数環境変数を利用する事が可能です。
workflows: jobのセットをワークフローとして管理できます。今回はbuildとdeployの2つのフェーズに分けています。Aのjobが完了していないとBのjobが動かないなど依存関係を設定できます。

2.0 workflowsの定義

workflows:
  version: 2
  build_and_deploy:
    jobs:
      - build
      - confirm_deploy:
          type: approval
          requires:
          - build
      - deploy:
          requires:
          - confirm_deploy

jobs: jobを定義します。Dockerイメージの定義 -> 環境の設定 -> コードのチェックアウト -> 実際に実行するstep -> テストの実行までセットで書かれている事が多いようです。
こちらのサンプルでは、buildタスクとconfirm_deployタスクとdeployタスクの3つのjobが設定されています。

2.1 それぞれのjobの定義

jobs:
  build:
    working_directory: ~/my-app
  deoloy:

jobsの一段落下に定義していきます。

2.2 Dockerイメージの利用の定義

circleci/ruby:2.5.1-node-browsersとpostgres:9.6のイメージを利用します。
イメージの命名規則PostgreSQLのビルド済みイメージを参照しながら適切なバージョンを選択します。environmentに環境変数を設定できます。

ビルド済みイメージ
https://github.com/CircleCI-Public/circleci-dockerfiles/tree/master/ruby/images/
https://github.com/docker-library/ruby/

parametersを使うと変数のように値を再利用する事もできます。

docker:
- image: circleci/ruby:2.5.1-node-browsers
  environment:
  - RAILS_ENV: test
  - PGHOST: 127.0.0.1
  - PGUSER: root
  - SELENIUM_CHROME_HEADLESS: true
- image: circleci/postgres:9.6
  environment:
  - POSTGRES_USER: root
  - POSTGRES_DB: ******

2.3 Docker以外のjobsの要素について

stepsの中に実際のタスクを記載します。
working_directoryで作業ディレクトリを指定します。$CIRCLE_WORKING_DIRECTORYで参照する事も可能です。
checkoutはworking_directoryにコードをチェックアウトする為のコマンドです。
runでコマンドを実行できます。
save_cacherestore_cachebundle installyarn installなどをキャッシュするのが一般的です。
persist_to_workspaceを最後に宣言する事で次のworkspaceにテンポラリファイルの状態が引き継がれるのでjobを細かく区切りやすいです。同じコマンドを何度も実行する手間が省けます。

2.4 buildのtask定義例

build:
  docker:
  - image: circleci/ruby:2.5.1-node-browsers
    environment:
    - RAILS_ENV: test
    - PGHOST: 127.0.0.1
    - PGUSER: root
    - SELENIUM_CHROME_HEADLESS: true
    - ENECHANGE_PROFILER_SERVER_URL: http://enechange-profiler-sample2.a36rk5bkqp.ap-northeast-1.elasticbeanstalk.com/profile/
  - image: circleci/postgres:9.6
    environment:
    - POSTGRES_USER: root
    - POSTGRES_DB: *************
  working_directory: ~/repo
  steps:
  - checkout
  - run: |
      git submodule init
      git submodule update
  - restore_cache:
      keys:
      - v1-dependencies-{{ checksum "Gemfile.lock" }}-{{ checksum "yarn.lock" }}
  - run:
      name: Install System Dependencies
      command: |
        sudo apt-get install fonts-migmix
  - run:
      name: Install Chrome
      command: |
        sudo apt install -y libappindicator3-1
        curl -L -o google-chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
        sudo dpkg -i google-chrome.deb
        sudo sed -i 's|HERE/chrome\"|HERE/chrome\" --disable-setuid-sandbox|g' /opt/google/chrome/google-chrome
        rm google-chrome.deb
        /opt/google/chrome/google-chrome --version
  - run:
      name: install dependencies
      command: |
        bundle install --jobs=4 --retry=3 --path vendor/bundle
  - run:
      name: install frontend dependencies
      command: yarn install
  - save_cache:
      key: v1-dependencies-{{ checksum "Gemfile.lock" }}-{{ checksum "yarn.lock" }}
      paths:
        - vendor/bundle
        - node_modules
  - run:
      name: Wait for DB
      command: dockerize -wait tcp://127.0.0.1:5432 -timeout 120s
  - run:
      name: Database setup
      command: bin/rails db:create; bin/rake db:setup; bin/rake db:seed --trace
  - run: |
      mkdir /tmp/test-results
      bundle exec rspec --format progress \
                        $(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)
  - run: echo "Hello, world!" > test
  - persist_to_workspace:
      root: .
      paths:
      - tmp
      - vendor
      - node_modules
      - test

2.5 deployのtask定義例

今回はebを使っているのでebコマンドを直接利用してdeployを実施します。
cronなどのtaskも定義できるので定期的にバッチ処理を実行するなども可能です。

deploy:
docker:
- image: circleci/ruby:2.5.1-node-browsers
working_directory: ~/repo
steps:
- checkout
- attach_workspace:
    at: ~/repo
- run: |
    git submodule init
    git submodule update
- run:
    name: Install eb Command
    command: |
      sudo apt-get -y -qq update
      sudo apt-get install python-pip python-dev build-essential
      sudo pip install awsebcli --upgrade
- run:
    name: Deploy Development
    command: |
      echo "Deploying.......$CIRCLE_BRANCH"
      eb deploy -l `date +%Y%m%d_%H%M%S` ***********

3. ローカルデバック方法

インストール

brew install circleci
circleci update install

文法チェック

circleci config validate -c .circleci/config.yml

ビルド

circleci build

とりあえずこんな感じで簡単なRails webアプリケーションのデフォルト設定が完了しました。