[React,Firebase,Github Actions] ５分でできる。ReactのアプリケーションをGithub ActionsでFirebaseにデプロイする方法

# やりたいこと

- 特定のブランチへのpush/mergeでそれぞれ異なる環境にデプロイ
- 一度に、Firebase HostingとCloud Functionsの両方にデプロイ

# 概略図

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/c536276f-b49f-d090-753e-bb0c7bcad00a.png)


# 使うもの
- Github Actions
- Github secrets
- Firebase CLI

# 手順 全部で3ステップ

## 手順1.ワークフロー用yamlを作成する。

以下はstagingブランチにpushした際に今回やりたい処理を実行するyaml。
これを`.github/workflows`直下に配置する。
production(本番環境)ブランチにも同様の処理をしたい場合は、ブランチ名を指定する部分だけをmainに書き換えたyamlを作成して同じく`.github/workflows`直下に配置する。

```yaml
name: Deploy The App To Firebase Hosting and Cloud Functions For Firebase
# 実行タイミング
"on":
  push: # pushで実行される。マージも含まれる
    branches:
      - staging  # どのブランチにマージした時に実行して欲しいか。

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checuout
        uses: actions/checkout@v2

      # ①アプリケーションをビルドする。
      - name: Install Packages And Build The Application
        run: cd ./path/to/your/hosting/app && npm i && npm run build
        env:
          CI: false

      # ②Hostingにデプロイ
      - name: Deploy to Hosting
        uses: w9jds/firebase-action@master
        with:
          args: deploy --only hosting --project=${{ secrets.PROJECT_ID_STG }}
        env:
          FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
          PROJECT_PATH: "cd ./path/to/your/firebase.json/directory" # firebase.jsonが存在するディレクトリへのパス

      # ③Cloud Functionsのコードに必要なpackageをinstall
      - name: Install Packages for Cloud Functions
        run: cd ./path/to/your/functions/app && npm i
        env:
          CI: false

      # ④Cloud Functionsにデプロイ
      - name: Deploy to Cloud Functions
        uses: w9jds/firebase-action@master
        with:
          args: deploy --only functions --project=${{ secrets.PROJECT_ID_STG }}
        env:
          FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
          PROJECT_PATH: "cd ./path/to/your/firebase.json/directory" # firebase.jsonが存在するディレクトリへのパス
```

### 注意点
コード中の③、④でそれぞれのコードをfirebaseにデプロイする際、firebase.jsonがどこに配置されているかが重要になる。
もしレポジトリのルートにfirebase.jsonがないのであれば、上記のコードのように環境変数`PROJECT_PATH`に.firebase.jsonが存在するディレクトリへのパスを示してあげる必要がある。
逆にルートにあれば省略可能。
出典:今回利用するaction: https://github.com/marketplace/actions/github-action-for-firebase
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/2861b77f-2cc7-7820-c105-a8a80d175a36.png)


## 手順2. デプロイ先ごとに異なる環境変数をGithub Secrets設定する
GithubActionsの中で使える環境変数をGithubのSecretsに設定する。
secretsはレポジトリ のsettingsのSecretsタブから設定できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/3b86fb46-3749-6311-d91a-4fd5346cf93f.png)

### firebaseのプロジェクトIdをsecretsに設定する
firebaseではプロジェクトごとにidが設定されており、これをデプロイコマンド使用時に`--project`に渡すことで指定したプロジェクトにデプロイすることができる。
上記コードでは`--project=${{ secrets.PROJECT_ID_STG }}`の部分
確認したら、任意の名前で登録する。
このプロジェクトIDはデプロイ先のプロジェクトごとに異なるので、それぞれ確認して別々の名前`HOGE_STG`と`HOGE_PROD`などで登録することをお勧めする。

確認方法は以下。

#### firebaseのプロジェクトIdを確認する
firebaseのプロジェクトIdはコンソールの次の場所から確認できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/771c9702-093e-5656-50d4-6001abb7c8a5.png)

あるいはコマンドラインでプロジェクトの一覧を表示して確認することもできる。

```shell
firebase projects:list
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/6e479a93-6c37-a52e-e838-15f870989602.png)

## firebaseのクレデンシャルトークンをsecretsに登録する
デプロイを実行する際に、認証トークンが必要になるのでそれを登録する。
コード中の以下の部分

```yaml
env:
 FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
```
### 認証トークンの取得方法
以下のコマンドをターミナルで実行すれば取得できる。

```shell
firebase login:ci
```
実行すると、ブラウザが立ち上がり、Googleログインと認証の許可を求められるのでログインして許可する。すると、ターミナル上にTOKENが払い出されるのでコピペしてsecretsに任意の名前で登録する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/da1ed20f-5132-5011-e4af-51bdf7803903.png)


以上。
あとは上記のyamlが含まれるコードをpush(merge)すればFirebase HostingとCloud Functionsに自動でデプロイされる。

# 参考
- [GitHub Action for Firebase](https://github.com/marketplace/actions/github-action-for-firebase)
- [GitHub ActionsでNuxtアプリをHostingとFunctionsにデプロイする](https://www.memory-lovers.blog/entry/2021/01/15/183000)