Help us understand the problem. What is going on with this article?

github actions でfirebaseに自動デプロイするための設定

サービス開発のときは、環境構築と同時にデプロイ自動化まで行うのが俺的セオリーです。
というわけで、firebaseを使ったアプリケーションのデプロイを自動化する方法を紹介します。

想定QA

Q. なんで環境構築と同時にデプロイ自動化までするの?面倒くない?

A. 下のような理由

  • 実際に使うインフラを知っておいたほうが、開発環境をどう構築したらいいかがわかる。開発環境は本番環境にできる限り近づけて作るべきなので、本番環境を先に知っといたほうがいい。
  • 開発終わってから、デプロイの仕方わからーんってなって、構成見直すといった手戻りを防げる。
  • どうせいつかやるから最初やっても同じ
  • 開発のときのテンションが上がる

Q. Github Actions癖強くない?CircleCIとかで良くない?餅は餅屋理論

A. Githubで完結するのは強い。Github Actionsのデプロイ設定が面倒くさいのは一時の苦痛だが、デプロイのためにCircleCI等使うサービス1つ増やすのは一生の苦痛。

目的

githubにpushしたら自動でデプロイされるように、github actionsを設定します。
nuxtアプリ(SPAモード)を題材に書きますが、ビルドコマンド等をよしなに変更したら、他の環境でも使えるはずです。

前提

firebaseのhosting, firestoreのrules/index, GCP Cloud Functionsの3つをデプロイします。

手順

  1. ci用にサービスアカウントを作成
  2. サービスアカウントの認証ファイルをbase64で変換
  3. github secretsにSA keyの登録
  4. [optional] firebaseの各種認証情報もついでに登録
  5. github actionsの設定
    1. firebase hostingへのデプロイ
    2. firebase firestoreのデプロイ
    3. functionsのデプロイ

ci用にサービスアカウントを作成

https://console.cloud.google.com/iam-admin/serviceaccounts よりci用のサービスアカウントを作成します。

image.png
「サービスアカウントを作成」ボタンをおします。

image.png
IDを適当に設定し、作成を押します。

image.png
「Firebase Develop 管理者」の権限を付与します。
後述するCloudFunctionsにもデプロイする場合は、「Cloud Functions開発者」「サービス アカウント ユーザー」のロールも付与します。

次の画面の「ユーザーにこのサービス アカウントへのアクセス権を付与」は設定せずに、そのまま作成します。

image.png
一覧画面に戻ったら、詳細メニューから鍵を作成のボタンを押し、jsonファイルをダウンロードします。

サービスアカウントの認証ファイルをbase64で変換

jsonファイルをbase64で文字列に変換します。
macだとこんな感じで変換できます。
gcp-sa-key.jsonは先程ダウンロードしたファイルです。

> cd ~/Downloads
> cat gcp-sa-key.json | base64
NANKARANDOMPPOIMOZIRETSUGADETEKURU4LJ5HFROPO2pSTNgt1HhKU6ZIo1n2t
1YY5uiNoIziuZI5QwYrd0szqBu6vGQJ6UuZPqZfEP6gmKX8FFXUXldj0yKcEx+7C
DWgMir3m/Tz4PoXQBVx7tqG3NdMoM3gCm4k++HHWHRP/VX3Xf+UB8UQEl+VsSOgk
PP96iGr2pW3WAo7IJK/qB0nQ
# このままクリップボードにコピー(mac限定)
> cat gcp-sa-key.json | base64 | pbcopy

github secretsにSA keyの登録

githubリポジトリに行き、settingsの中のsecretsから環境変数を設定します。
url的にはhttps://github.com/{your_account}/{your_repo_name}/settings/secretsでアクセスできます。
image.png

[optional] firebaseの各種認証情報もついでに登録

本筋と外れますが、nuxtとfirebaseをつなぐ認証情報をここで色々設定しておきます。
最終的にはこんな感じになります。
image.png

github actionsの設定

ここからが本題です。
今回用いるプロジェクト構成図は以下のようになっています。
(関係するファイルのみ抜き出しています。)

root
├── firestore // firestoreのrulesやindexesをまとめたディレクトリ
│   ├── firebase.json // firestoreの設定
│   ├── firestore.rules // firestoreの読み書きrules
│   ├── firestore.indexes.json // firestoreのindexの設定
│    ・・・
├── front // フロントのコードをまとめたディレクトリ nuxt create-app の成果物。
│   ├── firebase.json // hostingの設定が書かれている
│    ・・・
└── functions
    ├── func1
    └── func2

firebase hostingへのデプロイ

説明はyml内に書きます。

deploy.yml
name: Deploy

# masterにpushするたびに、github actionsを走らせる。
on:
  push:
    branches: [ master ]

