Quantcast
Channel: メドピア開発者ブログ
Viewing all articles
Browse latest Browse all 216

CircleCIのYAMLを短く書けるRails Orbを作りました

$
0
0

11月に入社したCTO室SREの@sinsokuです。

主にやっていることはRailsアプリのレビューや開発環境の改善です。*1

  • 社内のRailsアプリを横断して浅くレビューする(8つくらい)
  • MedPeerの開発環境の改善
    • docker-compose upで30個のコンテナが起動するのを減らす
  • SwitchPointからActiveRecord v6への移行
  • CircleCIの実行時間の短縮、稀に落ちるテストの修正
  • その他の細かい改善

このうち、CircleCIについて知見が溜まったので技術ブログで紹介します。

CircleCIで気をつける点

CircleCIの実行時間を短くするにはいくつかコツがあります。

  • gemとnpmをできるだけキャッシュする
  • RSpecを並列で実行する前に assets:precompileを実行しておく
  • 各ジョブで必要なgem(もしくはnpm)だけをキャッシュから復元する
    • 例: JavaScriptのテストはnpmのキャッシュだけ復元する

ワークフローを図にするとこんな感じです。

f:id:sinsoku:20200207111113p:plain
CircleCIのジョブのワークフロー

キャッシュの仕組みについて

詳しく知りたい人はCircleCIのページを読んで頂くとして、ここでは一番重要な 部分キャッシュについて説明します。

CircleCIのキャッシュキーには複数のキーを指定することができます。

- restore_cache:keys: # 「OSとCPUの種類」「ブランチ名」「Gemfile.lock の checksum」でキャッシュを探す- gem-cache-v1-{{ arch }}-{{ .Branch }}-{{ checksum "Gemfile.lock" }}
    # 上のキーで見つからない場合、「OSとCPUの種類」「ブランチ名」でキャッシュを探す- gem-cache-v1-{{ arch }}-{{ .Branch }}
    # それでも見つからない場合、 `gem-cache-v1` で始まる最新のキャッシュを探す- gem-cache-v1

キャッシュキーを複数指定すると上から順番にキャッシュを探します。
これによりGemfile.lockが変わっても、 bundle-installで全てのgemをインストールしないで済むようになります。

キャッシュの肥大化

部分キャッシュを使っているとgemが増え続け、キャッシュのリストアに時間がかかる問題が起きます。
bundle install --cleanすれば良いのですが、少しずつ遅くなるため気づき辛い問題です。

参考: bundle install には --clean を指定する (特に Circle CI では) | Born Too Late

ちなみにYarnは自動的に不要なnpmを消してくれます。🐈

Rails Orb

上記の点を気にしながら、社内のRailsアプリで横断的に対応するのは大変なので、誰でも良い感じに設定できるOrbを作りました。

github.com

実際に社内のいくつかのRailsプロジェクトに導入しています。

使い方

Orbの提供するジョブやコマンドの詳細はOrb registryを参考にしてください。

また、Rails Orbを使う前にCircleCIの設定画面で uncertified orbsを許可する必要があります。

f:id:sinsoku:20200212184310p:plain

gemやnpmのキャッシュについて

Gitリポジトリのデフォルトブランチをキャッシュキーに含めることでキャッシュヒット率を上げています。

- restore_cache:keys:- << parameters.key >>-{{ arch }}-{{ .Branch }}-{{ checksum "Gemfile.lock" }}
    - << parameters.key >>-{{ arch }}-{{ .Branch }}
    - << parameters.key >>-{{ arch }}-{{ checksum ".git/refs/remotes/origin/HEAD" }}
    - << parameters.key >>-{{ arch }}

一般的なジョブを提供

CircleCIの設定を簡単にできるように、以下4つのジョブを提供しています。

  • rb-deps: bundle installを実行する
  • js-deps: yarn installを実行する
  • assets: assets:precompileを実行する
  • rspec: RSpecでテストを並列に実行する

新規案件で rails newした直後なら以下の設定で良い感じにCircleCIが動きます。

version:2.1orbs:rails: medpeer/rails@x.y.z

executors:ruby:docker:- image:&docker_ruby circleci/ruby:2.7.0-node-browsers
  ruby_with_db:docker:- image:*docker_ruby- image: circleci/postgres:12.1-alpine-ram
    environment:DATABASE_URL:'postgres://postgres:postgres@127.0.0.1:5432'workflows:rspec:jobs:- rails/rb-deps:executor: ruby
      - rails/js-deps:executor: ruby
      - rails/assets:executor: ruby
          requires:- rails/rb-deps
            - rails/js-deps
      - rails/rspec:executor: ruby_with_db
          db-port:'5432'parallelism:4requires:- rails/assets

ジョブとコマンドを組み合わせる

Orbの提供するrb-depsジョブとbundle-installコマンドを組み合わせると、RuboCopを実行するジョブなども短く書けます。

version:2.1orbs:rails: medpeer/rails@x.y.z

executors:ruby:docker:- image: circleci/ruby:2.7.0-node-browsers

jobs:rubocop:executor: ruby
    steps:- checkout

      # Restore gems from cache- rails/bundle-install:restore_only:true- run: bundle exec rubocop --parallel

workflows:rspec:jobs:- rails/rb-deps:executor: ruby
      - rubocop:requires:- rails/rb-deps

まとめ

Rails Orbを使うと .circleci/config.ymlの記述をかなり減らせるかなと思います。

各社でCircleCIのYAML職人をしている方、ぜひRails Orbを試してみてください。


(☝︎ ՞ਊ ՞)☝︎是非読者になってください


メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら

https://medpeer.co.jp/recruit/entry/

■開発環境はこちら

https://medpeer.co.jp/recruit/workplace/development.html

*1:SRE所属だけど、あまりSREっぽい仕事をしていない


Viewing all articles
Browse latest Browse all 216

Latest Images

Trending Articles