-
Notifications
You must be signed in to change notification settings - Fork 31
137 lines (122 loc) · 5.13 KB
/
Copy pathdeploy-firebase.yml
File metadata and controls
137 lines (122 loc) · 5.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
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, send/file-send
# readers and sweepers), Firestore security rules, Firestore indexes,
# and Cloud Storage rules. 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"
- "storage.rules"
- "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,storage"
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,storage', 'firestore:indexes')
run: |
npx --yes firebase-tools@latest deploy \
--only firestore:indexes \
${{ steps.project.outputs.flags }} \
--non-interactive --force
- name: Deploy Storage rules
if: contains(github.event.inputs.targets || 'functions,firestore:rules,firestore:indexes,storage', 'storage')
run: |
npx --yes firebase-tools@latest deploy \
--only storage \
${{ 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,storage', '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"