FIrebase Hostingで作った環境にcircleciで自動テストを導入してみた

# TL;DR
[以前の記事](https://qiita.com/Swordroot_M/items/7ea4f0e08f74ad62f027)で整えた環境で[ポートフォリオサイト](https://swordroot.work/)を作りました。
今回はそこにさらにciを導入して自動テストを行う環境を整備しました。

この記事ではこのポートフォリオのリポジトリでmasterブランチにpushされたら、circleciでテストとデプロイを自動で行うようにするところまで説明します。

# リポジトリとcircleciを紐づける
まずは、リポジトリとcircleciを紐づけます。そのためにまずは、githubアカウントを利用してcircleciにサインインします。![スクリーンショット 2019-09-12 10.38.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153926/2f6bd9d1-b5f0-4e79-c660-ffe810baa82a.png)

ログインしたら左サイドバーの`Add Project`をクリック
![スクリーンショット 2019-09-12 10.42.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153926/a8838fe8-e1f4-6c74-5656-c553dc0231a8.png)

その後、ciを導入したいリポジトリの右にある`SET UP PROJECT`をクリックします。そうすると導入手順が英語で書いてあります。
書いてある内容はざっくり意訳すると以下の通りですので、その通り進めていきます。

1. リポジトリ内に`.circleci/config.yml`を作成する。（内容は一旦表示されているものをコピペする）
2. リモートリポジトリにpushする
3. start buildingボタンをクリック![スクリーンショット 2019-09-12 10.49.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153926/17d29194-de05-e4df-e19e-8e05bb562d49.png)


これで「ブランチ問わずリモートリポジトリにコミットがpushされたら自動でテスト実行」という動作をするようになりました。

# テストを実行可能にする
次は、テストコードを実行できるようにしましょう。今回はjestを利用します。
まずは必要なパッケージをインストール

```bash
npm i -D jest @types/jest ts-jest
```

そして`package.json`と`tsconfig.json`に以下の内容を追加します。（ちょっとここわかりにくいかもしれないので、わかりづらかったら遠慮なくコメントとか編集リクエストとか送ってください〜）

```json:package.json
{
  "scripts": {
    "test": "jest"
  },
  "jest": {
    "moduleFileExtensions": [
      "ts",
      "js"
    ],
    "transform": {
      "^.+\\.ts$": "ts-jest"
    },
    "globals": {
      "ts-jest": {
        "tsConfig": "tsconfig.json"
      }
    },
    "testMatch": [
      "**/tests/**/*.test.ts"
    ],
    "moduleNameMapper": {
      "^#/(.+)": "<rootDir>/$1"
    }
  }
}
```

```json:tsconfig.json
{
  "compilerOptions": {
    "types": [
      "@types/jest"
    ]
  },
  "include": [
    "./tests/**/*.ts"
  ]
}
```

これでTypeScriptでテストを記述して実行できるようになります。
試しに、以下のような100%成功するテストを書いて実行してみます。

```typescript:tests/sample.test.ts
describe('sample', () => {
  it('test is executed', () => {
    // some test
  })
})
```

そして以下のコマンドを実行

```
npm test
```

実行結果は以下の通り

```
> jest

 PASS  tests/sample.test.ts
  sample
    ✓ test is executed (1ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.755s, estimated 2s
```

ちゃんとテストが実行されていますね。

# circleci上からfirebaseにデプロイできるようにする
## トークンの取得
次に、circleci上からfirebaseにデプロイできるようにします。まずはデプロイのためにパッケージをインストール。

```
npm i -D firebase-tools
```

次に、circleci上の環境からデプロイするためのトークンを取得します

```
npx firebase login:ci
```

このコマンドを実行すると勝手にブラウザが開き、ログインに使用するアカウントを選ぶ画面がでくるのでアカウントを選びます。
選ぶとログインが完了し、コンソールに以下の内容が表示されています。

```
Visit this URL on this device to log in:
[認証用のURL]

Waiting for authentication...

✔  Success! Use this token to login on a CI server:

[デプロイ用トークン]

Example: firebase deploy --token "$FIREBASE_TOKEN"
```

このデプロイ用トークンを使うので控えておいてください。

## circleciの環境変数にトークンを登録
先ほど取得したトークンをcircleciに環境変数として登録します
circleciにログインして、左側サイドバーのsettingsをクリック
![スクリーンショット 2019-09-12 11.52.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153926/a1f31ab9-f8b6-24c0-3966-70deb9f3a31a.png)

次に左メニューのProjectsをクリック
![スクリーンショット 2019-09-12 11.52.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153926/02adfcf6-f33b-c91b-3031-abc3f0d320e1.png)

環境変数を追加したいプロジェクトの右端にある歯車のマークをクリック
![スクリーンショット 2019-09-12 11.53.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153926/63b657a1-8fe8-1b56-4ac0-db7db8be6f40.png)

Build SEttingsのEnvironment Variablesをクリック
![スクリーンショット 2019-09-12 11.53.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153926/af0de263-8957-95ce-f18f-55011dfe796b.png)

環境変数を追加したいプロジェクトの行の右端にあるAdd Variableをクリック
![スクリーンショット 2019-09-12 11.54.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153926/8bfcb09f-2c0c-5c1f-f8af-58cdf329a37f.png)


ポップアップが出てくるので、環境変数として先ほどのトークンを追加する
![スクリーンショット 2019-09-12 11.55.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153926/b10ac436-a8f8-edbc-70c3-d3dac053894d.png)

これでcircleciの環境変数に先ほどのトークンを追加できました。

## npm scriptにデプロイ用のスクリプトを追加

package.jsonに以下の内容を追加しましょう。

```json:package.json
{
  "scripts": {
    "deploy:hosting": "firebase deploy --only hosting --project your-project-id"
  }
}

```

これで自動化の準備が整いました。


# 自動でビルドするジョブを作る
さて、ここからcircleciを利用して自動で実行するジョブの内容を、config.ymlを編集する形で作っていきます。
まずはきちんとビルドできるか確かめるためにbuildジョブを作ります。
config.yamlを一回まっさらにして、新しく以下の内容を記述します。

```yaml:config.yml
version: 2
jobs:
  build:
    docker:
      - image: circleci/node:10 #circleciではdockerを利用してテスト環境を作るので、それに使うイメージを指定
      
    working_directory: ~/repo

    steps:
      - checkout
      - run: npm install
      - run: npm run build
```

これで、buildジョブの完成です。

# 自動でテストを実行するジョブを作る
次は、テストを実行するジョブです。`config.yaml`に以下のように追記しましょう

```yaml:config.yml
version: 2
jobs:
  build:
    docker:
      - image: circleci/node:10 #circleciではdockerを利用してテスト環境を作るので、それに使うイメージを指定
      
    working_directory: ~/repo

    steps:
      - checkout
      - run: npm install
      - run: npm run build
#ここから追記
  test:
    docker:
      - image: circleci/node:10
      
    working_directory: ~/repo

    steps:
      - checkout
      - run: npm install
      - run: npm test
```
これでテストを行うジョブの完成です

# 自動でデプロイするジョブを作る
次は、デプロイを実行するジョブです。`config.yaml`に以下のように追記しましょう

```yaml:config.yml
version: 2
jobs:
  build:
    docker:
      - image: circleci/node:10
      
    working_directory: ~/repo

    steps:
      - checkout
      - run: npm install
      - run: npm run build
  test:
    docker:
      - image: circleci/node:10
      
    working_directory: ~/repo

    steps:
      - checkout
      - run: npm install
      - run: npm test
#ここから追記
  deploy:
    docker:
      - image: circleci/node:10
      
    working_directory: ~/repo

    steps:
      - checkout
      - run: 
          command: |
            npm install
            npm run build
            npm run deploy:hosting -- --token $FIREBASE_TOKEN
```

これで自動でデプロイするジョブの完成です。

# ビルドからデプロイまで一連の処理を自動で行うワークフローの作成
最後に、ここまでで作った3つのジョブを順番に実行させるワークフローを作成します。

```yaml:config.yml
version: 2
jobs:
  build:
    docker:
      - image: circleci/node:10
      
    working_directory: ~/repo

    steps:
      - checkout
      - run: npm install
      - run: npm run build
  test:
    docker:
      - image: circleci/node:10
      
    working_directory: ~/repo

    steps:
      - checkout
      - run: npm install
      - run: npm test
  deploy:
    docker:
      - image: circleci/node:10
      
    working_directory: ~/repo

    steps:
      - checkout
      - run: 
          command: |
            npm install
            npm run build
            npm run deploy:hosting -- --token $FIREBASE_TOKEN
#ここから追記
workflows:
  version: 2
  build_test_deploy:
    jobs:
      - build
      - test:
          requires: 
            - build
      - deploy:
          requires: 
            - test
          filters:
            branches:
              only: master #masterブランチにpushされた時だけデプロイさせるためのフィルタ
```

これでconfig.ymlも完成です。

# masterブランチにプッシュして動作確認
最後に、masterブランチにプッシュして、動作確認をしましょう。

テスト結果はブラウザ上で確認できます確認するにはまず左サイドバーのworkflowsをクリック
![スクリーンショット 2019-09-12 12.24.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153926/16cdd49a-09fe-9f64-1e81-c5045ab06ed3.png)

次に確認したいプロジェクトをクリック
![スクリーンショット 2019-09-12 12.24.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153926/2473bde5-9b9d-8d3e-7c5d-54aceadc9899.png)

そうすると右側に、実行されたワークフローの一覧が出るので一番上の結果がscceededになっていれば成功です
![スクリーンショット 2019-09-12 12.25.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153926/5572a870-3f25-191f-d46f-f2a77815b0c5.png)

もしfailedになっていた場合は、クリックすると詳細を確認できるので、どこが失敗しているのか修正してまたプッシュしましょう。

# まとめ
長くなってしまいましたが、ビルド・テスト・デプロイを自動化することができました。
あとはテストの内容を詰めたいですね。