CircleCI2.0でテストからEBデプロイまでしてみた

# この記事について
最近CircleCI Enterpriseが1.0から2.0になった関係で、[SmartHRさんの記事](http://tech.smarthr.jp/tech/705)を参考に設定ファイルを書き換えました。

2.0に関しては、まだ情報が多いとは言えないためとりあえずこれで動く！というものを共有できたらと思います。

# CircleCIの使い方
私たちのチームではAPIとフロントの2つをCircleCIでテスト及びEBへデプロイしています。
今回はハマる点の多かったAPIの設定ファイルを使用します。
API側の環境はLaravel5.5、EBはMulticontainer Dockerを使用しております。

# 実際の設定ファイル
きっとどうやるか知りたいだけの方もいらっしゃると思うので先に2.0の設定ファイルを表示します。

```yaml:config.yml
# アンカーをまとめている場所
references:
  commands:
    install_docker: &install_docker
      name: install docker 17.03.1-ce
      command: |
        export VER=17.03.1-ce
        curl -L -o /tmp/docker-$VER.tgz https://get.docker.com/builds/Linux/x86_64/docker-$VER.tgz
        tar -xz -C /tmp -f /tmp/docker-$VER.tgz
        sudo mv /tmp/docker/* /usr/bin
    install_pip: &install_pip
      name: install pip and modules
      command: |
        wget https://bootstrap.pypa.io/get-pip.py
        sudo python get-pip.py
        sudo pip install awscli
        sudo pip install awsebcli
        sudo pip install https://pypi.python.org/packages/2.7/b/blessed/blessed-1.9.5-py2.py3-none-any.whl
    install_php: &install_php
      name: install php extensions
      command: |
        sudo apt-get update && sudo apt-get -y install zlib1g-dev unzip
        yes '' | sudo pecl install -o -f redis && echo "extension=redis.so" > /usr/local/etc/php/conf.d/redis.ini
        sudo docker-php-ext-install pdo_mysql zip
        sudo docker-php-ext-enable redis

# CircleCIの設定
version: 2
jobs:
  test:
    environment:
      - DB_HOST: '127.0.0.1'
      - DB_DATABASE: 'test-db'
      - DB_USERNAME: 'root'
      - DB_PASSWORD: ''
      - REDIS_HOST: '127.0.0.1'
      - AWS_CUSTOM_ENDPOINT_S3: http://127.0.0.1:1234
    docker:
      - image: circleci/php:7.1
      - image: circleci/mysql:5.7
        environment:
          MYSQL_DATABASE: 'test-db'
      - image: circleci/fakes3:0.2.4
      - image: redis
    steps:
      - checkout
      - restore_cache:
          key: {{ .Branch }}
      - run: *install_php
      - run:
          name: run composer install
          command: |
            composer config -g repos.packagist composer https://packagist.jp
            composer global require hirak/prestissimo --no-interaction
            composer install --no-interaction
      - run:
          name: test
          command: |
            vendor/bin/phpunit
      - save_cache:
          key: {{ .Branch }}
          paths:
            - vendor
  deploy_dev:
    docker:
      - image: circleci/php:7.1
    steps:
      - checkout
      - setup_remote_docker
      - run: *install_docker
      - run: *install_pip
      - run: *install_php
      - restore_cache:
          key: {{ .Branch }}
      - deploy:
          name: deploy in development
          command: |
            eb use development
            eb deploy
      - save_cache:
          key: {{ .Branch }}
          paths:
            - vendor
  deploy_stg:
    docker:
      - image: circleci/php:7.1
    steps:
      - checkout
      - setup_remote_docker
      - run: *install_docker
      - run: *install_pip
      - run: *install_php
      - restore_cache:
          key: {{ .Branch }}
      - deploy:
          name: deploy in staging
          command: |
            eb use staging
            eb deploy
      - save_cache:
          key: {{ .Branch }}
          paths:
            - vendor
workflows:
  version: 2
  test_and_deploy:
    jobs:
      - test:
          filters:
            tags:
              only: /^v[0-9]+(\.[0-9]+){2}$/
      - deploy_dev:
          requires:
            - test
          filters:
            branches:
              only: master
      - deploy_stg:
          requires:
            - test
          filters:
            branches:
              ignore: /.*/
            tags:
              only: /^v[0-9]+(\.[0-9]+){2}$/

```

※公開用のため一部内容を修正しています

# 解説
それでは細かい解説をしていきます
referencesは以下を参考にリファクタリングした部分になります
[CircleCI 2.0でworkflow間のrunコマンドを共通化する](https://qiita.com/inuscript/items/3568690b5da29ab034dc)

## `version`
廃止予定や変更予告などの表示をするために使用されます

## `jobs`
一つ以上の`job`を定義した部分になります

## `job_name`
今回では`test`,`deploy_dev`,`deploy_stg`のことです
`job_name`は一つの設定ファイル内でユニークである必要があります

### `environment`
環境変数を定義します

### `docker`
jobで使用するdockerの設定を行います
dockerの他に`machine`と`macos`があり、これらをまとめて`executor`と呼びます

#### `image`
使用するdockerのイメージを定義します
CircleCIが用意しているイメージは以下を参照してください
https://circleci.com/docs/2.0/circleci-images/
もちろんこの他のDocker Hubに上がっているイメージも使用できます

#### `environment`
`executor`内で使用する環境変数を定義します
また、上の階層で定義されている環境変数よりも優先されます

### `steps`
`steps`は単一のキーと値のペアの配列になります
キーには`step_type`を設定します
値にはステップタイプに応じてハッシュまたは文字列を設定します

中にはこの形式ではないステップもあります

#### `checkout`
CircleCIのVM上に対象のリポジトリをチェックアウトします

#### `save_cache`
`path`でした指定したディレクトリ、もしくはファイルに`key`をつけて保存します
キャッシュの復元には`restore_cache`を使用します
`{{ .Branch }}`はcacheのキー用のテンプレートの一つで、ビルドしているブランチ取得します
その他のテンプレートは以下を参考にしてください
https://circleci.com/docs/2.0/configuration-reference/#save_cache

#### `restore_cache`
`key`を元に保存されたキャッシュを復元します
キャッシュの保存には`save_cache`を使用します

#### `run`
実行するコマンドを定義します

##### `name` 
CircleCIのコンソールで表示されるステップの名前を設定します

##### `command`
実行するコマンドを定義します

#### `deploy`
基本的には`command`と変わりません
違いは並列処理をしていた場合全ての処理が終わるのを待ってから実行されるところです
弊チームでは並列処理を実行していないため動作確認はしていません

## `workflows`
`job`の実行順序などの制御に使用します

### `version`
上位階層の`version`と同じです

### `workflow_name`
今回では`test_and_deploy`のことです
`workflow_name`は一つの設定ファイル内でユニークである必要があります

現在workflow_nameを複数定義する方法がわからないため、教えていただきたいです:bow:

#### `jobs`
workflowで実行するjobを定義します

##### `job_name`
前述したものと同じ

###### `requires`
job開始時に正常に終了しているべきjobを定義します

###### `filters`
`branches`もしくは`tags`を利用してjobの実行を制御します

###### `branches`
`only`もしくは`ignore`のキーを持ちます
onlyは指定したブランチの場合のみ実行
ignoreは指定したブランチ以外の場合のみ実行

###### `tags`
`only`もしくは`ignore`のキーを持ちます
onlyは指定したタグの場合のみ実行
ignoreは指定したタグ以外の場合のみ実行

# まとめ
1.0の時と比べて大きく変わったため移行に時間がかかりました
ただ、まとまりがあって可読性は上がったのかと思います
あとなぜかわかりませんがめちゃくちゃ早くなりました