CircleCI 試してみた

# はじめに
Git と連携した CI/CD を勉強したく、GitHub と連携できる CircleCI なるサービスがあるとのことなのでそちらを試してみた内容をまとめたいと思います。

※初心者の備忘録になります。

# やったこと
一旦、適当なリポジトリで CircleCI の使用感を確かめてから、本命のリポジトリで試してみました。

# とりあえず CircleCI を動かしてみる

適当な[GitHubリポジトリ](https://github.com/suguruTakahashi-1234/sample_web_page/tree/circleci-project-setup)で試してみます。

原理は一旦置いておいて、とりあえず試すための手順を説明します。

今回、使用するリポジトリのファイルは以下の通りです（なんでもいいです）。
<img width="945" alt="a.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/d7bb14be-1df5-3f78-7302-51991d987e36.png">
https://app.circleci.com/projects にアクセスすると以下のように連携したGitHubのリポジトリが表示されます。
今回は sample_web_page リポジトリを用いており、そこの「Set Up Project」を選択します。
<img width="763" alt="b.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/75811b2f-b403-2e93-a4a1-88cf4d81b794.png">
以下の画面が表示されるのでとりあえず、「Add Config」を選択します。
これによって、画面下のデフォルトの内容で設定ファイルが追加されます。
<img width="768" alt="c.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/d458b619-b073-439c-1448-e7bc50392bcc.png">
「Add Config」を選択すると、いきなり Pipeline が動きます。

よくみると `circleci-project-setup` という見知らぬブランチが表示されていることがわかります。
「Add Config」すると勝手にこのリモートブランチが作成されるみたいです。

さきほどの設定ファイルもこのリモートブランチに追加されて、その設定ファイルを読みこんで Pipeline が動き出して、それがうまく動作して「SUCCESS」となるそうです。
<img width="1081" alt="d.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/82f86f09-eaa1-4f3a-de10-f0296c5f7363.png">
`circleci-project-setup` ブランチを確認しにいったら、やはり設定ファイルが作成されていましたね。
パスは `.circleci/config.yml` です。
<img width="1249" alt="e.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/fba20734-3dec-b8d1-0cb9-390d96e71d94.png">
とりあえず、動かすことには成功したようです。

# ローカルでの確認
次にローカルでも CicleCI が動くとのことなので動かしてみたいと思います。

ちなみに config.yml の設定ファイルを新規作成、または更新するときは、いちいちPushしてリモートのCicleCIで稼働は確認せずに、一度ローカルで動くことを確認してからPushするのがいいとのことです。（なるほど！）

この記事を参考にしました。
[CircleCI 2.0 をlocalで動かす](https://qiita.com/13Slhr77Cgzn892/items/81831234aa605e4b6464)

※前提としてDockerが入っていることになります。

以下のコマンドでインストールできます。

```bash:circleciコマンドのインストール
$ curl -o /usr/local/bin/circleci https://circle-downloads.s3.amazonaws.com/releases/build_agent_wrapper/circleci && chmod +x /usr/local/bin/circleci
circleci update

（省略）

$ circleci version

circleci version: 0.1.0
INFO: We\'ve built a brand new CLI for CircleCI! Please run 'circleci switch' to upgrade.
Build Agent version: 1.0.37604-d5a5647e
Built: 2020-07-28T20:10:21+0000

# アップデートのため 'circleci switch' コマンドを求められたので実行
$ circleci switch
（省略）

$ circleci version
0.1.8764+bb7188b (release)
```
circleci コマンドをインストールできました。

ここからは先ほど、とりあえず試してみた `circleci-project-setup` ブランチの `.circleci/config.yml` で試すとどうなるか検証してみます。

まず、`circleci config validate -c .circleci/config.yml` コマンドで validation チェックします。

```bash:validate
$ circleci config validate -c .circleci/config.yml
Config file at .circleci/config.yml is valid.
```

成功したのでビルドを試してみます。

`circleci build .circleci/config.yml` コマンドを実行するとローカル環境で `.circleci/config.yml` ファイルを読みこんでビルドが走ります。

```bash:ローカル環境での実行
$ circleci build .circleci/config.yml
（なぜかエラー出力）
```

うまくいきませんでした。。。
成功すると、Dockerが動き出して、リモートのCicleCI上で行っていることが起こります。

調べてみたらどうやら v2.1系には対応していないとのことでした。（[ソース](https://qiita.com/nemotoy/items/7a9b8958a051df1de40f)）

一旦、validation チェックだけのためになってしまいましたが、なにもしないよりはマシなので、これでいきたいと思います。

# 本命のリポジトリでいろいろ試してみる

Vue.js で作成したプロジェクトで CicleCI を試してみたいと思います。

Vue.js のプロジェクトであれば、npm の各種コマンドやユニットテストも実行可能なので、そちらも CicleCI でビルドを走らせてより開発案件に近い形で実行させます。

操作は[こちらの記事](https://qiita.com/tatane616/items/8624e61473a9957d9a81)を参考にさせていただきました。

リポジトリは[こちら](https://github.com/suguruTakahashi-1234/circle-test)になります。

ちなみにこのリポジトリは [vue-cliでプロジェクト作成してあれこれ試してみた（初心者向け）](https://qiita.com/sugurutakahashi12345/items/ed35018025a5732a46a5)で作成したものになります。

## config.yml の設定

本記事では割愛しますが、このあたりの記事が config.yml の書き方の説明がわかりやすかったです。

[GitHub+CircleCI入門](https://qiita.com/tatane616/items/8624e61473a9957d9a81)
[いまさらだけどCircleCIに入門したので分かりやすくまとめてみた](https://qiita.com/gold-kou/items/4c7e62434af455e977c2)

今回設定した config.yml は以下の通りです。

```yml: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: default
    steps:
      - checkout
      - run:
          name: Install dependencies
          command: npm install
      - save_npm

  lint:
    executor: default
    steps:
      - checkout
      - restore_npm
      - run: 
          name: Lint
          command: npm run lint
      - save_npm

  build:
    executor: default
    steps:
      - checkout
      - restore_npm
      - run: 
          name: Build
          command: npm run build
      - save_npm

  test:
    executor: 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:
 - docker : Dockerイメージは `node:12` を利用
 - working_directory : ワーキングディレクトリを `~/workspace` に設定（※working_directory で指定したディレクトリが存在しない場合は、自動的に作成されます。） 

- commands
 - restore_npm : package.json のハッシュをキーにして node_modules のキャッシュを復元（npm系のお決まりみたいです）
 - save_npm : package.json のハッシュをキーにして node_modules のキャッシュを保存（npm系のお決まりみたいです）
- jobs
 - setup : `npm install` コマンドを実施する
 - lint : `npm run lint` コマンドを実施する
 - build : `npm run build` コマンドを実施する
 - test : `npm run test:unit` コマンドを実施する
- workflows
 - pull-request: setup > lint > build > test と jobを順次実行する pull-request と言う名前のワークフロー

本稿でも記述したように一旦こちらのファイルはリモートに上げる前に、ローカルで実行してみます。

```bash:config.yml
$ circleci config validate -c .circleci/config.yml
Config file at .circleci/config.yml is valid.

$ circleci build .circleci/config.yml
（エラーでした）
```
またもや、うまくいきませんでした。。。
調べてみたらどうやら restore_npm や save_npm は対応していないとのことです。（[ソース](https://qiita.com/nemotoy/items/7a9b8958a051df1de40f)）

あんまり、ローカルでの動きは保証されてないみたいですね。。。
結局リモートで確かめるしかないようです。

## CircleCI のビルドのタイミング
CircleCI が走るタイミングはデフォルトでは、どんなブランチでも Push されたときにビルドが走る設定になっております。

ビルドのタイミングは細かく設定することもでき、例えば特定のブランチを選択したり、Push ではなく Pull Request のタイミング、またはcronのようなスケジューリングなども設定することができます。（[やり方](https://udomomo.hatenablog.com/entry/2020/03/08/232353)）

また、話が若干それますが CircleCI のビルドが成功しないと、Pull Request 時にマージできないようにも設定できます。([やり方](https://qiita.com/gold-kou/items/4c7e62434af455e977c2#%E4%BB%BB%E6%84%8Fci%E3%81%AB%E6%88%90%E5%8A%9F%E3%81%97%E3%81%AA%E3%81%84%E3%81%A8%E3%83%9E%E3%83%BC%E3%82%B8%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84%E3%82%88%E3%81%86%E3%81%AB%E3%81%97%E3%81%9F%E3%81%84github%E5%81%B4%E3%81%AE%E8%A8%AD%E5%AE%9A))

## Pull Requst での CircleCI ビルドの確認

上記のように Pull Request を出さなくても Push のタイミングでビルドが走りますが、今回は実際の運用を想定して検証用のブランチを Push したのちに Pull Request を出して動きを確認してみたいと思います。

Push したのちに Pull Request を出して CircleCI のビルドに成功すると、以下のように Pull Request の画面で `All checks have passed` と表示されます。
<img width="952" alt="ss.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/f2b1df88-77b2-fa93-5c16-f561fee974f6.png">

次に、この状態からあえて、ユニットテストを失敗するようにコミットを入れて、Push した結果が以下になります。

一目瞭然で、ビルドにエラーが発生したことが確認できますね。
<img width="836" alt="sss.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/9d4642bf-9b21-1ba8-c6ed-f7dd6c482dd8.png">
さらに失敗した test の 「Details」 をクリックしてエラーの内容を確認します。 

すると CircleCI のサイトに遷移して、test の中のどこのStepで失敗したかがわかるように表示されます。
<img width="1241" alt="スクリーンショット 2020-07-30 2.29.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/63a33bdf-76a5-1ea6-2249-f0a1f67648bd.png">

ここまでが一通り試してみた結果になります。

# さいごに
個人的に初の CI は経験できましたが CD まではできていないので、次は CD を実施したいと思います。

次の記事↓
[CircleCI から Firebase Hosting にデプロイするまで](https://qiita.com/sugurutakahashi12345/items/04b78b946322b8b410f7)