CircleCI から Firebase Hosting にデプロイするまで

# やりたいこと
CircleCI によって GitHub の master ブランチへのプルリクエストをマージしたタイミングで Firebase Hosting 環境にデプロイすることです。

Firebase を始めて利用する人向けに説明します。

また、CircleCI の説明については割愛します。
CircleCI について知りたい方は[こちら](https://qiita.com/sugurutakahashi12345/items/aeca12d9c5a5526c724c)の記事を読んでみてください。

# Firebase Hosting にコマンドラインからデプロイするまで

CircleCI から Firebase Hosting にコマンドラインからデプロイ前に、まずはコマンドラインから Firebase Hosting にデプロイまでについて説明します。

## クラウド上でのプロジェクトの作成

まずは、Firebase のプロジェクトを作成します。
[Firebase](https://firebase.google.com/?hl=ja) のサイトから「使ってみる」をクリックします。
<img width="1261" alt="a.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/24b65481-d052-f92b-6037-6d56a3322b77.png">
「プロジェクトを作成」をクリックします。
<img width="1253" alt="b.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/a81d9544-8593-ca46-e99c-9086a728d059.png">
適当な名前をつけて「続行」をクリックします。
<img width="1260" alt="c.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/e427c248-dbe5-4c5d-10c3-b686430f58c3.png">
「続行」をクリックします。
<img width="856" alt="d.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/040929ed-d3b4-b8eb-97c9-77a252a8e4e7.png">
全部チェックつけて「プロジェクトを作成」をクリックします。
<img width="799" alt="e.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/7d0602f1-ca7f-fb76-b0cb-268685ad5e29.png">
「続行」をクリックします。
<img width="369" alt="f.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/ec973562-cc0b-c783-8cba-c2daf8fddee4.png">
ダッシュボードに遷移できたらプロジェクトの作成の終了です。
<img width="1255" alt="g.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/5fee35df-03cf-8410-7d4e-0e5106a413f3.png">

## firebase login

ローカル環境で firebase コマンドを有効にするために firebase-tools をインストールする必要があるので `npm install -g` でインストールします。

```bash:firebase-toolsインストール
npm install -g firebase-tools
```

続いてログインコマンドを実行し、Googleアカウントを紐づけます。

```bash:ログイン
firebase login
```

ブラウザにこのような表示がでてきたらログイン完了です。
<img width="457" alt="h.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/c64f15d7-acc5-1750-8c65-3461530a9c3e.png">

## firebase init

Firebase Hostingにてデプロイさせたいプロジェクトにcdコマンドなどで移動して `firebase init` を実行します。
gitプロジェクトでいうと .gitignore がある階層で実行するイメージです。

今回、実際に `firebase init` を実行したリポジトリは[こちら](https://github.com/suguruTakahashi-1234/circle-test)に公開しております。
vue-cli にて作成したプロジェクトになります。
このプロジェクトを作成した記事は[こちら](https://qiita.com/sugurutakahashi12345/items/ed35018025a5732a46a5)になります。ご参考までに。

適当なディレクトリに移動して `firebase init` を実行します。

```bash:init
firebase init
```

対話方式で設定を求められます。

各環境に合わせて設定してください。今回の場合は以下に設定しました。

 - `? Which Firebase CLI features do you want to set up for this folder? Press Space to select fea
tures, then Enter to confirm your choices.` -> Hosting を選択。
 - `? Please select an option` -> Use an existing project を選択。
 - `? Select a default Firebase project for this directory` -> さきほど作成したプロジェクトを選択。
 - `? What do you want to use as your public directory?` -> `dist` ディレクトリを指定。これは vue-cli プロジェクトは `npm run build` コマンドによって `dist` ディレクトリに build したソースを配置するように設定しているため。ここは各環境に合わせて設定してください。
 - `? Configure as a single-page app (rewrite all urls to /index.html)?` -> SPA ではないので No を選択。
<img width="691" alt="j.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/adb5e66a-08ff-2062-6d88-b19d177828f3.png">

（↑このようなコンソールが表示されます）

## firebase deploy

この段階でコマンドによるデプロイが可能になります。

`npm run build` コマンドによって `dist` ディレクトリに build したソースを配置されます。（これは vue-cli での設定です。）


そして `firebase deploy` コマンドを実行することによって `dist` ディレクトリに配置されたファイル郡が Firebase Hosting にデプロイされます。

```bash:コマンドによるデプロイ
npm run build
firebase deploy
```
デプロイしたページにはコンソールに表示されるURLからアクセスできます。
<img width="630" alt="x.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/6612d8a3-e042-b73c-73b6-c0f3ee9fe062.png">

コンソールに表示されている `https://vuesample-e2c8b.web.app` にアクセスすると自作のWebページが表示されていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/211f9e40-b7a2-7cdb-09cd-0e7f6943c4b3.png)

Webサーバーを用意することなく簡単に世の中にデプロイできましたね！
これだけでもすごいことです！


# CircleCI から Firebase Hosting にデプロイするまで
コマンドラインからデプロイできるところまで先ほど説明しました。
そしてこれから CircleCI から Firebase Hosting にデプロイするまでについて説明します。

基本的な流れは以下のようになります。  
1. `firebase-tools` のプロジェクトへのインストール
2. Firebase のトークンの CircleCI への登録
3. `firebase deploy` コマンドの `.circleci/config.yml` への設定

## 1. `firebase-tools` のプロジェクトへのインストール

CircleCI で動く Pipeline に firebase-tools をインストールさせる必要があるので、ローカルのプロジェクトに対して `npm install --save-dev firebase-tools` コマンドを実行することによって、CircleCI の Pipeline 上で `npm install` した際に firebase-tools がインストールされるようにします。

```bash
npm install --save-dev firebase-tools
```

## 2. Firebase のトークンの CircleCI への登録

自身の環境外からデプロイするためには Firebase のトークンが必要なため、それを生成して CircleCI に登録します。

```bash:Firebaseのトークンの生成
firebase login:ci
```
以下のようにトークンが生成されます。
![https___qiita-image-store.s3.ap-northeast-1.amazonaws.com_0_259125_c72d35ab-7c9c-5dbc-a471-515bee8666be.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/7fdd466f-a664-76a3-e8f1-fabc6bfe88c3.png)

トークンが生成されたので、こちらを CircleCI に登録しに行きます。

CircleCI のサイトから右上の「Project Settings」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/3ea3c194-5cb8-304e-616e-8b8d08848f66.png)

「Environment Variables」 -> 「Add Environment Variables」をクリックする。
<img width="1792" alt="l.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/45efdd5b-558b-ebf3-a863-98d4ecc77868.png">

Name に FIREBASE_TOKEN、Value に先ほど生成したトークンを設定して「Add Variable」をクリックする。
<img width="581" alt="m.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/fe7ca35e-7c81-05ad-0c1f-e47c5cb27ada.png">

登録完了になります。
<img width="1045" alt="n.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/917ada7b-0d39-a2fc-ecb4-19f076890026.png">

これで .circleci/config.yml のコマンド上で `$FIREBASE_TOKEN` と宣言すれば、トークンが使用できます。

※ Firebase ID が記載されている .firebaserc を .gitignore に登録している場合は同様の手順で、`$FIREBASE_ID` を登録して、デプロイコマンド時に `$FIREBASE_ID` を指定してください。今回は .firebaserc を .gitignore として登録していないのでそちらについてはスキップします。

## 3. `firebase deploy` コマンドの `.circleci/config.yml` への設定

今回は `.circleci/config.yml` を以下のように登録しました。

```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:
  build:
    executor: default
    steps:
      - checkout
      - restore_npm
      - run:
          name: Install dependencies
          command: npm install
      - run: 
          name: Lint
          command: npm run lint
      - run: 
          name: Build
          command: npm run build
      - run:
          name: Test
          command: npm run test:unit
      - save_npm
  deploy:
    executor: default
    steps:
      - checkout
      - restore_npm
      - run: 
          name: Build
          command: npm run build
      - run:
          name: Check dist
          command: ls -la dist
      - run:
          name: Deploy to Firebase Hosting
          command: ./node_modules/.bin/firebase deploy --token=$FIREBASE_TOKEN

workflows:
  push-build:
    jobs:
      - build
      - deploy:
          requires:
            - build
          filters:
            branches:
              only: master
```
ポイントは Firebase Hosting にデプロイするのは master ブランチに Push された場合のみに設定したところです。（`filters`の箇所になります。）

つまり、以下のようにプルリクエストのために開発用ブランチでPushした場合は `build` のジョブのみ走り、master ブランチへのプルリクエストがマージされたタイミング、または master ブランチへ直接 Push した場合は `build` と `deploy` の2つのジョブが走るように設定しました。

もちろんプロジェクトの運用にもよりますがこのようにも設定できるということで、紹介も兼ねて設定しました。

下図のように feature/firebase ブランチでは `build` しか走ってないですが、master ブランチでは `build` と `deploy` の2つのジョブが走るようになっているのが確認できますね。

<img width="1085" alt="aas.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/4a41cec7-b958-eefe-1ee7-ebe38830dab6.png">

以上が CircleCI から Firebase にデプロイするまでになります。

# さいごに
次は今回のデプロイの結果を Slack で通知する仕組みを作成したいと思います。

次の記事↓
[CircleCI の Job の結果を Slack に通知する](https://qiita.com/sugurutakahashi12345/items/fd17fdf36b7b34f1fe31)