今更ながらcircleciのVer 2.1の新機能であるexecutor
とcommands
を使ってcircleciのconfigファイルをスッキリさせてWorkflowもいい感じに見直したので、そのへんをメモしておきます📝
circleci ver2.1新機能executor
とcommands
とは?
executor
とcommands
とはcircleciの2.1から追加された新機能です✨
今回は、それぞれの簡単な説明と実際に自分の個人開発で使っているcircleciのconfigを改善してみたので、そのへんを次から書いていきます👍
executor
executorは公式のドキュメントにも記載のある通りjobの実行環境を指定することが出来ます。今まではdocker
で記載して、それぞれでimageを記載しているような感じになってしまっていましたが、executorを使うとスッキリと実行環境をjobごとに指定出来ますね🙌
Executors define the environment in which the steps of a job will be run, allowing you to reuse a single executor definition across multiple jobs. https://circleci.com/docs/reference-2-1/#executors
使い方はこんな感じでしょうか⚙
version: 2.1 executors: alice: docker: - image: ruby:2.7.0-alpine bob: docker: - image: node:14.5.0-alpine jobs: alice: executor: name: alice steps: - run: command: "echo hello!" bob: executor: name: bob steps: - run: command: "echo goodbye!"
実行環境が見やすく定義出来ますね✨
commands
commandsは公式のドキュメントにも記載のある通り、commandsを使うとstepで実行可能なコマンドを定義して再利用することが出来ます🙌
並列性を高めるためにjobを分けたりするときにyamlの定義参照等を使わなくてもスッキリとかけるようになったのかなと思います✨
A command definition defines a sequence of steps as a map to be executed in a job, enabling you to reuse a single command definition across multiple jobs. https://circleci.com/docs/reference-2-1/#commands
使い方はこんな感じでしょうか⚙
version: 2.1 executors: alice: docker: - image: ruby:2.7.0-alpine bob: docker: - image: node:14.5.0-alpine commands: say_hello: steps: - run: name: say hello!! command: echo hello! jobs: alice: executor: name: alice steps: - say_hello bob: executor: name: bob steps: - say_hello
いい感じにコマンドが再利用出来ますね✨
見直した結果のBefore/After
今回個人で開発しているRailsアプリケーションで使っていたcircleciのconfigファイルを先程説明した機能で、ちょっと改善してみました⚙
環境は下記のような感じです。
image | memo |
---|---|
ruby | 2.7.0 with node.js (rails 6.0.3) |
db | postgresql |
Before
改善前はjsまわりとrubyまわりでworkflowを分けていましたが、それだけだったので、どこで落ちたのかわかりにくい + 並列数が上げても並列に動かしにくかったなと💦
あとはjobのstep数が多く + 具体的なコマンドが書かれてしまっていたので可読性が良くなったなと😅
workflow
config
version: 2 default: &default # specify the version you desire here - image: circleci/ruby:2.7.0-node-browsers environment: RAILS_ENV: test PGHOST: 127.0.0.1 DATABASE_USER: circleci DATABASE_PASSWORD: password jobs: build: docker: - <<: *default - image: circleci/postgres environment: POSTGRES_USER: circleci POSTGRES_PASSWORD: password steps: - checkout - persist_to_workspace: root: . paths: - . node_build: docker: - <<: *default steps: - attach_workspace: at: . - restore_cache: keys: - v1-node-dependencies-{{ checksum "yarn.lock" }} - v1-dependencies- - run: name: install dependencies command: yarn install - save_cache: paths: - ./node_modules key: v1-node-dependencies-{{ checksum "yarn.lock" }} - run: name: run code analyze command: yarn lint ruby_build: docker: - <<: *default - image: circleci/postgres environment: POSTGRES_USER: circleci POSTGRES_PASSWORD: password steps: - attach_workspace: at: . - run: name: Configure Bundler command: | echo 'export BUNDLER_VERSION=$(cat Gemfile.lock | tail -1 | tr -d " ")' >> $BASH_ENV source $BASH_ENV gem install bundler -v $BUNDLER_VERSION - restore_cache: keys: - v1-dependencies-{{ checksum "Gemfile.lock" }} - v1-dependencies- - run: name: install dependencies command: bundle install --jobs=4 --retry=3 --path ./vendor/bundle - save_cache: paths: - ./vendor/bundle key: v1-dependencies-{{ checksum "Gemfile.lock" }} - run: name: run rubocop command: bundle exec rubocop - run: name: run brakeman command: bundle exec brakeman - run: name: run migration command: | bundle exec rake db:create bundle exec rake db:schema:load - run: name: run tests command: | TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)" bundle exec rspec $TEST_FILES workflows: version: 2 build: jobs: - build - ruby_build: requires: - build - node_build: requires: - build
After
改善後はjs側はライブラリのinstallと静的解析で分けて、ruby側はライブラリのインストールと静的解析とテストで分けてみました🤖
これでjs側とruby側、またruby側も静的解析とテストで並列にCIを回すことができるようになりそうです🙌
あとはexecutorで実行環境をまとめたので、どの環境で動くのかが明確になったのと、commandsを使って実行コマンドを整理したのでstepの中がスッキリして見やすくなったかなと思います✨
workflow
config
version: 2.1 web: &web - image: circleci/ruby:2.7.0-node-browsers environment: RAILS_ENV: test PGHOST: 127.0.0.1 DATABASE_USER: circleci DATABASE_PASSWORD: password db: &db - image: circleci/postgres environment: POSTGRES_USER: circleci POSTGRES_PASSWORD: password executors: web: docker: - <<: *web web-db: docker: - <<: *web - <<: *db commands: attach_current: steps: - attach_workspace: at: . install_node_deps: steps: - run: name: install node dependencies command: yarn install cache_node_deps: steps: - save_cache: name: Cache node dependencies paths: - ./node_modules key: v1-node-dependencies-{{ checksum "yarn.lock" }} restore_node_deps: steps: - restore_cache: name: Restore node dependencies keys: - v1-node-dependencies-{{ checksum "yarn.lock" }} - v1-dependencies- configure_bundler: steps: - run: name: Configure Bundler command: | echo 'export BUNDLER_VERSION=$(cat Gemfile.lock | tail -1 | tr -d " ")' >> $BASH_ENV source $BASH_ENV gem install bundler -v $BUNDLER_VERSION install_ruby_deps: steps: - run: name: install dependencies command: bundle install --jobs=4 --clean --path ./vendor/bundle cache_ruby_deps: steps: - save_cache: name: Cache ruby dependencies paths: - ./vendor/bundle key: v1-dependencies-{{ checksum "Gemfile.lock" }} restore_ruby_deps: steps: - restore_cache: name: Restore ruby dependencies keys: - v1-dependencies-{{ checksum "Gemfile.lock" }} - v1-dependencies- jobs: build: executor: name: web steps: - checkout - persist_to_workspace: root: . paths: - . node_build: executor: name: web steps: - attach_current - restore_node_deps - install_node_deps - cache_node_deps node_lint: executor: name: web steps: - attach_current - restore_node_deps - install_node_deps - run: name: run code analyze command: yarn lint ruby_build: executor: name: web steps: - attach_current - configure_bundler - restore_ruby_deps - install_ruby_deps - cache_ruby_deps ruby_lint: executor: name: web steps: - attach_current - restore_ruby_deps - configure_bundler - install_ruby_deps - run: name: run rubocop command: bundle exec rubocop - run: name: run brakeman command: bundle exec brakeman ruby_test: executor: name: web-db steps: - attach_current - restore_ruby_deps - configure_bundler - install_ruby_deps - run: name: run migration command: | bundle exec rake db:create bundle exec rake db:schema:load - run: name: run tests command: bundle exec rspec spec/ workflows: version: 2 build: jobs: - build - ruby_build: requires: - build - ruby_lint: requires: - ruby_build - ruby_test: requires: - ruby_build - node_build: requires: - build - node_lint: requires: - node_build