はじめに
CircleCIを使用してRailsのサンプルプロジェクトのCIをしてみました。
古い記事だとOrbを使っていなかったり、イメージが古かったりすることがありますが、本記事では現在CircleCI公式が出している情報に基づいて設定し、動作確認まで取れたものを記載します。
環境
- Ruby:2.7.2
- Rails:6.1
- DB:PostgreSQL
CircleCIのRailsデモプロジェクトの動作確認
CircleCI公式が用意してくれているデモ用のリポジトリがあるので、まずはそれをforkして動作確認してみます。
以下の通り、Rubyバージョンの修正は必要だったものの、それだけで正常に動作することを確認できました。
自作のサンプルプロジェクトに適用する
公式ドキュメントとデモプロジェクトの設定を参考にして、自作のサンプルプロジェクトで動作する設定(config.yml)を作成しました。
主な修正点は以下です。
これだけでCIが正常に動作することを確認できました。
- PostgreSQLのイメージを更新
- DB名とDBのユーザ名をプロジェクトに合わせて変更
- Rubyバージョンはプロジェクトに合わせて変更
- RubocopはWarning以上のみ検知するように変更
特に設定しなくてもInsights
からテスト結果の詳細を確認できました。
動作確認済みのソースは以下の通りです。
.circleci/config.yml
version: 2.1 # 2.1 を使うと Orb や他の機能を使用することができます。
# 設定で使用する Orb を宣言します。
# Orb に関する詳細は、https://circleci.com/docs/ja/2.0/orb-intro/をご覧ください。
orbs:
ruby: circleci/ruby@1.8.0
node: circleci/node@2.0.0
jobs:
build: # "build"という名前の最初のジョブです。
docker:
- image: cimg/ruby:2.7.2-node # カスタマイズされた CircleCI Docker イメージを使用します。
steps:
- checkout # Git コードをプルダウンします。
- ruby/install-deps # Ruby Orb を使って依存関係をインストールします。
# Node Orb を使ってパッケージをインストールします。
# Yarn の使用および 依存関係のキャッシュに yarn.lock の使用を指定します。
# 詳細は、 https://circleci.com/docs/2.0/caching/ を参照してください。
- node/install-packages:
pkg-manager: yarn
cache-key: "yarn.lock"
test: # "test"という名前の2つ目のジョブです。
# テストを高速化するために「並列ジョブコンテナ」を実行します。
# これによりテストが複数のコンテナに分割されます。
parallelism: 3
# ここでは、2 つの Docker イメージを設定します。
docker:
- image: cimg/ruby:2.7.2-node # プライマリ Docker イメージです。ここでステップコマンドが実行されます。
- image: cimg/postgres:14.2
environment: # add POSTGRES environment variables.
POSTGRES_USER: rails_cushion
POSTGRES_DB: rails_cushion_test
POSTGRES_PASSWORD: ""
# Ruby/Rails 固有の環境変数をプライマリコンテナに適用します。
environment:
BUNDLE_JOBS: "3"
BUNDLE_RETRY: "3"
PGHOST: 127.0.0.1
PGUSER: rails_cushion
PGPASSWORD: ""
RAILS_ENV: test
# 実行する一連のステップです。「ビルド」のステップと似たステップもあります。
steps:
- checkout
- ruby/install-deps
- node/install-packages:
pkg-manager: yarn
cache-key: "yarn.lock"
# ここでは、データベース上で実行する前に
# セカンダリコンテナが起動することを確認します。
- run:
name: DB の待機
command: dockerize -wait tcp://localhost:5432 -timeout 1m
- run:
name: データベースのセットアップ
command: bundle exec rails db:schema:load --trace
# RSpec を並列実行します。
- ruby/rspec-test
- run:
name: RuboCop
command: bundle exec rubocop --fail-level W --display-only-fail-level-offenses
workflows:
version: 2
build_and_test: # ワークフローの名前は "build_and_test" です。
jobs: # このワークフローの一部として実行するジョブのリストです。
- build # まず、ビルドを実行します。
- test: # 次に、テストを実行します。
requires: # テストを実行するにはビルドを渡す必要があります。
- build
動作確認に使用したRailsのサンプルリポジトリは以下です。(Dockerは使っていません)
設定の解説
以下、今回使用したCircleCIの設定について少し解説しておきます。
Orb
orbs:
ruby: circleci/ruby@1.8.0
node: circleci/node@2.0.0
- Orbとは特定の機能がパッケージ化されたもので、たとえばRubyのOrbにはBundlerやRspecなどの機能が含まれています。
- 各Orbの詳細はここから検索して確認できます。たとえば、RubyのOrbだと
install-deps
というコマンドが含まれていて、ruby/install-deps
とすることで、Bundlerによってgemをインストールできます。 - よく使う共通機能はOrbにまとまっていることが多いので、Orbの活用により設定を簡潔に記載することができます。
- 自身で実装すると複雑で長くなりがちなキャッシュや並列実行の処理が既に実装されているケースが多いので、Orbにある機能は積極的に使った方がいいと思っています。
image
docker:
- image: cimg/ruby:2.7.2-node # プライマリ Docker イメージです。ここでステップコマンドが実行されます。
- image: cimg/postgres:14.2
- 基本的にCIはDockerコンテナ上で実行されるので、そのイメージを指定します。
-
steps
に記載した処理は最初に指定したイメージ上で実行されます。今回のPostgreSQLのイメージのように2番目に指定して使用することが前提となっているイメージも存在します。 - 最近はcimgというプレフィックスがあるものを使用します。(circleciというプレフィックスは2021年末にサポート終了したらしい)
- imageはここから検索できます。
並列実行
# テストを高速化するために「並列ジョブコンテナ」を実行します。
# これによりテストが複数のコンテナに分割されます。
parallelism: 3
- 複数のコンテナを起動し、実行するテストをそれらに分割して割り当てることで高速化を実現する機能です。
- 以前は有料版でしか使えなかったはずですが、今年2022年から無料版がアップデートされて、30ジョブまで並列実行できるようになったようです。
- 機能を使用するには本来タイミングデータ等を使用してうまくテストを分割する必要がありますが、Orbs内のRspecには既にその処理が組み込まれているため、自動で分割されるようになります。
ジョブの実行順序
workflows:
version: 2
build_and_test: # ワークフローの名前は "build_and_test" です。
jobs: # このワークフローの一部として実行するジョブのリストです。
- build # まず、ビルドを実行します。
- test: # 次に、テストを実行します。
requires: # テストを実行するにはビルドを渡す必要があります。
- build
- デフォルトでは複数のジョブは並列実行されるため、実行順序を指定したい場合は
requires
を使用します。 - 今回の設定例では、
test
ジョブの実行を開始する前にbuild
ジョブの成功が必要という意味になります。
参考情報