Two environments
Development and production are separate databases, separate storage and separate edge functions. Never assume a change you can see is live for customers, and never test a destructive action against production because "it is the same data".
How changes reach an environment
.github/workflows/deploy-supabase.yml applies database migrations and deploys all edge functions. It runs on pushes to the dev branch and can be dispatched manually. Because functions deploy as a set, a deploy triggered for one fix also publishes every other function change sitting on the branch — check what else is pending before dispatching.
Drift checking
.github/workflows/db-drift-check.yml runs daily and is read-only. It reports where the deployed schema no longer matches the migrations. Drift almost always means someone ran SQL by hand; resolve it by writing the migration that matches reality rather than by editing the database again.
Rules that keep this sane
- Schema changes go in migrations. Content (knowledge base articles, templates) goes in seed scripts, not migrations.
- Seed scripts are idempotent — they use fixed identifiers and upsert — so they can be re-run safely, but re-running a seed overwrites live edits made through the admin UI. Edit the seed, then apply it; do not edit live and hope.
- New environment configuration (
app_config, buckets, provider credentials) is not carried by the pipeline and must be set up deliberately.
Cache after a release
The web app invalidates cached data using an app version value. If a customer reports that a change "has not appeared", a hard refresh is the first thing to ask for — it is far more often stale cache than a failed deploy.