← ClaudeAtlas

supabase-ci-migration-guardslisted

Use before writing or reviewing any migration that references Supabase-managed schemas — `auth.users`, `auth.uid()`, `storage.objects`, `storage.buckets`, `realtime.subscription`, `supabase_functions.*`, or any policy / function that depends on `auth.jwt()`. Auto-fire when a diff in `supabase/migrations/*.sql` matches the regex `(auth|storage|realtime)\.|to_regnamespace|create or replace function .* returns`. Also fire when the user says "fix the CI migration job" / "migration failed in CI" / "vanilla postgres errored on this migration" / "schema auth does not exist". Skip if the migration only touches the `public` schema with no Supabase-namespace references.
damson/hard-won-skills · ★ 1 · API & Backend · score 67
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