なぜ local で CircleCI を動かしたいと思ったのか
リモートの CircleCI 上でよく落ちるテストがあるが、ローカルでbundle exec rspecではほぼ再現しないことがあった。
『push デバックは辛いな』『Docker の設定で、低スペック状態にして確認することもできるし』という思いから、local で CircleCI でテストできる環境を整えようということからやってみた
結論、まだローカルではうまく行ってない!
テストの実行自体は問題ないのだがスクリーンショットが.... 😭
各種インストール
Docker
Dockerのサイトにアクセスし、Docker Desktopをダウンロードします。
今回は開発環境がMacだったので、Download for mac でダウンロードを行います。Docker.dmg ファイルがダウンロードされる。
ダウンロード完了後、Docker.dmg を開き、Docker を Applicationsフォルダに drag and drop を行う。

CircleCI
local で CircleCI を動かすために、CircleCI CLI のインストールを行う。
今回は Homebrew を利用してインストールを行います。
$ brew install circleci # Docker インストール済みの場合はこちら $ brew install --ignore-dependencies circleci
CircleCI用の設定ファイル
CircleCI CLI では、config のバージョンが2.1だとこのJob実行が行えないとのことでした。
このプロダクトでは既に CircleCI を利用しており、config を確認したところバージョンが2.1であったため、バージョンが2の設定ファイルを用意する必要があります。
.circleci/config.yml
version: 2.1
executors:
default:
docker:
- &base_docker
image: circleci/xxxxxxxxxx
environment:
LANG: ja_JP.UTF-8
LANGUAGE: "ja_JP:ja"
RAILS_ENV: "test"
REVIEWDOG_VERSION: "0.10.2"
RUBYOPT: "-EUTF-8"
TZ: Asia/Tokyo
commands:
bundle_install_and_cache:
steps:
# Download and cache dependencies
- restore_cache:
keys:
- v3-dependencies-{{ checksum "Gemfile.lock" }}
# fallback to using the latest cache if no exact match is found
- v3-dependencies-
- bundle_install
- save_cache:
paths:
- ./vendor/bundle
key: v3-dependencies-{{ checksum "Gemfile.lock" }}
bundle_install:
steps:
- run:
name: install dependencies
command: |
bundle install --clean --jobs=4 --retry=3 --path vendor/bundle
install_nodejs:
steps:
# https://circleci.com/docs/2.0/circleci-images/#best-practices
- run:
name: "Update Node.js and npm"
command: |
curl -sSL "https://nodejs.org/dist/v12.19.0/node-v12.19.0-linux-x64.tar.xz" \
| sudo tar --strip-components=2 -xJ -C /usr/local/bin/ node-v12.19.0-linux-x64/bin/node
curl https://www.npmjs.com/install.sh | sudo bash
node_version:
steps:
- run:
name: node version
command: node --version
yarn_version:
steps:
- run:
name: yarn version
command: yarn --version
yarn_install:
steps:
- restore_cache:
keys:
- v1-yarn-packages-{{ checksum "yarn.lock" }}
- v1-yarn-packages-
- run:
name: yarn install
command: yarn install --frozen-lockfile --ignore-optional --cache-folder ~/.cache/yarn
- save_cache:
paths:
- ~/.cache/yarn
key: v1-yarn-packages-{{ checksum "yarn.lock" }}
jobs:
build:
executor: default
working_directory: ~/repo
steps:
- checkout
- bundle_install_and_cache
- install_nodejs
- node_version
- yarn_version
- yarn_install
- persist_to_workspace:
root: ~/repo
paths:
- ./vendor/bundle
- ./node_modules
- ./public/assets
- ./tmp/cache/assets
circleci config process .circleci / config.yml > .circleci / process.yml
上記のコマンドで、バージョン2.1の設定ファイルの内容をバージョン2に整形し、process.yml(ファイル名は任意)というファイルに出力させる。
注意 : save_cache/restore_cache/store_artifacts の記述があるが、CircleCi CLI では利用できない。そのため、ローカルで実行時には警告が表示されます。また、workflow にも対応していません。
.circleci/process.yml
`save_cache` と `restore_cache`の記述に関しては削除済み
version: 2
jobs:
build:
docker:
- image: circleci/xxxxxxxxxx
environment:
LANG: ja_JP.UTF-8
RAILS_ENV: test
REVIEWDOG_VERSION: 0.10.2
RUBYOPT: -EUTF-8
TZ: Asia/Tokyo
working_directory: ~/repo
steps:
- checkout
- run:
name: install dependencies
command: |
bundle install --clean --jobs=4 --retry=3 --path vendor/bundle
- run:
name: Update Node.js and npm
command: |
curl -sSL "https://nodejs.org/dist/v12.19.0/node-v12.19.0-linux-x64.tar.xz" \
| sudo tar --strip-components=2 -xJ -C /usr/local/bin/ node-v12.19.0-linux-x64/bin/node
curl https://www.npmjs.com/install.sh | sudo bash
- run:
name: node version
command: node --version
- run:
name: yarn version
command: yarn --version
- run:
name: yarn install
command: yarn install --frozen-lockfile --ignore-optional --cache-folder ~/.cache/yarn
- persist_to_workspace:
root: ~/repo
paths:
- ./vendor/bundle
- ./node_modules
- ./public/assets
- ./tmp/cache/assets
circleci local execute -c .circleci/process.yml # config にバージョン2で設定しているとき circleci local execute
上記のコマンドで CircleCI の build をローカルで実行することができます。
build 以外のジョブを実行する際には、--job JOB_NAME のオプションをつけることで実行することができます。
features テストが失敗した時スクリーンショットを撮りたい!
gem 'capybara-screenshot' を入れて、失敗した時に勝手にスクリーンショットをとってくれる様にする。
group :test do gem 'capybara-screenshot' end
テストを実行する時のみgem 'capybara-screenshot'が必要なので、テスト実行時のみパッケージがインストールされるようにする。
capybara-screenshotの設定を追加する。
Capybara::Screenshot.register_filename_prefix_formatter(:rspec) do |example|
"screenshot_#{example.description.tr(' ', '-').gsub(%r{^.*/spec/}, '')}"
end
GitHub と CircleCI を連携している場合は、font をインストールしていないとお豆腐(□)が大量発生します。
commands に font のインストールについて追加し、そのコマンドをテストを実行しているジョブに追記します。
commands に追記せずそのまま steps に記載でも👍 知らんけど
commands:
install_font:
steps:
- run:
name: apt-get update
command: sudo apt-get update
- run:
name: Install fonts
command: |
sudo apt-get install -y fonts-ipaexfont fonts-noto-cjk &&
sudo fc-cache -fv
job:
test:
steps:
- install_font
ここではfonts-ipaexfont fonts-noto-cjkを入れていますが、お好みのフォントをどうぞ。
これでリモートでは綺麗なスクリーンショットが撮られる様になります。
最後にstore_artifactsをテスト実行後に追加するのを忘れずに
- store_artifacts:
path: tmp/capybara/

CircleCI の ARTIFACTS から失敗した際の画面のスクリーンショットを確認することができる様になります。
スクリーンショット(png)と HTML の両方で失敗原因について確認することができる様になります。
最後に
Dockerの設定でボリュームをマウントしてるが、ローカルにはなかった。
確認したところテストの実行が終了した段階でプロジェクトのファイルがなくなる様になっているみたいです。
そもそもスクリーンショットは/home/circleci/repo/tmp/capybara/配下に格納される様になってました。
格納場所をそもそも勘違いしてました。馬鹿ですねぇw
no_output_timeout:で止めている間にコンテナに入って、スクリーンショットが取れていることは確認できた。ただどんなスクリーンショットが撮られているかまでは確認してないけどね!!
docker cp コンテナ:tmp/capybara ローカルパスでローカルにcapybara配下に格納されているスクリーンショットをローカルに
ってところで、この記事の期日が来てしまった...
ローカルでもうまくできたらまた会おう