Skip to content

feat: changed to useflowvault.com #10

feat: changed to useflowvault.com

feat: changed to useflowvault.com #10

name: Deploy Firebase backend
# Vercel handles the Next.js frontend via its GitHub integration.
# This workflow covers what Vercel does NOT: the Firebase side of the
# stack — Cloud Functions (dead-man's-switch sweep), Firestore security
# rules, and Firestore indexes. It runs on every push to master plus a
# manual dispatch button.
#
# Required repository secrets:
# FIREBASE_SERVICE_ACCOUNT A service-account JSON with roles:
# - Cloud Functions Admin
# - Firebase Rules Admin
# - Service Account User
# - Cloud Datastore Index Admin (for indexes)
# - Artifact Registry Writer (first deploy only)
# Paste the whole JSON blob as the secret value.
#
# Required repository variables:
# FIREBASE_PROJECT_ID e.g. "flowvault-prod"
#
# Vercel env vars (NEXT_PUBLIC_*) do not belong here — they live in
# Vercel's own project settings.
on:
push:
branches: [master]
# Only redeploy when backend files actually change. Prevents wasting
# a deploy on a README-only or frontend-only commit.
paths:
- "functions/**"
- "firestore.rules"
- "firestore.indexes.json"
- "firebase.json"
- ".firebaserc"
- ".github/workflows/deploy-firebase.yml"
workflow_dispatch:
inputs:
targets:
description: "Comma-separated deploy targets"
required: false
default: "functions,firestore:rules,firestore:indexes"
concurrency:
group: deploy-firebase-${{ github.ref }}
cancel-in-progress: false
jobs:
deploy:
name: Deploy to Firebase
runs-on: ubuntu-latest
timeout-minutes: 20
environment:
name: production
url: https://console.firebase.google.com/project/${{ vars.FIREBASE_PROJECT_ID }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: functions/package-lock.json
- name: Install function dependencies
working-directory: functions
run: npm ci
- name: Build functions
working-directory: functions
run: npm run build
- name: Authenticate with Google Cloud
id: auth
run: |
echo '${{ secrets.FIREBASE_SERVICE_ACCOUNT }}' > "$RUNNER_TEMP/gcp-key.json"
echo "GOOGLE_APPLICATION_CREDENTIALS=$RUNNER_TEMP/gcp-key.json" >> "$GITHUB_ENV"
# Resolve the project-flag args once so every deploy step uses the same
# logic: prefer the Actions variable, fall back to .firebaserc default.
- name: Resolve project flags
id: project
env:
FIREBASE_PROJECT_ID: ${{ vars.FIREBASE_PROJECT_ID }}
run: |
if [ -n "$FIREBASE_PROJECT_ID" ]; then
echo "flags=--project $FIREBASE_PROJECT_ID" >> "$GITHUB_OUTPUT"
echo "Deploying to project (from vars): $FIREBASE_PROJECT_ID"
else
echo "flags=" >> "$GITHUB_OUTPUT"
echo "FIREBASE_PROJECT_ID var not set; relying on .firebaserc default alias"
fi
# Firestore rules are deployed FIRST and on their own, because they are
# the security-critical piece: if a later target (functions) fails, we
# still want the new rules live. A failing functions deploy must never
# leave users stuck on stale/default-deny rules.
- name: Deploy Firestore rules
if: contains(github.event.inputs.targets || 'functions,firestore:rules,firestore:indexes', 'firestore:rules')
run: |
npx --yes firebase-tools@latest deploy \
--only firestore:rules \
${{ steps.project.outputs.flags }} \
--non-interactive --force
- name: Deploy Firestore indexes
if: contains(github.event.inputs.targets || 'functions,firestore:rules,firestore:indexes', 'firestore:indexes')
run: |
npx --yes firebase-tools@latest deploy \
--only firestore:indexes \
${{ steps.project.outputs.flags }} \
--non-interactive --force
# Functions is last and allowed to fail without taking the whole workflow
# down, so the rules/indexes changes above still count as "shipped".
- name: Deploy Cloud Functions
if: contains(github.event.inputs.targets || 'functions,firestore:rules,firestore:indexes', 'functions')
continue-on-error: true
run: |
npx --yes firebase-tools@latest deploy \
--only functions \
${{ steps.project.outputs.flags }} \
--non-interactive --force
- name: Clean up credentials
if: always()
run: rm -f "$RUNNER_TEMP/gcp-key.json"