CircleCIを使ってFirebaseに開発環境と本番環境へのCICDを構築する

firebaseでの開発を効率化する為にcircleCIでのデプロイ自動化を構築してみた。

# 要約（目次）
1. nuxt.jsプロジェクト作成
2. firebaseにプロジェクトを二つ立てる（開発/本番）
3. `firebase init` 手打ちで初期設定
4. CircleCIで自動デプロイ設定

# 1. nuxt.jsプロジェクト作成
`nuxt-create-app`でnuxt.jsのプロジェクトをクリエイト。パッケージマネージャーはnpm, レンダリングモードはSPAを選んでください。
githubにリポジトリを登録。
git-flowで`develop`ブランチをクリエイトする。

# 2. firebaseにプロジェクトを二つ立てる（開発/本番）
ここからが本題
1. firebaseコンソールで「プロジェクトを追加」をクリックしてプロジェクトを追加する。
2. 「アプリを追加」するとAPI_KEYなどが発行される。この中の`projectId`を後でCircleCIに登録する。
3. 1,2をもう一度実行して開発用プロジェクトの構築する。プロジェクト名などに`_dev`などと入れておくとわかりやすい。

# 3. `firebase init` 手打ちで初期設定
初回デプロイは初期設定などがあるため手動で行います。
1. `firebase-tools`をインストールして`firebase init`で初期設定

```
$ npm install -g firebase-tools
$ firebase init
```
2.hostingを選択します。
3. 先ほど作成した本番firebaseプロジェクトを選択。
4. 公開フォルダは`dist`を指定します。

```
? What do you want to use as your public directory? dist
```

5.SPAかどうかを聞かれる、yを入力

```
? Configure as a single-page app (rewrite all urls to /index.html)? (y/N) y
```
6.index.htmlが存在すればそれを上書きするかどうか聞かれる。筆者の環境では既存プロジェクトで既にあるのでNを入力。

```
? File dist/index.html already exists. Overwrite? (y/N) N
```
これでホスティング設定は完了。確認のためデプロイしてみましょう。

```
$ npm run build
$ firebase deploy
```

7.次に開発用プロジェクトへのデプロイを行います。`firebase use --add`で開発用プロジェクトとも紐付けます

```
$ firebase use --add
? Which project do you want to add? 
```
firebaseの設定はこれで完了です。

# 4. CircleCIで自動デプロイ設定
1.「ADD PROJECT」からCircleCIプロジェクトを作成

2.CI用firebaseトークンを発行

```
$ firebase login:ci

Visit this URL on any device to log in:
(認証用のURL)

Waiting for authentication...

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

(トークンが表示されるので控える)

Example: firebase deploy --token "$FIREBASE_TOKEN"
```
3.CircleCIの環境変数を登録
<img width="1073" alt="スクリーンショット_2020-05-11_15_05_03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507709/b0f75d9a-ef2c-900c-b30d-b216af257e0d.png">

4.CircleCI設定ファイル作成
ルートディレクトリに`.circleci/config.yml`を作成

```.circleci/config.yml
version: 2
jobs:
  deploy_master:
    docker:
      - image: circleci/node:latest
    steps:
      - checkout
      - run:
          name: install firebase-tools
          command: sudo npm install -g firebase-tools
      - run:
          name: install nuxt
          command: npm install nuxt
      - run:
          name: build project
          command: npm run build
      - run:
          name: Deploy Firebase Hosting
          command: firebase deploy --token $FIREBASE_CI_TOKEN --project $PROD_PROJECT_ID

  deploy_dev:
    docker:
      - image: circleci/node:latest
    steps:
      - checkout
      - run:
          name: install firebase-tools
          command: sudo npm install -g firebase-tools
      - run:
          name: install nuxt
          command: npm install nuxt
      - run:
          name: build project
          command: npm run build
      - run:
          name: Deploy Firebase Hosting
          command: firebase deploy --token $FIREBASE_CI_TOKEN --project $DEV_PROJECT_ID

workflows:
  version: 2
  build_and_deploy: # ワークフローの名前
    jobs:
      - deploy_dev: # 上で定義したジョブを指定します
          filters:
            branches:
              only: develop # developブランチのみを実行対象とします
      - deploy_master:
          filters:
            branches:
              only: master # masterブランチのみを実行対象とします
```

これでdevelopブランチにpushかmergeすると開発用firebaseプロジェクトに、masterブランチだと本番用プロジェクトにデプロイされます。