ci: deploy Firestore rules with a service account, not login:ci (#51)

The deploy-firestore-rules job has failed on every push because
FIREBASE_TOKEN was never set, so rule changes (e.g. aircraft/vessels for
node-26#9) never reached prod. Switch to a dedicated least-privilege
service account whose JSON key lives in FIREBASE_SA_KEY; login:ci tokens
are deprecated and carry their minter's full access. Key is written to
RUNNER_TEMP at 0600 and removed on exit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Logan Cusano
2026-09-27 12:46:33 -04:00
co-authored by Claude Opus 5.5
parent ddf13402d0
commit 5845fc5694
2 changed files with 20 additions and 20 deletions
+15 -13
View File
@@ -307,28 +307,30 @@ jobs:
- name: Deploy firestore rules and indexes
env:
FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
FIREBASE_SA_KEY: ${{ secrets.FIREBASE_SA_KEY }}
run: |
set -e
# server-26#51: this used to run over SSH on the deploy VM, gated
# on the VM having firebase-tools installed. It never did, so it
# silently warned-and-skipped on every single deploy for weeks.
# Running it here instead means the only prerequisite is a secret
# -- FIREBASE_TOKEN, from `firebase login:ci` -- rather than
# something installed by hand on a machine this pipeline doesn't
# otherwise touch. A missing token now fails this job LOUDLY
# (picked up by notify-failure) instead of a buried warning line
# nobody reads in the app deploy's logs.
if [ -z "$FIREBASE_TOKEN" ]; then
echo "FIREBASE_TOKEN secret is not set -- cannot deploy Firestore rules/indexes." >&2
echo "Generate one with 'firebase login:ci' and add it as a Gitea Actions secret." >&2
# Auth is a dedicated service account (drb-ci-firestore-deploy,
# roles: Firebase Rules Admin, Cloud Datastore Index Admin,
# Service Usage Consumer), its JSON key stored as the
# FIREBASE_SA_KEY secret. Not `firebase login:ci`: those tokens are
# deprecated and carry the full permissions of whoever minted them.
# A missing key fails this job LOUDLY (picked up by notify-failure).
if [ -z "$FIREBASE_SA_KEY" ]; then
echo "FIREBASE_SA_KEY secret is not set -- cannot deploy Firestore rules/indexes." >&2
echo "Add the drb-ci-firestore-deploy service account's JSON key as a Gitea Actions secret." >&2
exit 1
fi
export GOOGLE_APPLICATION_CREDENTIALS="$RUNNER_TEMP/firebase-sa.json"
trap 'rm -f "$GOOGLE_APPLICATION_CREDENTIALS"' EXIT
( umask 077 && printf '%s' "$FIREBASE_SA_KEY" > "$GOOGLE_APPLICATION_CREDENTIALS" )
npm install -g firebase-tools
cd infra/firestore
firebase deploy --only firestore:rules,firestore:indexes \
--project ${{ secrets.FIREBASE_PROJECT_ID }} \
--token "$FIREBASE_TOKEN" --non-interactive
--project ${{ secrets.FIREBASE_PROJECT_ID }} --non-interactive
notify-failure:
name: Report a failed deploy
@@ -371,7 +373,7 @@ jobs:
# failed before any deploy was attempted" text even when the app
# deployed fine and only the Firestore rules/indexes push failed.
if deploy_result != "failure" and rules_result == "failure":
detail = "App deploy succeeded; Firestore rules/indexes deploy FAILED (server-26#51). Rules may be stale — check FIREBASE_TOKEN and the job log."
detail = "App deploy succeeded; Firestore rules/indexes deploy FAILED (server-26#51). Rules may be stale — check the FIREBASE_SA_KEY secret and the job log."
# server-26#65: the old text here unconditionally claimed
# "production is still running the previous build" -- true only