CI初心者がCircleCIでRubocopとRSpecの設定をするために急いで学んだこと


この記事の内容

急に職場でCIツールを扱うことになりました。CIツールはほとんど触ったことがなく...CIツールの設定に必要だったことをまとめました。
なお、扱っているプロジェクトはRailsのプロジェクトですので、設定は基本的にRailsの内容になります。

書いたコード

書いたコードを設定ごとに紹介していきます。全体のコードは最後に紹介します。なお全てのコードは.circleci/config.ymlに記載しています。

また、私のようにYAMLの基本文法からよくわからない!という人のために、CircleCIのために勉強したYAMLの基礎文法を下記にまとめました。

versions

CircleCIのバージョンです。後述するexecutorを使うために、今回は2.1にしています。

version: 2.1

基本文法(jobs ~ steps)

CircleCIの基本文法は下記の通り。

jobs:
  job-name: # ジョブの名前が入る。任意の名前でOK
    steps:
      - step1
      - step2
  • jobs ... これ以下に書いた内容が「ジョブ」であることを表します。
  • steps ... ひとつ一つのアクション。これらのアクションを集めると「ジョブ」になります。
  • ジョブ ... rspecrubocopなどひとまとまりの処理。

  • 参考:コンセプト

executors

executorsでは、ジョブのステップを実行する環境を定義します。複数JOB分をまとめて設定できます。設定項目は...

  • docker
  • working_directory(実行ディレクトリ)
  • environment(環境変数)

などなど。詳細は下記を参照してください。

executorに関して、実際に書いたコードは下記の通りです。

version: 2.1
executors:
  my-executor: # 任意の名前でOK
    docker:
      # 以下略

Docker

CircleCIの環境構築にはDockerが推奨されているようです。公式サイトのこちらのページからさまざまなCircleCI用のDockerが利用できます。

今回はRails 2.7.3のプロジェクトだったので、こちらを参考に以下のように記載しました。railsの場合は、yarnを入れる必要があるので、node.jsを含むタイプのものを使用するのがポイントです。

docker:
  - image: circleci/ruby:2.7.3-node-browsers

また、DBはpostgresを利用していたので、以下のようにも記載しています。

  - image: circleci/postgres:13.2

PostgresのDockerイメージは、CircleCIのDockerHubから、該当のバージョンを検索して記載します。

なお、公式サイトの下記の記載によると、

デフォルトでは環境変数POSTGRES_USERpostgresが設定されているようでした。
最終的に、dockerの項で書いたコードは以下の通りです。

docker:
  - image: circleci/ruby:2.7.3-node-browsers
    environment:
      BUNDLE_JOBS: 3
          BUNDLE_RETRY: 3
          BUNDLE_PATH: vendor/bundle
          PGHOST: 127.0.0.1
          PGUSER: 任意の名前
          RAILS_ENV: test
      - image: circleci/postgres:13.2
        environment:
          POSTGRES_USER: 任意の名前(上のPGUSERと同じ名前)
          POSTGRES_DB: アプリ名_test
          POSTGRES_PASSWORD: 任意のPW

こちらに書いてあった、Railsプロジェクトの設定コードを参考にしつつ、非推奨となっていたコマンドなどを置き換えています。

公式ではDBのパソワードについて特に言及がないのですが、比較的最近の変更でDBにパスワードを設定しないとエラーになるようでしたので、パスワードを設定しています。

ベタガキで良いのかは、謎です。。。。

Steps & 全体像

それぞれのJOBに書いたStepはこちらです。長いので、全体像も合わせて紹介します。基本的には、先に紹介したこちらの設定をもとに、古くなっていた箇所や、現行の仕様だとエラーになるところを変更しています。

なお、アプリに固有の設定は除いています。

version: 2.1
workflows: # 全体の流れを定義
  your_workflow_name: # ワークフローの名前(任意の名前)
    jobs: # 実行するジョブ(任意の名前)
      - your_job_name

executors: # 各ジョブの初期設定
  working_directory: ~/アプリの名前
  ruby_and_postgres:
    docker:
      - image: circleci/ruby:2.7.3-node-browsers
        environment:
          BUNDLE_JOBS: 3
          BUNDLE_RETRY: 3
          BUNDLE_PATH: vendor/bundle
          PGHOST: 127.0.0.1
          PGUSER: 任意の名前
          RAILS_ENV: test
      - image: circleci/postgres:13.2
        environment:
          POSTGRES_USER: 任意の名前(上のPGUSERと同じ名前)
          POSTGRES_DB: アプリ名_test
          POSTGRES_PASSWORD: 任意のPW

jobs:
  your_job_name:
    executor: ruby_and_postgres
    steps:
      - checkout
      # バンドル キャッシュを復元
      - restore_cache:
          keys:
            - rails-demo-bundle-v2-{{ checksum "Gemfile.lock" }}
            - rails-demo-bundle-v2-
      - run:
          name: バンドル インストール
          command: |
            gem install bundler -v 2.2.15
            bundle install
      # バンドル キャッシュを保存
      - save_cache:
          key: rails-demo-bundle-v2-{{ checksum "Gemfile.lock" }}
          paths:
            - vendor/bundle
      # Yarn の設定
      - restore_cache:
          keys:
            - rails-demo-yarn-{{ checksum "yarn.lock" }}
            - rails-demo-yarn-
      - run:
          name: Yarn のインストール
          command: yarn install --cache-folder ~/.cache/yarn
      # Yarn のキャッシュを保存
      - save_cache:
          key: rails-demo-yarn-{{ checksum "yarn.lock" }}
          paths:
            - ~/.cache/yarn
      # Rubocopの実行
      - run:
          name: Run Lint
          when: always
          command: bundle exec rubocop
      # DB関連の設定
      - run:
          name: DB起動待機
          command: dockerize -wait tcp://localhost:5432 -timeout 1m
      - run:
          name: Create DB
          command: |
            bin/rails db:migrate
            bin/rails db:schema:load --trace
      # テストの実行
      - run:
          name: Run Tests
          command: |
            bundle exec rspec --profile 10 \
                              --format RspecJunitFormatter \
                              --out test_results/rspec.xml \
                              --format progress \
                              $(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)
      - store_test_results:
          path: /tmp/test-results

その他

Gemのインストール

Stepsの最後にあるstore_test_results(テストの結果を保存する)を利用するために、rspec_junit_formatterをインストールしました。

Gemgile
group :test do
  gem 'rspec_junit_formatter'
end

Orbs

使ってみたかった便利な機能...。CircleCIの2.1から追加されたOrbsという機能によって、主な設定ファイルがひとまとめにできるようになたようです。

利用可能なOrbsはこちらのページに一覧になっていて、

例えば「Rails」で検索すると、

Railsの有名企業様達のOrbsが利用できるのでした。。。利用方法も詳しく載っていました。ありがたし。。。

orbs:
  rails: medpeer/[email protected]

今回は私の実力不足で利用に至らなかったのですが、次回は試してみたいです!

終わりに

色々苦労しましたが、勉強になりました。楽しかったので、機会があればもう少し深めてみたいです。
なお、本文中で書いた参考サイト以外にも、こちらの記事に大変お世話になりました!

細かなコマンドなどはこちらの記事で確認しながら進めさせていただきました。ありがとうございました。