supabase-ci-migration-guardslisted
Install: claude install-skill damson/hard-won-skills
# Supabase-CI migration compatibility guards
CI runs migrations against vanilla Postgres (with bootstrapped `anon`/`authenticated`/`service_role`/`authenticator` roles but **no Supabase schemas**); production runs them against real Supabase. Any FK, policy, or function that references `auth.*` / `storage.*` / `realtime.*` blows up CI. The three failure modes:
- `ERROR: schema "auth" does not exist` — FK references `auth.users(id)`
- `ERROR: relation "storage.objects" does not exist` — RLS policy reads storage metadata
- `ERROR: cannot change return type of existing function` — `CREATE OR REPLACE FUNCTION` whose signature drifted
Each costs one fix commit + one CI cycle. The patterns below avoid all three.
## Procedure
### 1. Scan the migration
```bash
grep -nE '\b(auth|storage|realtime|supabase_functions)\.' supabase/migrations/<new>.sql
```
For every match, decide: does the referenced object exist in vanilla Postgres? If no, the migration needs a guard.
### 2. Guard FKs to `auth.users(id)` (and similar)
**Wrong** — fails in CI:
```sql
create table upload_jobs (
id uuid primary key default gen_random_uuid(),
uploader_id uuid references auth.users(id) on delete set null, -- ❌
...
);
```
**Right** — column unconstrained, FK bound conditionally at the bottom:
```sql
-- The FK to auth.users is added in a DO block so vanilla Postgres CI
-- (which has no `auth` schema) can apply the migration. Supabase
-- envs (prod + local dev) get the real FK.
create tab