From b62eaa460c6af89c08a8a48e29b51b70d9007c68 Mon Sep 17 00:00:00 2001 From: YasunoriMATSUOKA Date: Tue, 9 Jun 2026 22:24:20 +0900 Subject: [PATCH] ci(cd): migrate Firebase deploy to OIDC + Workload Identity Federation Replace the long-lived FIREBASE_TOKEN auth with keyless Workload Identity Federation. Both CD workflows now authenticate to Google Cloud via google-github-actions/auth (impersonating a per-project deploy service account) and let the Firebase CLI use ADC, so no long-lived secret is needed. - Add `id-token: write` permission for OIDC token retrieval - Add the auth step (pinned to a full commit SHA) before deploy - Drop `firebase use --token` / `firebase deploy --token`; deploy with `--project --non-interactive` and ADC - Read WIF_PROVIDER / DEPLOY_SERVICE_ACCOUNT / GCP_PROJECT_ID from per-environment GitHub Variables - Document the CD/WIF setup in CLAUDE.md Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/cd-firebase-mainnet.yml | 10 ++++++++-- .github/workflows/cd-firebase-testnet.yml | 10 ++++++++-- CLAUDE.md | 8 ++++++++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/.github/workflows/cd-firebase-mainnet.yml b/.github/workflows/cd-firebase-mainnet.yml index 3ca0d66..20ebd56 100644 --- a/.github/workflows/cd-firebase-mainnet.yml +++ b/.github/workflows/cd-firebase-mainnet.yml @@ -5,6 +5,7 @@ on: permissions: contents: read + id-token: write jobs: build: @@ -53,8 +54,13 @@ jobs: working-directory: ./functions - run: npm run build working-directory: ./functions - - run: npx firebase use mainnet --token=${{ secrets.FIREBASE_TOKEN }} - - run: npx firebase deploy --token=${{ secrets.FIREBASE_TOKEN }} --force + - name: Authenticate to Google Cloud via Workload Identity Federation + uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3.0.0 + with: + project_id: ${{ vars.GCP_PROJECT_ID }} + workload_identity_provider: ${{ vars.WIF_PROVIDER }} + service_account: ${{ vars.DEPLOY_SERVICE_ACCOUNT }} + - run: npx firebase deploy --project mainnet --non-interactive --force - name: Clear env file if: always() diff --git a/.github/workflows/cd-firebase-testnet.yml b/.github/workflows/cd-firebase-testnet.yml index 94cd158..abade73 100644 --- a/.github/workflows/cd-firebase-testnet.yml +++ b/.github/workflows/cd-firebase-testnet.yml @@ -8,6 +8,7 @@ on: permissions: contents: read + id-token: write jobs: build: @@ -58,8 +59,13 @@ jobs: working-directory: ./functions - run: npm run build working-directory: ./functions - - run: npx firebase use testnet --token=${{ secrets.FIREBASE_TOKEN }} - - run: npx firebase deploy --token=${{ secrets.FIREBASE_TOKEN }} --force + - name: Authenticate to Google Cloud via Workload Identity Federation + uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3.0.0 + with: + project_id: ${{ vars.GCP_PROJECT_ID }} + workload_identity_provider: ${{ vars.WIF_PROVIDER }} + service_account: ${{ vars.DEPLOY_SERVICE_ACCOUNT }} + - run: npx firebase deploy --project testnet --non-interactive --force - name: Clear env file if: always() diff --git a/CLAUDE.md b/CLAUDE.md index 8f3d83d..450c838 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -67,3 +67,11 @@ npm run preview # ビルド結果のプレビュー - `.github/workflows/ci-react.yml` — PR ごとに `npm audit` → `npm ci` → `npm run build` - `.github/workflows/ci-functions.yml` — 同上を `functions/` で実行 - いずれも Node 24 環境。コミット前に `npm run typecheck` / `npm run build` が通ることを確認する + +## CD(デプロイ) + +- `.github/workflows/cd-firebase-testnet.yml` — main への push / 手動実行で testnet(`nemtus-hackathon-test`)へデプロイ +- `.github/workflows/cd-firebase-mainnet.yml` — 手動実行(`workflow_dispatch`)で mainnet(`nemtus-hackathon`)へデプロイ +- **認証は OIDC + Workload Identity Federation(キーレス)**。`google-github-actions/auth` で GCP のデプロイ用サービスアカウントを impersonation し、firebase CLI は ADC(`GOOGLE_APPLICATION_CREDENTIALS`)経由でデプロイする。長期 `FIREBASE_TOKEN` は使わない +- GitHub Environment(`testnet` / `mainnet`)の Variables に `WIF_PROVIDER` / `DEPLOY_SERVICE_ACCOUNT` / `GCP_PROJECT_ID` を設定する。GCP 側の WIF プール・SA 設定手順は移行計画を参照 +- ワークフローの permissions に `id-token: write` が必須(OIDC トークン取得のため)