circleciでgithubのブランチ毎にfirebaseへのデプロイ先を切り替える方法

2020年7月19日Firebase,CircleCI

Firebaseに複数の環境(本番環境と開発環境など)とGitHubのブランチと関連付け、circleciを利用してビルド・テスト・デプロイを自動化する方法をまとめました。

環境(Firebase/circleci/GitHub)

Firebaseprod本番環境
dev開発環境
circleciconfig.ymlmaster/developブランチが更新されたタイミングでデプロイ実行
GitHubmasterブランチ本番環境にデプロイするブランチ
developブランチ開発環境にデプロイするブランチ

環境別の.envファイルを作成する

Firebaseの設定ファイルを環境別に2つ準備する

Firebaseの設定は、以下の手順で取得できます

  • Firebaseにログイン
  • 対象のプロジェクト選択
  • 歯車アイコンから「プロジェクトを設定」を選択
  • 「全般」タグの「マイアプリ」の「Firebase SDK snippet」で「構成」を選択

以下のような形式で表示されています。

const firebaseConfig = {
  apiKey: "xxxxxxxxxxxxxxxx",
  authDomain: "プロジェクトID.firebaseapp.com",
  databaseURL: "https://プロジェクトID.firebaseio.com",
  projectId: "プロジェクトID",
  storageBucket: "プロジェクトID.appspot.com",
  messagingSenderId: "9999999999",
  appId: "9:999999999999:xxx:999999999999999999",
  measurementId: "X-XXXXXXXXXXXX"
};

この情報を.envのファイル形式で環境別に作成します。

 

.env.dev

ファイル名は環境を区別するために「.env.dev」とします。

REACT_APP_API_KEY="xxxxxxxxxxxxxxxx"
REACT_APP_AUTH_DOMAIN="開発環境のプロジェクトID.firebaseapp.com"
REACT_APP_DATABASE_URL="https://開発環境のプロジェクトID.firebaseio.com"
REACT_APP_PROJECT_ID="開発環境のプロジェクトID"
REACT_APP_STORAGE_BUCKET="開発環境のプロジェクトID.appspot.com"
REACT_APP_MESSAGING_SENDER_ID="9999999999"
REACT_APP_APP_ID="9:999999999999:xxx:999999999999999999"
REACT_APP_MEASUREMENT_ID="X-XXXXXXXXXXXX"

 

.env.prod

ファイル名は環境を区別するために「.env.prod」とします。

REACT_APP_API_KEY="xxxxxxxxxxxxxxxx"
REACT_APP_AUTH_DOMAIN="本番環境のプロジェクトID.firebaseapp.com"
REACT_APP_DATABASE_URL="https://本番環境のプロジェクトID.firebaseio.com"
REACT_APP_PROJECT_ID="本番環境のプロジェクトID"
REACT_APP_STORAGE_BUCKET="本番環境のプロジェクトID.appspot.com"
REACT_APP_MESSAGING_SENDER_ID="9999999999"
REACT_APP_APP_ID="9:999999999999:xxx:999999999999999999"
REACT_APP_MEASUREMENT_ID="X-XXXXXXXXXXXX"

 

env-cmdのインストール

envファイルを切り替える方法として「env-cmd」を利用します。

他にも環境設定を切り替える方法として「cross-env」というものもありますが、Firebaseの場合は切り替えたい環境変数の数が多いため、「env-cmd」の方が便利です。

インストール方法(npm)

npm install env-cmd

 

インストール方法(yarn)

yarn add env-cmd

 

.firebaserc

.firebasercを編集しFirebaesの各プロジェクトIDに対して環境名を設定します。

そうすることで、firebaseコマンドを実行する際に環境名を指定することでプロジェクトIDを切り替えられるようになります。

{
  "projects": {
    "dev": "開発環境のプロジェクトID",
    "prod": "本番環境のプロジェクトID"
  }
}

ここでは、開発環境をdevとし本番環境をprodとして設定しています。

 

package.json

packeage.jsonのscriptsで、buildやdeployを環境別に準備しましょう。

以下の例はbuildとdeploy用のコマンドを環境別に設定した場合です。

  "scripts": {
    "build:dev": "env-cmd -f .env.dev react-scripts build",
    "build:prod": "env-cmd -f .env.prod react-scripts build",
    "test": "react-scripts test",
    "deploy:dev": "firebase deploy --only hosting --project=dev",
    "deploy:prod": "firebase deploy --only hosting --project=prod",
  },
コマンド内容やっていること
build:dev開発環境用のビルドコマンドenv-cmdで.env.devのファイルを指定しbuildコマンドを実行
build:prod本番環境用のビルドコマンドenv-cmdで.env.prodのファイルを指定しbuildコマンドを実行
testテストコマンドreact-scriptsのテストコマンド実行(※環境の区別なし)
deploy:dev開発環境用のデプロイコマンドfirebaseコマンドのprojectオプションでdevを指定しデプロイを実行
deploy:prod本番環境用のデプロイコマンドfirebaseコマンドのprojectオプションでprodを指定しデプロイを実行

このように設定することで、コンソールから各環境へのコマンドの実行が簡単になります。

例えば、開発環境にデプロイする場合は

npm run deploy:dev

と実行します。

 

GitHubのアカウント取得とリポジトリの作成

今回の構成はGitHubの特定のブランチに変更があった場合にcircleciで自動ビルド・テスト・デプロイを行うことを前提としていますので、GitHubのアカウントがない場合は以下の記事を参考に取得してみてください。

 

circleciの設定

firebase-toolsのコマンドで各環境別にビルドやデプロイができる状態になれば、circleciの設定を行いましょう。

