Circle CI 2.0でフロントエンドをビルドする
2017-11-28

Circle CI 2.0でフロントエンドをビルドする

create-react-appで作っているReactアプリをCircle CI 2.0でビルドする手順について紹介します。

今回説明するのは、CircleCI 2.0を使う上での大まかな流れについてです。

前提条件

フロントエンドのプロジェクトにはtestbuildのタスクがあって、全てnpm runで実行できるとします。
またデプロイについては、buildタスクで1つのバンドルファイルを作成してS3にデプロイします。

定義ファイルを作成する

まずは定義ファイルを作成する必要があります。設定ファイルは.circleciフォルダの中にconfig.ymlを作成して定義していきます。

root
  .circleci
    config.yml

定義ファイルのシンタックスについてはv1.0と比べると結構変わっているので注意が必要です。
Slackの作業ログを見ると、Dashboardのどこかで定義ファイルが生成できたようですが、どこだか忘れてしまいました。

定義ファイルを生成すると次のようなファイルが作成されます。

デフォルトではCircleCIが準備したDocker imageを使います。(image: circleci/node:8.9の部分)
node, npm, yarnは既にimageに含まれているので、最小構成であればこれで大丈夫だと思います。

# Javascript Node CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-javascript/ for more details
#
version: 2
jobs:
  build:
    docker:
      # specify the version you desire here
      - image: circleci/node:8.9

      # Specify service dependencies here if necessary
      # CircleCI maintains a library of pre-built images
      # documented at https://circleci.com/docs/2.0/circleci-images/
      # - image: circleci/mongo:3.4.4

    working_directory: ~/workspace

    steps:
      - checkout

      # Download and cache dependencies
      - restore_cache:
          keys:
          - v1-dependencies-{{ checksum "package.json" }}
          # fallback to using the latest cache if no exact match is found
          - v1-dependencies-

      - run: yarn install

      - save_cache:
          paths:
            - node_modules
          key: v1-dependencies-{{ checksum "package.json" }}

      # run tests!
      - run: yarn test

定義ファイルの書き方については公式サンプルプロジェクトを見てください。

Docker imageを作成する

(この工程は必要な場合のみです。)

デフォルトではCircleCIが準備したDocker imageを使うのですが、これをさらにカスタムしてツールなどを導入したい場合は、新しくDocker imageを準備する必要があります。

自分の場合、S3にデプロイする場合はAWS-CLIツールを利用するので、これをインストールしたimageを作成する必要がありました。
imageを作成する際は、circleci/node:8.9を継承することができますので、ぜひそうしましょう。

FROM circleci/node:8.9

# ここから下にいろいろ定義する
...

実際に作成したimageはこちらです。

docker imageの作成方法についてはこちらを参照してください。

Jobを定義する

次にJobを定義します。この後の手順としては、Jobを定義してこれをワークフローの中で順番に呼び出していきます。

Jobとは、CircleCIの中で再利用できると便利だなと思う一連のタスクをまとめたものです。例えば、test とかtest and buildなどがそれにあたります。
とにかく次のワークフローの中ではこのジョブ名を利用してフローを作成するので、このことを意識して定義するといいと思います。

基本的にはjobs:の直下にタスク名(上の例ではbuild:)を定義して、steps:の中にやりたいことを順番に書いていきます。
この辺りは1.0をやったことがある人であれば、想像できると思います。

version: 2
jobs:
  build:
    steps:
      - run step1
      - run step2
      - run step3
      ...

細かな設定は公式ドキュメントを参考にしてください。

ワークフローを定義する

最後に定義したJobをワークフローとして組み立てていきます。

基本的にはworkflows:の直下にワークフロー名を定義して、jobs:の中にやりたいことを順番に書いていきます。

workflows:
  version: 2
  test_build_and_deploy:
    jobs:
      - test
      - build
      - deploy

ちなみにtestなどの、次のJobに進む前に完了していなければならないJobがある場合、requiresを使うことで表現することができます。

workflows:
  version: 2
  test_build_and_deploy:
    jobs:
      - test
      - build
          requires:
            - test
      - deploy
          requires:
            - build

この場合、test -> build -> deployの順にワークフローが実行されます。
ワークフローを定義する場合、同じ階層にあるJobは並列に実行されるため、requiresでフローの制御は必須だと思います。

また、特定のブランチのみ実行させたい場合は、filtersbranchesを組み合わせることで表現可能です。

workflows:
  version: 2
  test_build_and_deploy:
    jobs:
      - test
      - build
          filters:
            branches:
              only:
                - develop

この場合はdevelopプランチの場合のみbuildのJobが実行されるようになります。

定義したワークフローはCircleCI上の「WORKFLOWS」にて確認することができます。

おまけ

Circle CIのデフォルトのマシンリソースはmedium(CPU 2.0 RAM 4GB)となっていて、最近のフロントエンドのテスト、デプロイにおいてはスペック不足感が否めません。

CPUはコア数かな?

自分の場合は、テストでjs-domを使っているのですが、頻繁に次のようなエラーが発生していました。

ENOMEM: not enough memory, read

そんな時は、resource_classでマシンスペックをあげることができます。
しかし、今のところCircle CIのカスタマーサポートに依頼する必要があります。詳しくはこちらを見てください。

有効にしたいOrganization名と一緒に依頼すると割と早めに対応してくれました。Circle CIのカスタマーサポート素晴らしい!!

とはいえ、将来的にはresource_classはプレミアム機能になるかもしれないです。要注意!

まとめ

CircleCI 2.0でフロントエンドをビルドするための大まかな手順でした。
本題とは全く関係ないのですが、Circle CIのカスタマーサポート迅速でよかったなー。

CircleCI 2.0の公式ドキュメントについてはこちらを参照してください。