drone.io 1.0でキャッシュとparallel pipelineを利用して高速にビルドする

# drone.io 1.0でキャッシュとparallel pipelineを利用して高速にビルドする

[drone.io 1.0を使ってみる](https://qiita.com/mmhiyoko/items/7669e44652052468fb3b)で取り扱わなかった話題として、依存関係のキャッシュとpipelineの並列実行があります。
キャッシュ機能はdrone.io 0.8でもできました([Drillster/drone-volume-cache](https://github.com/Drillster/drone-volume-cache))。1.0でも公式pluginで実現できるので、紹介します。

並列実行に関しては、0.8では[Parallel Execution](https://0-8-0.docs.drone.io/pipelines/)として`group`を使って記述しましたが、1.0では`depends_on`を記述することで実現します。

## キャッシュの記述例
[drone-plugins/drone-volume-cache](https://github.com/drone-plugins/drone-volume-cache) を使うと、次のように `vendor/bundle`および`vendor/bin`をキャッシュできます。
ホスト側の`/tmp/cache/drone-rails-example`以下にキャッシュがtarで格納されます。ホスト側にvolumeをマウントしてるので、trusted repositoryフラグをONにする必要があります（Web UIから変更できます）。

```yml
---
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+)](https://discourse.drone.io/t/how-to-setup-parallel-pipeline-steps-1-0/3251)。

実際に、互いに独立して実行できるRubocopとRSpecの記述例を以下に示します(キャッシュの設定もします) [github](https://github.com/mmhiyoko/drone-rails-example/blob/feature/cache/.drone.yml)。

```yml
---
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`による記述の方が簡便だと思っています。

```txt
期待する順序
- [restore-cache] - [bundle-install] - [rubocop]
                                     \- [rspec]

実行される順序
- [restore-cache]
\- [bundle-install] - [rubocop]
                    \- [rspec]
```

Web UIでは並列実行の様子が表現されないのでちょっと寂しいです。
<img width="990" alt="drone-parallel.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146404/8ca10634-0764-675e-eb8c-abf07e6bb66d.png">