GitHub+CircleCI入門

# CircleCIとは

[CircleCI](https://circleci.com/) はSaaS型のCI/CDサービスです。
CI/CDとは「Continuous Integration / Continuous Delivery」の略であり、ビルドやテスト、デプロイを自動化して継続的に行うものです。
GitHubやBitbucketなどのGitホスティングサービスと連携することで、コードがPushされるなどのトリガーに応じて任意の処理を行うことができます。

今回は、PRを出した時にフロントエンドのテストが走るような設定を行ってみます。

# CircleCIでHello Worldしてみる

### アカウント登録
まずアカウントを作る必要がありますが、GitHubやBitbucketを既に利用している方は
[Signup](https://circleci.com/signup/)から「Sign Up with GitHub」や「Sign Up with Bitbucket」で簡単に登録できます。

![スクリーンショット 2019-05-18 18.02.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196629/be90adc2-2ab6-19d9-278f-4d58b9ee2d58.png)

### config.yml追加
GitHubで任意のリポジトリを作ったら、CircleCIの設定ファイルを書きます。

CircleCIの設定は、ルート直下に`.circleci`と言うフォルダを作り、その中の`config.yml`で行います。
`config.yml`に以下を追記してみましょう。

``` ..circleci/config.yml
version: 2.1
jobs:
  build:
    docker:
      - image: circleci/node:4.8.2
    steps:
      - checkout
      - run: echo "hello world"
```

上記のコードは、以下のことを行っています。
1. `circleci/node:4.8.2`というイメージを利用したDocker環境を立ち上げ
2. CircleCIがGitHubリポジトリをチェックアウトして上記Docker環境にリポジトリをクローン
3. `echo "hello world"`を実行

### CircleCI上でリポジトリをセットアップ＆ビルド
CircleCIのダッシュボードに行き、サイドバーから「ADD PROJECTS」を開き、先ほどのリポジトリを選んで「Set Up Project」します。
![Add Projects - CircleCI 2019-05-18 18-30-52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196629/dacccf71-fad4-0aa9-f28a-1933d89d73c0.png)

設定はそのままで、下の方にある「Start Building」をクリックしてみましょう。
![Add Projects - CircleCI 2019-05-18 18-34-40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196629/1d31111c-2eeb-d86d-01bd-bedbc952cb63.png)

ビルドが開始され、「RUNNING」→「SUCCEED」となったら成功です！
![スクリーンショット 2019-05-18 18.36.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196629/99f1a5b1-2832-ae15-dd20-b83024bb71bb.png)
![スクリーンショット 2019-05-18 18.36.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196629/8bac9366-bbec-77b6-133d-dcf4c8f24de4.png)

詳細を見てみると、ちゃんと「Hello World」されています！🎉
![CircleCI - CircleCI 2019-05-18 18-40-57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196629/ea8f5e9f-93ca-5ecd-6d6d-35b4cb09524e.png)


# CircleCIの設定
Hello Worldもできたので、今回利用するCircleCIの設定について少しだけ見てみます。

## version
CircleCIのバージョンです、`2`、`2.0`、`2.1`のうちのどれかを指定します。(2019/5/18時点)

## commands
commandsは、ジョブで実行する処理を定義しておくものです。
複数のジョブで同じ処理を行いたいときなどに、コマンドの再利用が可能になります。

```yaml
commands:
  sayhello:
    description: "A very simple command for demonstration purposes"
    parameters:
      to:
        type: string
        default: "Hello World"
    steps:
      - run: echo << parameters.to >>

```

## executors
executorsは、ジョブの実行環境を定義するものです。
複数のジョブで同じ環境を再利用したい時に便利です。

```yaml
version: 2.1
executors:
  my-executor:
    docker:
      - image: circleci/ruby:2.5.1-node-browsers

jobs:
  my-job:
    executor: my-executor
    steps:
      - run: echo outside the executor
```

## jobs
実行処理の単位です。
以下で説明するWorkflowsを使わない場合は、jobsマップに`build`と言う名前のジョブを用意する必要があります。
`build`ジョブは、GitHubなどのプッシュをトリガーにしてビルドする際のデフォルトのエントリーポイントです。
`steps`の中に実行したい処理を書いていきます。

```yaml
jobs:
  build:
    docker:
      - image: buildpack-deps:trusty
    environment:
      FOO: bar
    parallelism: 3
    resource_class: large
    working_directory: ~/my-app
    branches:
      only:
        - master
        - /rc-.*/
    steps:
      - run: make test
      - run: make
```

## workflows
workflowsは、複数のジョブを自動化することができます。
以下のサンプルだと、`build-deploy`と言う名前のworkflowが`build`, `deploy-stage`, `deploy-prod`の3つのジョブを実行しています。
`require`で、ジョブ間の依存関係を明確にしておくことができます。

```yaml
workflows:
  version: 2
  build-deploy:
    jobs:
      - build:
          filters:
            branches:
              ignore:
                - develop
                - /feature-.*/
      - deploy-stage:
          requires:
            - build
          filters:
            branches:
              only: staging
      - deploy-prod:
          requires:
            - build
          filters:
            branches:
              only: master
```

設定の詳細は、[Configuration Reference](https://circleci.com/docs/2.0/configuration-reference/)をご覧ください。

# サンプルプロジェクト
それでは、いよいよPRをトリガーにしてCircleCI上でフロントエンドのテストが実行されるように設定してみましょう！
「Vueで開発を行っていてPRでテストが走るようにしたい」ということにします。

## 今回使うプロジェクトを用意
Vueのプロジェクトを作ります。

```console
$ npm install -g @vue/cli
$ vue create circleci-test
``` 

プロジェクト作成時にはマニュアルを選び、テストも入れましょう。
![スクリーンショット 2019-05-18 19.39.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196629/5dcad19b-1d28-502f-e76d-e3b25f15b84c.png)

`npm run test:unit`でテストが走るのを確認できます。


## config.ymlを追加
`.circleci/config.yml`を作成します。

``` ..circleci/config.yml
version: 2.1
executors:
  default:
    working_directory: ~/workspace
    docker:
      - image: node:12

commands:
  restore_npm:
    steps:
      - restore_cache:
          name: Restore npm dependencies
          key: npm-{{ checksum "package.json" }}

  save_npm:
    steps:
      - save_cache:
          name: Cache npm dependencies
          key: npm-{{ checksum "package.json" }}
          paths:
            - ~/workspace/node_modules

jobs:
  setup:
    executor:
      name: default
    steps:
      - checkout
      - run:
          name: Install dependencies
          command: npm install
      - save_npm
    
  lint:
    executor:
      name: default
    steps:
      - checkout
      - restore_npm
      - run: 
          name: Lint
          command: npm run lint
      - save_npm
         
  build:
    executor:
      name: default
    steps:
      - checkout
      - restore_npm
      - run: 
          name: Build
          command: npm run build
      - save_npm
         
  test:
    executor:
      name: default
    steps:
      - checkout
      - restore_npm
      - run: 
          name: Test
          command: npm run test:unit
      - save_npm

workflows:
  pull-request:
    jobs:
      - setup
      - lint:
          requires:
            - setup
      - build:
          requires:
            - lint
      - test:
          requires:
            - build
```

それぞれの設定について詳しく見てみます。

- executors:
    - working_directory: ワーキングディレクトリを`~/workspace`に設定
    - docker: Dockerイメージは`node:12`を利用
- commands
    - restore_npm: `package.json`のハッシュをキーにして`node_modules`のキャッシュを復元
    - save_npm: `package.json`のハッシュをキーにして`node_modules`のキャッシュを保存
- jobs
    - setup: リポジトリをクローンし、`npm install`を行う。
    - lint: リポジトリをクローンし、`npm run lint`を行う。
    - build: リポジトリをクローンし、`npm run build`を行う。
    - test: リポジトリをクローンし、`npm run test:unit`を行う。
- workflows
    - pull-request: setup→lint→build→testの依存関係を持つ`pull-request`と言う名前のワークフロー

## GitHubリポジトリを用意とCircleCIのセットアップ
GitHubで`circleci-test`というリポジトリを用意し、先ほどのVueのプロジェクトをPushします。
さらに、Hello Worldの時と同様にCircleCIのダッシュボードに行き、`circleci-test`をセットアップします。

## ブランチを切ってPRを出す
ブランチを切って、PRを作成してみましょう。
PRの画面で、このようにCircleCIが動いていることが確認できます。
![スクリーンショット 2019-05-18 20.11.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196629/d4176d70-1f7f-94c7-0af7-edbe2b7e1d33.png)

全て正常に終わると、このようにグリーンになります。
![スクリーンショット 2019-05-18 20.14.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196629/8af326e1-ebce-563e-7ac8-9d401a28fb5c.png)

CircleCIを見に行くと、テストが通っていることを確認できます。
![スクリーンショット 2019-05-18 20.16.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196629/d42b17fb-5ff8-6c34-059a-f1cfe335adb3.png)

CircleCI便利ですね！🎉

# オマケ：CircleCIのコンテナにSSHで入る
CircleCIでは、ビルドしたコンテナにSSHで入ることができます。
デバッグ時にメモリの使用率を見たり、直接色々コマンドを打ちたい時に便利です。

右上の「Rerun workflow」の隣の三角を押して「Rerun job with SSH」を選びます。
![CircleCI 2019-05-19 11-19-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196629/dffa543e-a9a3-c47f-e79e-30f65571213c.png)

するとSSHのコマンドが表示されるので、これをターミナルに打ち込むとSSHで入ることができます、便利！🎉
![CircleCI 2019-05-19 11-19-48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196629/f610734a-1125-faab-ce84-e962374f8de1.png)



# 参考
- [いまさらだけどCircleCIに入門したので分かりやすくまとめてみた](https://qiita.com/gold-kou/items/4c7e62434af455e977c2)
- [CircleCI 2.1 の新機能を使って冗長な config.yml をすっきりさせよう！](https://tech.recruit-mp.co.jp/dev-tools/post-14868/)