Flutter on the WebをFirebase Hostingで公開する

この記事は、[「Flutter Advent Calendar 2021」](https://qiita.com/advent-calendar/2021/flutter)に投稿した「Flutter on the WebをFirebase Hostingで公開した」の一部となります。

# Firebase Hostingへ公開

GitHubにマージすると、`GitHub Action`で`Firebase Hosting`へデプロイするようにします。
`/Users/hidea/Documents/workspace/myapp` にFlutterのプロジェクトがあるという前提で話を進めます。

# GitHubを設定

GitHub上にリポジトリを作成します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4668/56c3e80b-04ae-2c27-4390-5fd7a1efebc4.png" width="512px"/>

作成したリポジトリに作ったFlutterプロジェクトをプッシュします。

```console
$ git init
$ git commit -m "first commit"
$ git branch -M main
$ git remote add origin https://github.com/hidea/myapp.git
$ git push -u origin main
```

# Firebaseへプロジェクトを追加

Firebase Hostingのドキュメントは以下が参考になります。

https://firebase.google.com/docs/hosting

Firebaseコンソールから作業します。
https://console.firebase.google.com/

Firebaseにプロジェクトを追加します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4668/5b8acadd-c766-f458-efa0-d834c3f41e3a.png" width="512px"/>
適当にプロジェクトに名前を付けます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4668/7fb491ed-4118-9863-2fd3-f6727b060638.png" width="512px"/>
Googleアナリティクスの設定etc.を経て、しばらく待機すると準備が完了します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4668/658fed29-4a4c-2c18-428d-3e9990cd9a84.png" width="512px"/>

# Firebase Hostingをセットアップ

作業はローカルのコンソールへ戻って、まず `Firebase CLI` をインストールします。
macosでの手順となるので、他の環境は以下のドキュメントを参考にしてください。

https://firebase.google.com/docs/cli

あらためて、`Firebase CLI` をインストールします。

```console
$ curl -sL https://firebase.tools | bash
```

Firebaseへログイン、ブラウザが開いて認証を求められるはずです。

```console
$ firebase login
```

プロジェクトリスト取得してみましょう。
先ほど追加したプロジェクトがあるはずです。

```console
$ firebase projects:list
✔ Preparing the list of your Firebase projects
┌──────────────────────┬────────────────┬────────────────┬──────────────────────┐
│ Project Display Name │ Project ID     │ Project Number │ Resource Location ID │
├──────────────────────┼────────────────┼────────────────┼──────────────────────┤
│ myapp                │ myapp-8bc55    │ 794621538619   │ [Not specified]      │
├──────────────────────┼────────────────┼────────────────┼──────────────────────┤
│ umadiag-app          │ umadiag-app    │ 1086908323424  │ [Not specified]      │
└──────────────────────┴────────────────┴────────────────┴──────────────────────┘
2 project(s) total.
```

Flutterのプロジェクトのパス上で、Firebase Hostingを設定をします。
`firebase init hosting` コマンドで初期化を行います。

```console
$ cd /Users/hidea/Documents/workspace/myapp
$ firebase init hosting

     ######## #### ########  ######## ########     ###     ######  ########
     ##        ##  ##     ## ##       ##     ##  ##   ##  ##       ##
     ######    ##  ########  ######   ########  #########  ######  ######
     ##        ##  ##    ##  ##       ##     ## ##     ##       ## ##
     ##       #### ##     ## ######## ########  ##     ##  ######  ########

You're about to initialize a Firebase project in this directory:

  /Users/hidea/Documents/workspace/myapp

=== Project Setup

First, let's associate this project directory with a Firebase project.
You can create multiple project aliases by running firebase use --add,
but for now we'll just set up a default project.
```

- 既存のプロジェクトを選択 **myapp**

```console
? Please select an option: Use an existing project
? Select a default Firebase project for this directory: myapp (myapp)
i  Using project myapp (myapp)

=== Hosting Setup

Your public directory is the folder (relative to your project directory) that
will contain Hosting assets to be uploaded with firebase deploy. If you
have a build process for your assets, use your build's output directory.
```

- 公開ディレクトリ **build/web**
- シングルページアプリ **Yes**
- GitHubで自動デプロイ **Yes**
（GitHub Actionの定義ファイルが自動生成されます）

```
? What do you want to use as your public directory? build/web
? Configure as a single-page app (rewrite all urls to /index.html)? Yes
? Set up automatic builds and deploys with GitHub? Yes
✔  Wrote build/web/index.html

i  Detected a .git folder at /Users/hidea/Documents/workspace/myapp
i  Authorizing with GitHub to upload your service account to a GitHub repository's secrets store.

Visit this URL on this device to log in:
Waiting for authentication...

✔  Success! Logged into GitHub as hidea
```

- GitHubリポジトリを指定 **hidea/myapp**

```console
? For which GitHub repository would you like to set up a GitHub workflow? (format: user/repository) hidea/myapp

✔  Created service account github-action-xxx with Firebase Hosting admin permissions.
✔  Uploaded service account JSON to GitHub as secret FIREBASE_SERVICE_ACCOUNT_MYAPP.
i  You can manage your secrets at https://github.com/hidea/myapp/settings/secrets.
```

- デプロイの度にビルドするか **Yes**
- デプロイ時に実行するスクリプト **flutter build web**（Flutterのビルドコマンド）

```
? Set up the workflow to run a build script before every deploy? Yes
? What script should be run before every deploy? flutter build web

✔  Created workflow file /Users/hidea/Documents/workspace/myapp/.github/workflows/firebase-hosting-pull-request.yml
```

- マージの度に自動的にデプロイするか **Yes**
- デプロイするブランチ名 **main**

```console
? Set up automatic deployment to your site's live channel when a PR is merged? Yes
? What is the name of the GitHub branch associated with your site's live channel? main

✔  Created workflow file /Users/hidea/Documents/workspace/myapp/.github/workflows/firebase-hosting-merge.yml

i  Action required: Visit this URL to revoke authorization for the Firebase CLI GitHub OAuth App: xxx
i  Action required: Push any new workflow file(s) to your repo

i  Writing configuration info to firebase.json...
i  Writing project information to .firebaserc...

✔  Firebase initialization complete!
```

初期設定コマンドは完了すると、以下のファイルが追加されます。

- .firebaserc
- .github/workflows
	- firebase-hosting-merge.yml
	- firebase-hosting-pull-request.yml
- firebase.json

# GitHub ActionへFlutterビルド環境を追加

GitHub Actionで実行する基本は生成されますが、そのままではFlutterのビルドには足りません。
`/myapp/.github/workflows`に生成されてた2ファイルを編集してFlutterアプリをビルドできる環境を整えます。

当初は、`git clone https://github.com/flutter/flutter.git -b stable`とか直接Flutterのリポジトリをクローンしていたのですが、気がついたら便利なライブラリ`subosito/flutter-action`があったのでそちらを利用します。

https://github.com/subosito/flutter-action

- firebase-hosting-merge.yml
- firebase-hosting-pull-request.yml

「Flutter開発環境のセットアップを追加」以下の5行を追加してください。

```yaml:firebase-hosting-merge.yml
# This file was auto-generated by the Firebase CLI
# https://github.com/firebase/firebase-tools

name: Deploy to Firebase Hosting on merge
'on':
  push:
    branches:
      - main
jobs:
  build_and_deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2

      # Flutter開発環境のセットアップを追加
      - uses: subosito/flutter-action@v1
        with:
          channel: 'stable' # or: 'beta', 'dev' or 'master'
      - run: flutter pub get
      - run: flutter test --platform chrome
      # ここまでを追加

      - run: flutter build web
      - uses: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: '${{ secrets.GITHUB_TOKEN }}'
          firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_MYAPP_8BC55 }}'
          channelId: live
          projectId: myapp-8bc55
```

# デプロイ

リポジトリにマージするとデプロイが自動で始まります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4668/7f64465f-6143-020a-907d-f96e2e4ca341.png" width="512px"/>

完了したら、Firebaseのコンソールを確認してみて下さい。
こちらでもデプロイが終わった旨が通知されているはずです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4668/1460bb81-f78b-2463-3451-e0ab02c9d377.png" width="512px"/>

ホスティングを見ると、ドメインがわかるのでアクセスすれば確認出来るはずです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4668/e15eddca-1afc-1274-d776-8b4fb8b594d1.png" width="512px"/>

試しに、Flutterのサンプルをホスティングしてみました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4668/2841ff79-4bd7-656b-921f-6d38106456d6.png" width="512px"/>

以上です。