CircleCIでのテスト実行時間を短縮する：コンパイル結果のキャッシュ

[CircleCIでのテスト実行時間を短縮する：テストの並列化](https://qiita.com/tmf16/items/2b927e427066f6e1303e) を行いましたが
まだ速くなるはず。

実行結果を眺めると`npm run dev`でかなりの時間がかかっている。
pug, css, vueあたりの`assets`配下が更新されていなければキャッシュできるのではと思い対応してみる。

## キャッシュに対応したCircleCI設定

```yaml:.circleci/config.yml
version: 2
references:
  php-c-image: &php-c-image
    image: sencorp/docker-php-c:v2.0.0
  postgres-image: &postgres-image
    image: circleci/postgres:10.1
    environment:
      POSTGRES_DB: hoge
      POSTGRES_USER: fuga
      POSTGRES_PASSWORD: fuga
jobs:
  build:
    docker:
      - *php-c-image
    working_directory: ~/repo
    steps:
      - checkout
      - restore_cache:
          keys:
              - composer-v2-{{ checksum "laravel/composer.lock" }}
      - run:
          name: composer install
          working_directory: ~/repo/laravel
          command: composer install -n --prefer-dist
      - save_cache:
          key: composer-v2-{{ checksum "laravel/composer.lock" }}
          paths:
            - laravel/vendor
      - restore_cache:
          keys:
              - npm-v2-{{ checksum "laravel/package-lock.json" }}
      - run:
          name: if there is no node_modules, npm ci
          working_directory: ~/repo/laravel
          command: |
            if [ ! -d node_modules ]; then
              npm ci
            fi
      - save_cache:
          key: npm-v2-{{ checksum "laravel/package-lock.json" }}
          paths:
            - laravel/node_modules
  test:
    docker:
      - *php-c-image
      - *postgres-image
    environment:
      APP_ENV: testing
      DB_HOST: localhost
      DB_PORT: 5432
      PAGER: cat # prevent psql commands using less
    working_directory: ~/repo
    steps:
      - checkout
      - restore_cache:
          keys:
              - composer-v2-{{ checksum "laravel/composer.lock" }}
      - restore_cache:
          keys:
              - npm-v2-{{ checksum "laravel/package-lock.json" }}
      - run:
          name: output assets last commit
          command: git log -1 laravel/resources/assets/ > assets_last_commit
      - restore_cache:
          keys:
              - npm_run-v2-{{ checksum "laravel/package-lock.json" }}-{{ checksum "assets_last_commit" }}
      - run:
          name: if there is no public/mix-manifest.json, npm run dev
          working_directory: ~/repo/laravel
          command: |
            if [ ! -f public/mix-manifest.json ]; then
              npm run dev
            fi
      - save_cache:
          key: npm_run-v2-{{ checksum "laravel/package-lock.json" }}-{{ checksum "assets_last_commit" }}
          paths:
            - laravel/resources/views
            - laravel/public/assets
            - laravel/public/mix-manifest.json
      - run:
          name: npm run dev
          working_directory: ~/repo/laravel
          command: npm run dev
      - run:
          name: dump-autoload
          working_directory: ~/repo/laravel
          command: composer dump-autoload
      - run:
          name: db migrate
          working_directory: ~/repo/laravel
          command: php artisan migrate
      - run:
          name: seed data
          working_directory: ~/repo/laravel
          command: php artisan db:seed
      - run:
          name: run test
          working_directory: ~/repo/laravel
          command: ./vendor/bin/paratest --processes 10
workflows:
  version: 2
  build-syntax-test:
    jobs:
      - build:
      - test:
          requires:
              - build
```

## どうキャッシュするか

`npm run dev`が必要な判定をどう簡単に実現するのかを少し悩みました。
辿り着いたのは `resources/assets/` 配下にコンパイルが必要なファイルが入っているので、そこのgit logを利用することに。

あとは`public/mix-manifest.json`ファイルが存在しているかどうかでキャッシュが復元されているかを判断しています。

## 結果

キャッシュがヒットしないときにはコンパイルの時間がそのまま必要ですが、
ヒットした際にはrestoreされるだけですので1秒以下に！

これでかなり改善されました。