読者です 読者をやめる 読者になる 読者になる

amakanのCIをShippableに移行した

https://amakan.net/ のこの辺の改善の続き。


f:id:r7kamura:20170114143123p:plain

CircleCIからShippableに移行した

amakanをDocker化した感想 - ✘╹◡╹✘ で触れた「CIのビルドに時間が掛かるようになった」という問題に対応するため、利用するCIサービスをCircleCIからShippableに移行した。他の候補としてTravisCI、Werckerなどを見たけれど、ShippableはDockerのキャッシュに上手く対応しているということで、これを選択した。

ビルドに掛かる時間が500秒から60秒になった

CIの中では、こういうことをやっている。

  • Node.js用のDockerイメージをビルドする
  • Node.js用のDockerイメージでテストを実行する
  • Node.js用のDockerイメージでCSSJavaScriptを生成する
  • Rails用のDockerイメージをビルドする (直前で生成したCSSJavaScriptを含めつつ)
  • Rails用のDockerイメージでテストを実行する
  • Rails用のDockerイメージをAmazon ECRにPushする

CircleCIからShippableに移行したことで、過去にビルドしたDockerイメージのキャッシュが再利用できるようになったので、それぞれのDockerイメージをビルドする部分が一瞬で終わるようになった。

Volumeを使おうとすると複雑

上述の処理を実現するために、これまで --volume $(pwd)/public/assets:/app/public/assets というオプションを利用していたが、--volumes-from ${SHIPPABLE_CONTAINER_NAME} というようにデータボリュームを用意する方法に変更する必要があった。--volume オプションを指定してもホスト側とは何も共有されない (エラーも出ない) という挙動を元に原因を調べるのに時間が掛かった。

UIが分かりづらい

他のCIサービスと比べると、UIが見づらくて使いづらい。良い機能を提供していると思うので、余計に勿体無く感じる。

無料ではプライベートリポジトリは1つまで

無料では1つまでしかプライベートリポジトリが利用できないので、高速化したいamakanだけとりあえずShippableで運用してみている。

設定例

amakanのshippable.ymlです。

language: none
build:
  pre_ci_boot:
    options: -v /app/public/assets
  ci:
    - export DOCKER_TAG=${ECR_REPOSITORY_URL}:${BUILD_NUMBER}
    - docker build --file ./docker/node/Dockerfile --tag amakan_node .
    - docker run amakan_node yarn run test
    - docker run --volumes-from ${SHIPPABLE_CONTAINER_NAME} amakan_node yarn run build
    - cp /app/public/assets/* public/assets/
    - docker build --file ./docker/rails/Dockerfile --tag ${DOCKER_TAG} .
    - docker run ${DOCKER_TAG} bundle exec rake test
  post_ci:
    - >
      if [[ "${BRANCH}" == "master" ]]; then
        sudo docker push ${DOCKER_TAG}
      fi
integrations:
  hub:
    - integrationName: ecr
      type: ecr
      region: ap-northeast-1
      branches:
        only:
          - master
  notifications:
    - integrationName: email
      type: email
      on_success: never
      on_failure: never
      on_pull_request: never
    - integrationName: slack
      type: slack
      on_failure: always
      on_success: always
      recipients:
        - "#shippable"