drone.io 1.0でキャッシュとparallel pipelineを利用して高速にビルドする
drone.io 1.0を使ってみるで取り扱わなかった話題として、依存関係のキャッシュとpipelineの並列実行があります。
キャッシュ機能はdrone.io 0.8でもできました(Drillster/drone-volume-cache)。1.0でも公式pluginで実現できるので、紹介します。
並列実行に関しては、0.8ではParallel Executionとしてgroup
を使って記述しましたが、1.0ではdepends_on
を記述することで実現します。
キャッシュの記述例
drone-plugins/drone-volume-cache を使うと、次のように vendor/bundle
およびvendor/bin
をキャッシュできます。
ホスト側の/tmp/cache/drone-rails-example
以下にキャッシュがtarで格納されます。ホスト側にvolumeをマウントしてるので、trusted repositoryフラグをONにする必要があります(Web UIから変更できます)。
---
kind: pipeline
name: default
steps:
- name: restore-cache
image: plugins/volume-cache
settings:
mount:
- ./vendor/bundle
- ./vendor/bin
restore: true
volumes:
- name: cache
path: /cache
- name: bundle-install
image: ruby:2.6.1
commands:
- bundle install --path=vendor/bundle --binstubs=vendor/bin --clean
- bundle exec rubocop -R -fs app spec
- bundle exec rspec
environment:
RAILS_ENV: test
- name: rebuild-cache
image: plugins/volume-cache
settings:
mount:
- ./vendor/bundle
- ./vendor/bin
rebuild: true
volumes:
- name: cache
path: /cache
- name: notify-slack
image: plugins/slack
settings:
webhook:
from_secret: webhook
services:
- name: db
image: mysql:5.7
environment:
MYSQL_DATABASE: drone_example_test
MYSQL_PASSWORD: drone_example
MYSQL_RANDOM_ROOT_PASSWORD: true
MYSQL_USER: drone_example_test
TZ: Asia/Tokyo
volumes:
- name: cache
host:
path: /tmp/cache/drone-rails-example
parallel pipeline steps
drone.ioのpipelineは基本的に記述順に逐次的に実行されますが、depends_on
を記述すると、依存するstepが終わったら記述の前後関係なく実行されることになります。
FAQに0.8との比較を含めてわかりやすい記述が掲載されていますHow to setup parallel Pipeline steps (1.0+)。
実際に、互いに独立して実行できるRubocopとRSpecの記述例を以下に示します(キャッシュの設定もします) github。
---
kind: pipeline
name: default
steps:
- name: restore-cache
image: plugins/volume-cache
settings:
mount:
- ./vendor/bundle
- ./vendor/bin
restore: true
volumes:
- name: cache
path: /cache
- name: bundle-install
image: ruby:2.6.1
commands:
- bundle install --path=vendor/bundle --binstubs=vendor/bin --clean
environment:
RAILS_ENV: test
depends_on:
- restore-cache
- name: rubocop
image: ruby:2.6.1
commands:
- bundle check --path=vendor/bundle
- bundle exec rubocop -R -fs app spec
environment:
RAILS_ENV: test
depends_on:
- bundle-install
- name: rspec
image: ruby:2.6.1
commands:
- bundle check --path=vendor/bundle
- bundle exec rspec
environment:
DATABASE_HOST: db
DATABASE_PORT: 3306
RAILS_ENV: test
depends_on:
- bundle-install
- name: rebuild-cache
image: plugins/volume-cache
settings:
mount:
- ./vendor/bundle
- ./vendor/bin
rebuild: true
volumes:
- name: cache
path: /cache
depends_on:
- bundle-install
- name: notify-slack
image: plugins/slack
settings:
webhook:
from_secret: webhook
depends_on:
- rubocop
- rspec
services:
- name: db
image: mysql:5.7
environment:
MYSQL_DATABASE: drone_example_test
MYSQL_PASSWORD: drone_example
MYSQL_RANDOM_ROOT_PASSWORD: true
MYSQL_USER: drone_example_test
TZ: Asia/Tokyo
volumes:
- name: cache
host:
path: /tmp/cache/drone-rails-example
...
bundle-instal stepの後に、rubocop, rspecコマンドをそれぞれ並列で実行しています。
depends_on
の記述がその他のstepにも記述されていますが、これは必要な記述です。
bundle-install stepのdepends_onにrestore-cacheを記述しないと、次のような意図しない順序でstepが実行されます。
この辺りは0.8のgroup
による記述の方が簡便だと思っています。
期待する順序
- [restore-cache] - [bundle-install] - [rubocop]
\- [rspec]
実行される順序
- [restore-cache]
\- [bundle-install] - [rubocop]
\- [rspec]