# jobを複数定義できる。
jobs:

  # frontのデプロイ
  front:
    runs-on: ubuntu-latest
    # デフォルトで走らせるディレクトリを指定
    defaults:
      run:
        working-directory: ./front
    steps:
    - uses: actions/checkout@v2

    # node & yarn を入れる
    - name: setup node
      uses: actions/setup-node@v1
      with:
        node-version: '12.x'
    - name: install
      run: yarn
      env:
        NODE_ENV: development

    # yarn generateコマンドでbuildする。
    # nuxtに注入する環境変数を明示的に指定する。
    - name: build
      run: yarn generate
      env:
        APP_ENV: production
        NUXT_ENV_APIKEY: ${{ secrets.NUXT_ENV_APIKEY }}
        NUXT_ENV_AUTH_DOMAIN: ${{ secrets.NUXT_ENV_AUTH_DOMAIN }}
        NUXT_ENV_DATABASE_URL: ${{ secrets.NUXT_ENV_DATABASE_URL }}
        NUXT_ENV_PROJECT_ID: ${{ secrets.NUXT_ENV_PROJECT_ID }}
        NUXT_ENV_STORAGE_BUCKET: ${{ secrets.NUXT_ENV_STORAGE_BUCKET }}
        NUXT_ENV_MESSAGING_SENDER_ID: ${{ secrets.NUXT_ENV_MESSAGING_SENDER_ID }}
        NUXT_ENV_APP_ID: ${{ secrets.NUXT_ENV_APP_ID }}

    # build結果をfirebase hosgint にデプロイ
    # 先ほど取得したSAのkeyを環境変数として渡す。
    # PROJECT_ID は firebaseのプロジェクトID(uniqueな方)
    - name: Deploy Firebase Hosting
      uses: w9jds/firebase-action@master
      with:
        args: deploy --only hosting
      env:
        PROJECT_ID: your-pj-id
        GCP_SA_KEY: ${{ secrets.GCP_SA_KEY }}
        PROJECT_PATH: ./front

hostingだけしたい人はここまでで大丈夫です。

firebase firestoreのデプロイ

先ほどのdeploy.ymlに追記します。

deploy.yml
name: Deploy

# masterにpushするたびに、github actionsを走らせる。
on:
  push:
    branches: [ master ]

# jobを複数定義できる。
jobs:
  front:
    # ((省略))

  firestore:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2

    # front同様、SAのkeyを環境変数として渡す。
    # firebaseのdeployコマンドのoptionが異なる。
    - name: Deploy Firestore rules and index
      uses: w9jds/firebase-action@master
      with:
        args: deploy --only firestore
      env:
        PROJECT_ID: your-pj-id
        GCP_SA_KEY: ${{ secrets.GCP_SA_KEY }}
        PROJECT_PATH: ./firestore

functionsのデプロイ

注意: この章ではfirebaseのfunctionsではなくGCPのCloud Functionsへのデプロイの仕方を紹介します。(pythonを使いたかったため)

最後にfunctionsへのデプロイの仕方です。
functionsは別jobに並列化することで実行時間を減らすことができます。
functionのdeployにわたすoptionは公式ドキュメントから確認できます。

参考
- https://github.com/GoogleCloudPlatform/github-actions
- https://cloud.google.com/functions/docs/deploying/filesystem?hl=ja

deploy.yml
name: Deploy

# masterにpushするたびに、github actionsを走らせる。
on:
  push:
    branches: [ master ]

# jobを複数定義できる。
jobs:
  front:
    # ((省略))

  firestore:
    # ((省略))

  functions_func1:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout
      uses: actions/checkout@v2
    - uses: GoogleCloudPlatform/github-actions/setup-gcloud@master
      with:
        version: '290.0.1'
        service_account_key: ${{ secrets.GCP_SA_KEY }}
        project_id: your-pj-id
    - name: Deploy Functions
      run: |
        gcloud functions deploy a --allow-unauthenticated --source ./functions/func1 \
        --runtime python37 --trigger-http --region=asia-northeast1 \
        --set-env-vars ENV=production

  functions_func2:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout
      uses: actions/checkout@v2
    - uses: GoogleCloudPlatform/github-actions/setup-gcloud@master
      with:
        version: '290.0.1'
        service_account_key: ${{ secrets.GCP_SA_KEY }}
        project_id: your-pj-id
    - name: Deploy Functions
      run: |
        gcloud functions deploy a --allow-unauthenticated --source ./functions/func2 \
        --runtime python37 --trigger-http --region=asia-northeast1 \
        --set-env-vars ENV=production

まとめ

みなさんも快適な自動デプロイライフを!

aitaro
東京大学大学院 技術経営戦略学専攻
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away