circleciのアカウント作成

circleciのアカウントは、以下のURLからGitHubのアカウントで取得できます。

circleciのページ

 

GitHubのリポジトリと関連付ける

以下の手順でGitHubのリポジトリと紐付けましょう。

  • circleciにログイン
  • 「Go to App」をクリック
  • GitHubのアカウントを選択する画面が表示されるので選択し次に進める
  • 「Add Projects」のアイコンをクリック
  • 関連付けするリポジトリの「Set Up Project」をクリック
  • 「Start Building」をクリック(※設定ファイルは後で書き換えるのでそのままクリックでいよい)

 

環境変数(Environment Variables)の設定

FirebaseのトークンIDがデプロイ時に必要になりますのでcircleciの環境変数に登録します。

ここでは環境別にそれぞれ以下の環境変数名で登録します。

環境変数名設定値
FIREBASE_TOKEN_PROD本番環境のFirebaseトークンID
FIREBASE_TOKEN_DEV開発環境のFirebaesトークンID

環境変数の設定方法

circleciのプロジェクトの設定画面から「Environment Variables」で環境変数を登録できます。

 

FirebaseトークンIDの確認方法

コンソールで以下のコマンドを実行すると、ブラウザで認証画面が表示されます。

認証完了後にコンソールにトークンIDが表じれます。

firebase login:ci

 

.circleci/config.yml

crcleciの設定ファイルは配置するフォルダとファイル名が決まっていますので、間違えずに作成しましょう。

GitHubのプロジェクトフォルダ
└─ .circleci
  └─ config.yml

 

developブランチを開発環境へデプロイし、masterブランチを本番環境へデプロイするサンプルです。

version: 2.1

#----------------------------------------------
# Deploy React App to Firebase Hosting
#----------------------------------------------

executors:
  executor:
    docker:
      - image: circleci/node:12.16.1

commands:
  npm_install:
    steps:
      - restore_cache:
          name: Restore Dependencies
          keys:
            - v1-dependencies-{{ checksum "yarn.lock" }}
      - run:
          name: Install Dependencies
          command: yarn install
      - save_cache:
          name: Save Dependencies
          key: v1-dependencies-{{ checksum "yarn.lock" }}
          paths:
            - node_modules

  firebase_install:
    steps:
      - run:
          name: Install Firebase CLI
          command: yarn add -D firebase-tools

  build:
    parameters:
      env_name:
        type: string
        default: "dev"
    steps:
      - run:
          name: Build Project
          command: yarn build:<< parameters.env_name >>

  deploy:
    parameters:
      env_name:
        type: string
        default: "dev"
      token:
        type: string
        default: $FIREBASE_TOKEN_DEV
    steps:
      - run:
          name: Deploy to Firebase Hosting
          command: node_modules/.bin/firebase deploy --only hosting --project=<< parameters.env_name >> --token << parameters.token >>

jobs:
  #-----------------------
  # jobs:dev
  #-----------------------
  build_dev:
    executor:
      name: executor
    working_directory: ~/tmp/dev
    steps:
      - checkout
      - npm_install
      - build:
          env_name: "dev"
      - persist_to_workspace:
          root: ~/tmp/dev
          paths:
            - .

  test_dev:
    executor:
      name: executor
    working_directory: ~/tmp/dev
    steps:
      - attach_workspace:
          at: ~/tmp/dev
      - run:
          name: Test Project
          command: yarn test

  deploy_dev:
    executor:
      name: executor
    working_directory: ~/tmp/dev
    steps:
      - attach_workspace:
          at: ~/tmp/dev
      - firebase_install
      - deploy:
          env_name: "dev"
          token: "$FIREBASE_TOKEN_DEV"

  #-----------------------
  # jobs:prod
  #-----------------------
  build_prod:
    executor:
      name: executor
    working_directory: ~/tmp/prod
    steps:
      - checkout
      - npm_install
      - build:
          env_name: "prod"
      - persist_to_workspace:
          root: ~/tmp/prod
          paths:
            - .

  test_prod:
    executor:
      name: executor
    working_directory: ~/tmp/prod
    steps:
      - attach_workspace:
          at: ~/tmp/prod
      - run:
          name: Test Project
          command: yarn test

  deploy_prod:
    executor:
      name: executor
    working_directory: ~/tmp/prod
    steps:
      - attach_workspace:
          at: ~/tmp/prod
      - firebase_install
      - deploy:
          env_name: "prod"
          token: "$FIREBASE_TOKEN_PROD"

workflows:
  version: 2
  build_and_deploy:
    jobs:
      #------------------------
      # develop branch to dev
      #------------------------
      - build_dev:
          filters:
            branches:
              only: develop
      - test_dev:
          requires:
            - build_dev
          filters:
            branches:
              only: develop
      - deploy_dev:
          requires:
            - test_dev
          filters:
            branches:
              only: develop

      #------------------------
      # master branch to prod
      #------------------------
      - build_prod:
          filters:
            branches:
              only: master
      - test_prod:
          requires:
            - build_prod
          filters:
            branches:
              only: master
      - deploy_prod:
          requires:
            - test_prod
          filters:
            branches:
              only: master

コマンドの共通化などを行っているため、長くなっていますがポイントは以下の2つです。

ポイント

  • branches:onlyでブランチ名を指定してビルド・テスト・デプロイの各コマンドを実行
  • package.jsonに設定したコマンドを環境に合わせて実行

 

GitHubにPushして自動デプロイ

実際にcircleciに設定した内容が動作するか、GitHubの各ブランチにPushして確認してみましょう。