【JS】FirebaseのCIをGitHubActionsで作ろう
こんにちは!静的サイトホスティングはFirebase派のMizutani(@sirycity)です。(NetlifyでDNSが浸透せずにブログが3日間落ちたトラウマあり)
今回はGitHubActionsを用いたFirebaseのCIの作り方についてです。実際にこのブログで使ってる設定を抜粋して紹介するよー!
※多分もっといい方法があるので分かり次第追記していきます → 2021-01-21:追記しました
簡単な概要
静的サイトホスティングといえばFirebaseとNetlify、あとはGitHub PagesとかVercelあたりが有名ですね。しかしこの中でFirebaseにだけない機能があります。それはCI。
CIってのはざっくり言うとGitHubにPushするとビルドとかテストとか勝手にやってデプロイしてくれる機能のことね。このCIってのはJenkinsとかCircleCI、TravisCIとかが有名だけどすげー難しいんです(小学生並みの感想)。NetlifyとかにはCI機能が最初から付いてるからJenkinsとかいらないんだけどFirebaseにはCIがついてない。
ところが2019年、GitHubActionsっていうGitHubに組み込まれてるCIが誕生したんですね。Actionsは特に設定とかしなくてもGitHub使ってれば勝手に使えるんです。なので今までと比べて CIがめっちゃ簡単につくれる! つまり FirebaseにCIの機能を簡単に追加できる! ってわけです。というわけでActionsを使ってFirebaseにCIをくっつけていきましょう。
手順
Firebaseプロジェクトをつくる
まずはFirebaseのプロジェクトを作りましょう。中身は空っぽでいいよ。
Googleアカウントを作ったらFirebaseのトップページに行って『使ってみる』を押して後は説明通りに進めればOK。適当に作ってもあとで消せるし大丈夫!できたらFirebaseのプロジェクト一覧ページに移動しよう。ここにプロジェクト名とIDがのってれば完了です。IDはあとで使うよ。
プロジェクトIDを確認したらホスティングのページを開いてデフォルトのURLを確認しておこう。ホスティングのページはここ。
https://console.firebase.google.com/u/0/project/【プロジェクトID】/hosting/main
デフォルトのURLは末尾が .web.app みたいになってるURLです。最終的にはこのURLにデプロイすることになるよ!これもあとでデプロイ先のURLとして使うから覚えておいてね!
firebase-toolsを入れてCIトークン入手
npmは入ってるかな?↓ターミナルからこれ打ってみてバージョンが返って来ればOK。
npm -v
問題なければfirebase-toolsをインストールしよう!↓こんな感じ。グローバルかローカルにインストール。普通はグローバルだけどCI使うならローカルに!ローカルにしないと今回やるCI動かんし。今回はローカルでやる。
// global
npm i -g firebase-tools
// local
npm i -D firebase-tools
そしてら↓これを打ってCIトークンを入手。打つとブラウザが立ち上がりGoogleがログインを求めてきます。ログインが終わるとターミナルにCIトークンが吐き出されるのでメモしておこう。CIトークンは1//0abcde...
みたいな長ーい文字列ね。
// global
firebase login:ci
// local
npx firebase login:ci
GitHubに環境変数を設定
GitHubに環境変数書きます。環境変数を設定するページはこんな感じのURLになってるよ↓
https://github.com/【あなたの名前】/【リポジトリの名前】/settings/secrets
ここにCI_TOKENって名前でさっきメモったCIトークンの値を設定してね。これでGitHubは終わり。
必要なファイル作成
FirebaseとActionsに必要なファイルを作っていきます。まずは開発ディレクトリに移動しましょう。package.jsonとか置いてある場所ね。移動したらFirebaseの設定ファイル作る。
touch firebase.json
そしたらfirebase.jsonの中身をこんな感じに追記。
{
"hosting": [
{
"target": "target",
"public": "public",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"]
}
]
}
- “target”の欄は特に名前はなんでもいいよ。今回はとりあえず”target”にするね。後でActionsで使うよ。
- “public”の欄はあなたが使っているフレームワークのビルド後のindex.htmlが入っているディレクトリの名前。このブログで使ってるGatsby.jsの場合は”public”っていうディレクトリ名だからそのまんま”public”って名前を設定してるけど、フレームワークによって違うから注意してね。例えばNext.jsだと”out”、Nuxt.jsだと”dist”。
- “ignore”の欄はこのままコピペでいいよ:)
次にActionsのファイルを作っていくよ!ディレクトリ構成がちょっと複雑なので注意。ymlファイルは名前なんでもいいけどとりあえずci.yml
にしとくね。
mkdir .github
mkdir .github/workflows
touch .github/workflows/ci.yml
このci.ymlに以下を追記…と言いたいところだけどここがめっちゃ長い。とりあえず最低限これだけあれば動くって構成を紹介していきます。
CIを記述
ひたすらci.ymlに書いていく。
まずはCIの名前。適当に分かりやすい名前つける。
name: CI
GitHubでどんな操作をしたらCIが走るか?の条件設定。「mainにpushしたら」にしときます。
on:
push:
branches:
- main
ビルドする環境設定。基本↓をコピペでOK。ubuntuは最新版、nodeはLTSのv14にしとく。
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x]
ここからコマンド…ってのを宣言。
steps:
checkoutってのを書きます。Actionsのおまじないみたいなもんです。コピペでOK。
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
npmのパッケージをinstallする設定。npm installでもいいけど、npm ciにするとバージョンが厳密に固定されるのでこっち。
あと、lintとかtestとか入れるならここがいいかも。ESLintとかstylelintとかtscとかjestとか。
- name: install
run: npm ci
# Lintとかtestを入れるならこのタイミング
フレームワークのビルド。この辺のコマンドもフレームワークによって違うので注意。まあ大抵の場合npm run buildになってるけど、npxで直接実行してもok。npx gatsby build みたいな。
- name: build
run: npm run build
こっからfiebaseにデプロイしてく。次の4つの値をチェックしといてね!
- 上の方でGitHubに設定したCI_TOKEN
- 同じく上の方で使うって言ったプロジェクトID(FIREBASE_PROJECT_ID)
- firebase.jsonに書いた”target”の値
- 上で確認した末尾がweb.appで終わるデプロイ先のURL
あとはfirebase-toolsをインストールしといてね!↑の方でもやったけど。というわけでデプロイは3段階にわけて説明する。
1.まずはじめにfirebaseのプロジェクトIDとCIトークンを指定。 CIトークンでアカウントを特定して、プロジェクトIDでそのアカウントのどのプロジェクトを対象とするかを指定する感じ!
- name: firebase deploy
run: |
npx firebase use 【プロジェクトID】 --token ${{ secrets.CI_TOKEN }}
2.次にホスティング対象が書かれたfirebase.jsonとデプロイ先のURLを指定。 firebase.jsonにはホスティングの設定とかが書かれてるから必要で、デプロイ先のURLは1つのプロジェクト内のどのURLにデプロイするかを特定するために必要。 firebaseは1つのプロジェクトに複数URLを設定できたりするからね。
npx firebase target:apply hosting 【firebase.jsonの"target"】 【デプロイ先のURL】 --token ${{ secrets.CI_TOKEN }}
3.最後にデプロイ。
npx firebase deploy --only hosting:【firebase.jsonの"target"】 --token ${{ secrets.CI_TOKEN }}
おつかれ。ぜんぶひっくるめてこんな感じ↓になったかな?ほんとはテストとかキャッシュとかもしたいしtargetとかURLは環境変数にしたいけど、とりあえずこれで動くはず。
name: CI
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: install
run: npm ci
# Lintとかtestを入れるならこのタイミング
- name: build
run: npm run build
- name: firebase deploy
run: |
npx firebase use 【プロジェクトID】 --token ${{ secrets.CI_TOKEN }}
npx firebase target:apply hosting 【firebase.jsonの"target"】 【デプロイ先のURL】 --token ${{ secrets.CI_TOKEN }}
npx firebase deploy --only hosting:【firebase.jsonの"target"】 --token ${{ secrets.CI_TOKEN }}
デプロイ
普通にプロジェクトをGitHubにPushしよう。Actionsはファイルがあると勝手に始まるから今まで通りpushするだけでいいよ。
CIの進行状況は以下のようなURLで確認可能です。CIが動いているの見るの、楽しいよね!そうでもない?
https://github.com/【あなたの名前】/【リポジトリの名前】/actions
終わったらfirebaseのfoo.web.app
みたいなURLを確認して、ちゃんと上がっていれば完了!ちなみにCIがコケた場合は↑のURLでも分かるし、何も設定しなくてもGitHubに登録してあるメールアドレス宛てに通知が来るから安心だね。
さいごに
めんどい。これを自動でやってくれるNetlifyってすごいね…
ただ、CIを自分で作れるようになると本番環境とテスト環境を使い分けたりとかできるのでめっちゃ便利。標準で付いてくるCIはちょっとブラックボックスで怖いしね。あと、CIは最初に作っちゃえばかなり流用できるので、この際にCIチャレンジするのも良いんじゃないでしょうか?Firebaseすごいしな。以上。めっちゃ長文になっちゃったけど読んでくれてありがとう!またね。