Skip to content

Commit 826b237

Browse files
committed
Automate Firestore rules deploy and add production unknown-queue smoke checks
1 parent fbe4284 commit 826b237

File tree

5 files changed

+438
-17
lines changed

5 files changed

+438
-17
lines changed

.github/workflows/ci.yml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,65 @@ jobs:
3737

3838
- name: Run full verification
3939
run: npm run verify:local
40+
41+
detect-firestore-changes:
42+
name: detect-firestore-changes
43+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
44+
runs-on: ubuntu-latest
45+
outputs:
46+
firestore_changed: ${{ steps.filter.outputs.firestore_changed }}
47+
48+
steps:
49+
- name: Checkout
50+
uses: actions/checkout@v4
51+
52+
- name: Detect firestore-related changes
53+
id: filter
54+
uses: dorny/paths-filter@v3
55+
with:
56+
filters: |
57+
firestore_changed:
58+
- firestore.rules
59+
- firebase.json
60+
- firebase-applet-config.json
61+
- scripts/print-firestore-rules-target.mjs
62+
- scripts/smoke-firestore-unknown-queue.mjs
63+
64+
firestore-rules-deploy:
65+
name: firestore-rules-deploy
66+
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.detect-firestore-changes.outputs.firestore_changed == 'true'
67+
needs:
68+
- verify-local
69+
- detect-firestore-changes
70+
runs-on: ubuntu-latest
71+
timeout-minutes: 20
72+
73+
steps:
74+
- name: Checkout
75+
uses: actions/checkout@v4
76+
77+
- name: Setup Node.js
78+
uses: actions/setup-node@v4
79+
with:
80+
node-version: 20
81+
cache: npm
82+
83+
- name: Install dependencies
84+
run: npm ci
85+
86+
- name: Verify firestore deploy target
87+
run: npm run rules:target:check
88+
89+
- name: Deploy Firestore rules (production)
90+
env:
91+
FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
92+
run: npm run rules:deploy:prod
93+
94+
- name: Smoke test unknown ingredient queue access (production)
95+
env:
96+
SMOKE_OWNER_EMAIL: ${{ secrets.SMOKE_OWNER_EMAIL }}
97+
SMOKE_OWNER_PASSWORD: ${{ secrets.SMOKE_OWNER_PASSWORD }}
98+
SMOKE_OWNER_HOUSEHOLD_ID: ${{ secrets.SMOKE_OWNER_HOUSEHOLD_ID }}
99+
SMOKE_NON_MEMBER_EMAIL: ${{ secrets.SMOKE_NON_MEMBER_EMAIL }}
100+
SMOKE_NON_MEMBER_PASSWORD: ${{ secrets.SMOKE_NON_MEMBER_PASSWORD }}
101+
run: npm run rules:smoke:prod

README.md

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -210,15 +210,17 @@ These constraints are enforced in `firestore.rules` and validated by `test/rules
210210
- Confirm production Firebase Auth domain setup before release (Google provider and authorized domains)
211211

212212
### Production Firestore Rules Runbook
213-
1. Authenticate Firebase CLI:
214-
- `npx firebase login`
215-
2. Verify project/database deploy targets:
216-
- `npm run rules:target:check`
217-
3. Deploy production Firestore rules:
213+
1. Mainline path (default):
214+
- Merge to `main`; CI deploys `firestore.rules` automatically when Firestore files change.
215+
2. CI deploy preconditions:
216+
- `verify-local` must pass.
217+
- `npm run rules:target:check` must pass (project/database target integrity gate).
218+
3. Post-deploy smoke checks:
219+
- Owner smoke user must read `households/{householdId}/unknownIngredientQueue`.
220+
- Non-member smoke user must receive `PERMISSION_DENIED`.
221+
4. Emergency/manual deploy only:
218222
- `npm run rules:deploy:prod`
219-
4. Validate production owner view:
220-
- Sign in as owner and open the pantry/unknown queue section.
221-
- Confirm no `Unknown ingredient queue access denied` banner appears.
223+
- `npm run rules:smoke:prod`
222224
5. Optional deploy diagnostics:
223225
- `npm run rules:deploy:prod:dry`
224226

@@ -243,6 +245,11 @@ This project uses GitHub as the deployment source of truth.
243245
- CI command chain:
244246
- `npm ci`
245247
- `npm run verify:local`
248+
- `verify-local` includes `npm run rules:target:check`
249+
- `main` push additional automation:
250+
- Detect Firestore-related file changes.
251+
- Deploy Firestore rules automatically when changed.
252+
- Run production smoke test for owner-allow and non-member-deny unknown queue reads.
246253

247254
### Local push gate (Husky)
248255
- Husky install hook is configured via `npm run prepare`.
@@ -255,6 +262,13 @@ This project uses GitHub as the deployment source of truth.
255262
- Require status checks to pass before merging.
256263
- Add required status check: `verify-local`.
257264
- Require branches to be up to date before merging.
265+
- Add repository secrets for Firestore deploy/smoke workflow:
266+
- `FIREBASE_TOKEN`
267+
- `SMOKE_OWNER_EMAIL`
268+
- `SMOKE_OWNER_PASSWORD`
269+
- `SMOKE_OWNER_HOUSEHOLD_ID`
270+
- `SMOKE_NON_MEMBER_EMAIL`
271+
- `SMOKE_NON_MEMBER_PASSWORD`
258272

259273
### Required Vercel settings
260274
- Git repository connected to this GitHub repo.
@@ -275,10 +289,12 @@ This project uses GitHub as the deployment source of truth.
275289
### Firestore rules tests fail with Java/emulator error
276290
- Install Java 17+ and confirm `java -version` resolves correctly in shell.
277291

278-
### `Unknown ingredient queue access denied. Deploy latest Firestore rules and retry.`
279-
- Ensure Firebase CLI is authenticated: `npx firebase login`
280-
- Deploy rules to production (includes named Firestore DB target): `npm run rules:deploy:prod`
281-
- Retry owner view and confirm unknown queue loads.
292+
### `Unknown ingredient queue access denied... [build:<id>]`
293+
- Confirm the visible build id is the latest deployment.
294+
- Validate CI Firestore deploy and smoke test status on latest `main` run.
295+
- For emergency recovery, deploy + smoke manually:
296+
- `npm run rules:deploy:prod`
297+
- `npm run rules:smoke:prod`
282298

283299
### Google sign-in popup fails locally
284300
- Add `localhost` / `127.0.0.1` to Firebase Auth authorized domains.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@
1515
"rules:target:check": "node scripts/print-firestore-rules-target.mjs",
1616
"rules:deploy:prod": "npx firebase deploy --only firestore:rules --project gen-lang-client-0862152879",
1717
"rules:deploy:prod:dry": "npx firebase deploy --only firestore:rules --project gen-lang-client-0862152879 --debug",
18+
"rules:smoke:prod": "node scripts/smoke-firestore-unknown-queue.mjs",
1819
"e2e": "node test/e2e/run.mjs",
1920
"e2e:headed": "E2E_HEADLESS=false node test/e2e/run.mjs",
20-
"verify:local": "npm run lint && npm run unit:test && npm run build && npm run rules:test && npm run e2e",
21+
"verify:local": "npm run rules:target:check && npm run lint && npm run unit:test && npm run build && npm run rules:test && npm run e2e",
2122
"prepare": "husky"
2223
},
2324
"dependencies": {

0 commit comments

Comments
 (0)