O fluxo padrão

A maior parte do trabalho segue este caminho. Cada seta é uma ação humana, não automática:

[Local]  →  desenvolve, cria migration, valida
    ↓  git push, abre PR para dev
[simpe-ms-test]  →  quem mergeia em dev aplica migrations no QA cloud
    ↓  QA valida, abre PR dev → main
[simpe-ms-dev]  →  quem mergeia em main aplica migrations em produção

Cada uma dessas três etapas é manual e intencional. Não tem job de CI fazendo promoção automática — é responsabilidade de quem aprova o merge em cada nível.

Criando uma migration

No seu local, depois de subir o stack:

supabase migration new nome_curto_descritivo

Isso cria supabase/migrations/<timestamp>_nome.sql. Edite com o SQL que precisa. Para aplicar:

npm run db:reset

db:reset dropa o schema, reaplica todas as migrations e roda o seed. Demora uns 30 segundos. É a forma "nuclear", mas é a mais previsível — sempre te deixa em um estado conhecido.

Alternativa mais rápida (só aplica as pendentes, sem zerar dados):

supabase migration up

Use no dia a dia se quiser preservar dados que você inseriu para teste; use db:reset antes de abrir PR.

Regra absoluta

Nunca edite uma migration que já foi aplicada em simpe-ms-test ou simpe-ms-dev. Se precisar consertar algo, crie uma migration nova com timestamp posterior. Editar uma migration aplicada quebra o histórico do banco e força recuperação manual.

No seu local, antes de pushar, você pode editar livremente — o db:reset recria do zero.

Promovendo para simpe-ms-test

Quando seu PR é aprovado e mergeado em dev, alguém precisa aplicar as novas migrations e fazer deploy das edge functions no cloud de QA. Por convenção, quem aprova o merge é o responsável por isso.

supabase link --project-ref <ref-do-simpe-ms-test>
supabase db push
supabase functions deploy nome_da_funcao --no-verify-jwt

A CLI mostra o diff antes de aplicar. Confira. Se mudou alguma edge function, faça o deploy também — sem isso, a Vercel vai chamar uma function antiga que pode não bater com o schema novo.

Promovendo para produção

Quando o PR dev → main é aprovado, quem faz o merge precisa replicar tudo em simpe-ms-dev:

supabase link --project-ref <ref-do-simpe-ms-dev>
supabase db push
supabase functions deploy nome_da_funcao --no-verify-jwt

Confirme com supabase projects list que o relink foi para o projeto certo antes de rodar o push — é a única etapa onde uma confusão de projeto pode causar dano real.

Idealmente esse processo acontece junto do merge em main, para que o deploy automático da Vercel encontre o banco já atualizado.

Cenário especial — feature que pula a fila

Você tem duas features em desenvolvimento paralelo (chamemos de A e B), ambas com migrations. A está pronta para produção; B ainda não. Não dá para mergir A em dev porque B já está lá no meio, e a próxima promoção dev → main arrastaria as duas.

Cenário comum

Feature integrada

Branch a partir de dev, desenvolve, PR para dev. Quando estabilizar, dev → main. Todas as features de dev vão juntas.

Cenário especial

Feature independente

Branch a partir de main, desenvolve, PR direto para main. Pula a integração em dev — vai sozinha para produção.

A regra geral: a ordem em que migrations vão para produção é a ordem em que branches mergeiam em main. Quem mergeia em dev antes vai junto com tudo o que tiver lá. Quem mergeia em main direto vai sozinho.

Detalhe sobre conflitos

Se A e B mexem no mesmo arquivo (ex: a mesma tabela), pode dar conflito quando B for rebased contra main depois de A já estar lá. Resolva no rebase normalmente — o que importa é que as migrations não se misturaram acidentalmente, mesmo que o código TypeScript tenha conflitos a resolver.

Edge functions

Edge functions vivem em supabase/functions/<nome>/index.ts e compartilham supabase/deno.jsonc (imports, lints). São Deno, não Node.

Rodando localmente

supabase start já sobe um container de edge runtime que serve as functions automaticamente em http://127.0.0.1:54321/functions/v1/. Mudanças no código exigem restart do container ou usar:

supabase functions serve nome_da_funcao

Esse comando abre um watcher com hot reload. npm run dev:local já inclui ele.

Deploy

supabase functions deploy nome_da_funcao --no-verify-jwt

Para usar um import map específico:

supabase functions deploy nome_da_funcao --import-map supabase/deno.jsonc

Secrets

São por projeto (test e dev têm secrets separados):

supabase secrets list
supabase secrets set MINHA_VAR=valor
supabase secrets unset MINHA_VAR

No seu local, defina secrets em supabase/.env (não confundir com o .env da raiz do projeto).

Rollback e consertos

Algo que estava certo no local quebrou ao chegar em simpe-ms-test? A correção sempre vem em uma nova migration, não na edição da anterior:

  • Migration corretiva: o estado atual do banco tem um problema que pode ser corrigido com SQL adicional — ajustar constraint, popular coluna, renomear trigger. Crie migration new fix_descricao.
  • Down-migration: a mudança anterior precisa ser revertida completamente. Crie uma migration que desfaz (DROP TABLE, DROP COLUMN, etc.). Cuidado: dados podem ser perdidos.

O fluxo é o mesmo de sempre: testa local com db:reset, push em test, valida, replica em prod.