@luanpdd/kit-mcp 1.30.2 → 1.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (347) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +168 -168
  3. package/gates/agent-no-recursive-dispatch.md +84 -82
  4. package/kit/COMANDOS.md +138 -138
  5. package/kit/README.md +76 -76
  6. package/kit/agents/advisor-researcher.md +107 -106
  7. package/kit/agents/ai-mutation-tester.md +1 -0
  8. package/kit/agents/assumptions-analyzer.md +108 -107
  9. package/kit/agents/audit-log-implementer.md +314 -313
  10. package/kit/agents/auditor-consistencia-isolamento.md +414 -413
  11. package/kit/agents/b2b-saas-architect.md +157 -156
  12. package/kit/agents/burn-rate-forecaster.md +1 -0
  13. package/kit/agents/cascading-failures-auditor.md +299 -298
  14. package/kit/agents/codebase-mapper.md +769 -768
  15. package/kit/agents/crm-pipeline-implementer.md +257 -256
  16. package/kit/agents/debugger.md +814 -813
  17. package/kit/agents/detector-tenant-quente.md +338 -337
  18. package/kit/agents/evolution-go-integrator.md +201 -200
  19. package/kit/agents/example-reviewer.md +22 -21
  20. package/kit/agents/executor.md +565 -564
  21. package/kit/agents/golden-signals-instrumenter.md +1 -0
  22. package/kit/agents/incident-investigator.md +1 -0
  23. package/kit/agents/integration-checker.md +201 -200
  24. package/kit/agents/invite-flow-implementer.md +190 -189
  25. package/kit/agents/legacy-characterizer.md +369 -368
  26. package/kit/agents/lgpd-compliance-auditor.md +296 -295
  27. package/kit/agents/load-shedding-instrumenter.md +1 -0
  28. package/kit/agents/multi-tenant-isolation-auditor.md +254 -253
  29. package/kit/agents/multi-tenant-rls-writer.md +341 -340
  30. package/kit/agents/nyquist-auditor.md +179 -178
  31. package/kit/agents/observability-coverage-auditor.md +316 -315
  32. package/kit/agents/observability-instrumenter.md +1 -0
  33. package/kit/agents/omm-auditor.md +1 -0
  34. package/kit/agents/org-onboarding-implementer.md +224 -223
  35. package/kit/agents/payload-capture-instrumenter.md +274 -273
  36. package/kit/agents/phase-researcher.md +697 -696
  37. package/kit/agents/plan-checker.md +273 -272
  38. package/kit/agents/planner.md +923 -922
  39. package/kit/agents/postmortem-writer.md +1 -0
  40. package/kit/agents/project-researcher.md +653 -652
  41. package/kit/agents/prr-conductor.md +1 -0
  42. package/kit/agents/refactor-safety-auditor.md +405 -404
  43. package/kit/agents/release-pipeline-auditor.md +1 -0
  44. package/kit/agents/research-synthesizer.md +246 -245
  45. package/kit/agents/roadmapper.md +678 -677
  46. package/kit/agents/schema-checker.md +1 -0
  47. package/kit/agents/seam-finder.md +360 -359
  48. package/kit/agents/shotgun-surgery-detector.md +350 -349
  49. package/kit/agents/slo-engineer.md +1 -0
  50. package/kit/agents/storytelling-analyst.md +1 -0
  51. package/kit/agents/supabase-architect.md +1 -0
  52. package/kit/agents/supabase-auth-bootstrapper.md +1 -0
  53. package/kit/agents/supabase-branching-architect.md +563 -562
  54. package/kit/agents/supabase-cicd-pipeline-implementer.md +778 -777
  55. package/kit/agents/supabase-column-privileges-writer.md +400 -399
  56. package/kit/agents/supabase-edge-fn-tester.md +2 -1
  57. package/kit/agents/supabase-edge-fn-writer.md +2 -1
  58. package/kit/agents/supabase-migration-writer.md +386 -385
  59. package/kit/agents/supabase-rbac-implementer.md +393 -392
  60. package/kit/agents/supabase-realtime-implementer.md +364 -363
  61. package/kit/agents/supabase-rls-hardener.md +522 -521
  62. package/kit/agents/supabase-rls-writer.md +324 -323
  63. package/kit/agents/supabase-roles-implementer.md +356 -355
  64. package/kit/agents/supabase-storage-implementer.md +1 -0
  65. package/kit/agents/super-admin-implementer.md +282 -281
  66. package/kit/agents/toil-auditor.md +1 -0
  67. package/kit/agents/ui-auditor.md +438 -437
  68. package/kit/agents/ui-checker.md +303 -302
  69. package/kit/agents/ui-researcher.md +356 -355
  70. package/kit/agents/user-profiler.md +176 -175
  71. package/kit/agents/validador-evolucao-schema.md +336 -335
  72. package/kit/agents/verifier.md +729 -728
  73. package/kit/commands/adicionar-backlog.md +75 -75
  74. package/kit/commands/adicionar-fase.md +42 -42
  75. package/kit/commands/adicionar-tarefa.md +45 -45
  76. package/kit/commands/adicionar-testes.md +41 -41
  77. package/kit/commands/ajuda.md +21 -21
  78. package/kit/commands/atualizar.md +37 -37
  79. package/kit/commands/auditar-cascading.md +111 -111
  80. package/kit/commands/auditar-marco.md +179 -179
  81. package/kit/commands/auditar-observabilidade-cobertura.md +183 -183
  82. package/kit/commands/auditar-refactor.md +219 -219
  83. package/kit/commands/auditar-release.md +109 -109
  84. package/kit/commands/auditar-uat.md +23 -23
  85. package/kit/commands/autonomo.md +40 -40
  86. package/kit/commands/branch-pr.md +24 -24
  87. package/kit/commands/burn-rate-status.md +408 -408
  88. package/kit/commands/capturar-payloads.md +193 -193
  89. package/kit/commands/caracterizar.md +212 -212
  90. package/kit/commands/concluir-marco.md +247 -247
  91. package/kit/commands/configuracoes.md +36 -36
  92. package/kit/commands/dados-distribuidos.md +188 -188
  93. package/kit/commands/definir-perfil.md +10 -10
  94. package/kit/commands/depurar.md +190 -190
  95. package/kit/commands/detectar-duplicacao.md +197 -197
  96. package/kit/commands/discutir-fase.md +131 -131
  97. package/kit/commands/encontrar-seams.md +136 -136
  98. package/kit/commands/entrar-discord.md +17 -17
  99. package/kit/commands/estatisticas.md +18 -18
  100. package/kit/commands/example-greeting.md +33 -33
  101. package/kit/commands/executar-fase.md +58 -58
  102. package/kit/commands/expresso.md +56 -56
  103. package/kit/commands/fase-ui.md +34 -34
  104. package/kit/commands/fazer.md +57 -57
  105. package/kit/commands/fio.md +125 -125
  106. package/kit/commands/fluxos-trabalho.md +64 -64
  107. package/kit/commands/forense.md +176 -176
  108. package/kit/commands/gerenciador.md +38 -38
  109. package/kit/commands/inserir-fase.md +31 -31
  110. package/kit/commands/legacy.md +263 -263
  111. package/kit/commands/limpeza.md +17 -17
  112. package/kit/commands/listar-hipoteses-fase.md +45 -45
  113. package/kit/commands/listar-workspaces.md +18 -18
  114. package/kit/commands/load-shedding.md +117 -117
  115. package/kit/commands/mapear-codebase.md +70 -70
  116. package/kit/commands/multi-tenant.md +163 -163
  117. package/kit/commands/nota.md +33 -33
  118. package/kit/commands/novo-marco.md +43 -43
  119. package/kit/commands/novo-projeto.md +41 -41
  120. package/kit/commands/novo-workspace.md +43 -43
  121. package/kit/commands/pausar-trabalho.md +37 -37
  122. package/kit/commands/perfil-usuario.md +45 -45
  123. package/kit/commands/pesquisar-fase.md +195 -195
  124. package/kit/commands/planejar-fase.md +67 -67
  125. package/kit/commands/planejar-lacunas.md +33 -33
  126. package/kit/commands/plantar-ideia.md +25 -25
  127. package/kit/commands/progresso.md +24 -24
  128. package/kit/commands/proximo.md +30 -30
  129. package/kit/commands/publicar.md +490 -490
  130. package/kit/commands/rapido.md +35 -35
  131. package/kit/commands/reaplicar-patches.md +124 -124
  132. package/kit/commands/refactor-seguro.md +321 -321
  133. package/kit/commands/relatorio-sessao.md +19 -19
  134. package/kit/commands/remover-fase.md +31 -31
  135. package/kit/commands/remover-workspace.md +26 -26
  136. package/kit/commands/resumo-marco.md +50 -50
  137. package/kit/commands/retomar-trabalho.md +40 -40
  138. package/kit/commands/revisar-backlog.md +60 -60
  139. package/kit/commands/revisar-ui.md +32 -32
  140. package/kit/commands/revisar.md +37 -37
  141. package/kit/commands/saude.md +21 -21
  142. package/kit/commands/setup-notion.md +93 -93
  143. package/kit/commands/storytelling.md +179 -179
  144. package/kit/commands/sync-main.md +68 -68
  145. package/kit/commands/validar-fase.md +35 -35
  146. package/kit/commands/verificar-tarefas.md +44 -44
  147. package/kit/commands/verificar-trabalho.md +64 -64
  148. package/kit/file-manifest.json +82 -81
  149. package/kit/framework/bin/lib/commands.cjs +959 -959
  150. package/kit/framework/bin/lib/config.cjs +442 -442
  151. package/kit/framework/bin/lib/core.cjs +1230 -1230
  152. package/kit/framework/bin/lib/frontmatter.cjs +336 -336
  153. package/kit/framework/bin/lib/init.cjs +1442 -1442
  154. package/kit/framework/bin/lib/milestone.cjs +252 -252
  155. package/kit/framework/bin/lib/model-profiles.cjs +68 -68
  156. package/kit/framework/bin/lib/phase.cjs +888 -888
  157. package/kit/framework/bin/lib/profile-output.cjs +952 -952
  158. package/kit/framework/bin/lib/profile-pipeline.cjs +539 -539
  159. package/kit/framework/bin/lib/roadmap.cjs +329 -329
  160. package/kit/framework/bin/lib/security.cjs +382 -382
  161. package/kit/framework/bin/lib/state.cjs +1031 -1031
  162. package/kit/framework/bin/lib/template.cjs +222 -222
  163. package/kit/framework/bin/lib/uat.cjs +282 -282
  164. package/kit/framework/bin/lib/verify.cjs +888 -888
  165. package/kit/framework/bin/lib/workstream.cjs +491 -491
  166. package/kit/framework/bin/tools.cjs +918 -918
  167. package/kit/framework/commands/workstreams.md +63 -63
  168. package/kit/framework/references/checkpoints.md +778 -778
  169. package/kit/framework/references/continuation-format.md +249 -249
  170. package/kit/framework/references/decimal-phase-calculation.md +64 -64
  171. package/kit/framework/references/git-integration.md +295 -295
  172. package/kit/framework/references/git-planning-commit.md +38 -38
  173. package/kit/framework/references/model-profile-resolution.md +36 -36
  174. package/kit/framework/references/model-profiles.md +139 -139
  175. package/kit/framework/references/phase-argument-parsing.md +61 -61
  176. package/kit/framework/references/planning-config.md +202 -202
  177. package/kit/framework/references/questioning.md +162 -162
  178. package/kit/framework/references/tdd.md +263 -263
  179. package/kit/framework/references/ui-brand.md +160 -160
  180. package/kit/framework/references/user-profiling.md +657 -657
  181. package/kit/framework/references/verification-patterns.md +612 -612
  182. package/kit/framework/references/workstream-flag.md +58 -58
  183. package/kit/framework/templates/DEBUG.md +164 -164
  184. package/kit/framework/templates/UAT.md +265 -265
  185. package/kit/framework/templates/UI-SPEC.md +100 -100
  186. package/kit/framework/templates/VALIDATION.md +76 -76
  187. package/kit/framework/templates/claude-md.md +122 -122
  188. package/kit/framework/templates/codebase/architecture.md +185 -185
  189. package/kit/framework/templates/codebase/concerns.md +205 -205
  190. package/kit/framework/templates/codebase/conventions.md +204 -204
  191. package/kit/framework/templates/codebase/integrations.md +192 -192
  192. package/kit/framework/templates/codebase/stack.md +158 -158
  193. package/kit/framework/templates/codebase/structure.md +199 -199
  194. package/kit/framework/templates/codebase/testing.md +301 -301
  195. package/kit/framework/templates/config.json +44 -44
  196. package/kit/framework/templates/context.md +352 -352
  197. package/kit/framework/templates/continue-here.md +78 -78
  198. package/kit/framework/templates/copilot-instructions.md +7 -7
  199. package/kit/framework/templates/debug-subagent-prompt.md +91 -91
  200. package/kit/framework/templates/dev-preferences.md +20 -20
  201. package/kit/framework/templates/discovery.md +146 -146
  202. package/kit/framework/templates/discussion-log.md +63 -63
  203. package/kit/framework/templates/milestone-archive.md +123 -123
  204. package/kit/framework/templates/milestone.md +115 -115
  205. package/kit/framework/templates/phase-prompt.md +610 -610
  206. package/kit/framework/templates/planner-subagent-prompt.md +117 -117
  207. package/kit/framework/templates/project.md +186 -186
  208. package/kit/framework/templates/requirements.md +231 -231
  209. package/kit/framework/templates/research-project/ARCHITECTURE.md +204 -204
  210. package/kit/framework/templates/research-project/FEATURES.md +147 -147
  211. package/kit/framework/templates/research-project/PITFALLS.md +200 -200
  212. package/kit/framework/templates/research-project/STACK.md +120 -120
  213. package/kit/framework/templates/research-project/SUMMARY.md +170 -170
  214. package/kit/framework/templates/research.md +419 -419
  215. package/kit/framework/templates/retrospective.md +54 -54
  216. package/kit/framework/templates/roadmap.md +202 -202
  217. package/kit/framework/templates/state.md +176 -176
  218. package/kit/framework/templates/summary-complex.md +59 -59
  219. package/kit/framework/templates/summary-minimal.md +41 -41
  220. package/kit/framework/templates/summary-standard.md +48 -48
  221. package/kit/framework/templates/summary.md +209 -209
  222. package/kit/framework/templates/user-profile.md +146 -146
  223. package/kit/framework/templates/user-setup.md +256 -256
  224. package/kit/framework/templates/verification-report.md +258 -258
  225. package/kit/framework/workflows/add-phase.md +112 -112
  226. package/kit/framework/workflows/add-tests.md +351 -351
  227. package/kit/framework/workflows/add-todo.md +158 -158
  228. package/kit/framework/workflows/audit-milestone.md +340 -340
  229. package/kit/framework/workflows/audit-uat.md +109 -109
  230. package/kit/framework/workflows/autonomous.md +891 -891
  231. package/kit/framework/workflows/check-todos.md +177 -177
  232. package/kit/framework/workflows/cleanup.md +152 -152
  233. package/kit/framework/workflows/complete-milestone.md +696 -696
  234. package/kit/framework/workflows/diagnose-issues.md +231 -231
  235. package/kit/framework/workflows/discovery-phase.md +289 -289
  236. package/kit/framework/workflows/discuss-phase-assumptions.md +653 -653
  237. package/kit/framework/workflows/discuss-phase.md +784 -784
  238. package/kit/framework/workflows/do.md +104 -104
  239. package/kit/framework/workflows/execute-phase.md +838 -838
  240. package/kit/framework/workflows/execute-plan.md +510 -510
  241. package/kit/framework/workflows/fast.md +102 -102
  242. package/kit/framework/workflows/forensics.md +265 -265
  243. package/kit/framework/workflows/health.md +181 -181
  244. package/kit/framework/workflows/help.md +619 -619
  245. package/kit/framework/workflows/insert-phase.md +130 -130
  246. package/kit/framework/workflows/list-phase-assumptions.md +178 -178
  247. package/kit/framework/workflows/list-workspaces.md +56 -56
  248. package/kit/framework/workflows/manager.md +362 -362
  249. package/kit/framework/workflows/map-codebase.md +377 -377
  250. package/kit/framework/workflows/milestone-summary.md +223 -223
  251. package/kit/framework/workflows/new-milestone.md +486 -486
  252. package/kit/framework/workflows/new-project.md +1159 -1159
  253. package/kit/framework/workflows/new-workspace.md +237 -237
  254. package/kit/framework/workflows/next.md +97 -97
  255. package/kit/framework/workflows/node-repair.md +92 -92
  256. package/kit/framework/workflows/note.md +156 -156
  257. package/kit/framework/workflows/pause-work.md +176 -176
  258. package/kit/framework/workflows/plan-milestone-gaps.md +273 -273
  259. package/kit/framework/workflows/plan-phase.md +765 -765
  260. package/kit/framework/workflows/plant-seed.md +169 -169
  261. package/kit/framework/workflows/pr-branch.md +129 -129
  262. package/kit/framework/workflows/profile-user.md +450 -450
  263. package/kit/framework/workflows/progress.md +507 -507
  264. package/kit/framework/workflows/quick.md +757 -757
  265. package/kit/framework/workflows/remove-phase.md +155 -155
  266. package/kit/framework/workflows/remove-workspace.md +90 -90
  267. package/kit/framework/workflows/research-phase.md +82 -82
  268. package/kit/framework/workflows/resume-project.md +326 -326
  269. package/kit/framework/workflows/review.md +228 -228
  270. package/kit/framework/workflows/session-report.md +146 -146
  271. package/kit/framework/workflows/settings.md +283 -283
  272. package/kit/framework/workflows/ship.md +228 -228
  273. package/kit/framework/workflows/stats.md +60 -60
  274. package/kit/framework/workflows/transition.md +671 -671
  275. package/kit/framework/workflows/ui-phase.md +302 -302
  276. package/kit/framework/workflows/ui-review.md +165 -165
  277. package/kit/framework/workflows/update.md +323 -323
  278. package/kit/framework/workflows/validate-phase.md +174 -174
  279. package/kit/framework/workflows/verify-phase.md +252 -252
  280. package/kit/framework/workflows/verify-work.md +637 -637
  281. package/kit/hooks/check-update.js +118 -118
  282. package/kit/hooks/context-monitor.js +163 -163
  283. package/kit/hooks/kit-attribution-reminder.cjs +29 -50
  284. package/kit/hooks/kit-router.cjs +137 -0
  285. package/kit/hooks/prompt-guard.js +103 -103
  286. package/kit/hooks/statusline.js +125 -125
  287. package/kit/hooks/workflow-guard.js +101 -101
  288. package/kit/settings.json +45 -45
  289. package/kit/skills/ai-prompt-characterization/SKILL.md +335 -335
  290. package/kit/skills/armadilhas-sistemas-distribuidos/SKILL.md +447 -447
  291. package/kit/skills/audit-log-multi-tenant/SKILL.md +340 -340
  292. package/kit/skills/b2b-saas-architecture/SKILL.md +300 -300
  293. package/kit/skills/consistencia-leitura-replica/SKILL.md +385 -385
  294. package/kit/skills/crm-lead-pipeline-patterns/SKILL.md +343 -343
  295. package/kit/skills/escolha-modelo-consistencia/SKILL.md +494 -494
  296. package/kit/skills/evolucao-schema-compativel/SKILL.md +448 -448
  297. package/kit/skills/evolution-go-whatsapp-integration/SKILL.md +322 -322
  298. package/kit/skills/example-skill/SKILL.md +42 -42
  299. package/kit/skills/legacy-api-only-applications/SKILL.md +358 -358
  300. package/kit/skills/legacy-characterization-tests/SKILL.md +330 -330
  301. package/kit/skills/legacy-effect-analysis/SKILL.md +331 -331
  302. package/kit/skills/legacy-extract-class/SKILL.md +203 -203
  303. package/kit/skills/legacy-programming-by-difference/SKILL.md +252 -252
  304. package/kit/skills/legacy-seams-and-test-harness/SKILL.md +460 -460
  305. package/kit/skills/legacy-shotgun-surgery/SKILL.md +286 -286
  306. package/kit/skills/legacy-sprout-wrap-techniques/SKILL.md +434 -434
  307. package/kit/skills/legacy-storytelling-naked-crc/SKILL.md +270 -270
  308. package/kit/skills/lgpd-multi-tenant-compliance/SKILL.md +340 -340
  309. package/kit/skills/member-invite-flow/SKILL.md +305 -305
  310. package/kit/skills/member-management-react-shadcn/SKILL.md +328 -328
  311. package/kit/skills/multi-tenant-performance-scaling/SKILL.md +316 -316
  312. package/kit/skills/multi-tenant-rls-hierarchy/SKILL.md +342 -342
  313. package/kit/skills/org-onboarding-flow/SKILL.md +257 -257
  314. package/kit/skills/org-switcher-react-pattern/SKILL.md +349 -349
  315. package/kit/skills/permission-gate-react-pattern/SKILL.md +271 -271
  316. package/kit/skills/postgres-isolamento-concorrencia/SKILL.md +552 -552
  317. package/kit/skills/pre-refactor-characterization/SKILL.md +421 -421
  318. package/kit/skills/rbac-permissions-matrix-supabase/SKILL.md +338 -338
  319. package/kit/skills/streams-eventos-cdc/SKILL.md +711 -711
  320. package/kit/skills/supabase-branching-workflow/SKILL.md +544 -544
  321. package/kit/skills/supabase-ci-cd-github-actions/SKILL.md +880 -880
  322. package/kit/skills/supabase-column-level-security/SKILL.md +426 -426
  323. package/kit/skills/supabase-config-toml-remotes/SKILL.md +807 -807
  324. package/kit/skills/supabase-custom-claims-rbac/SKILL.md +472 -472
  325. package/kit/skills/supabase-edge-functions/SKILL.md +1 -1
  326. package/kit/skills/supabase-edge-functions-auth/SKILL.md +1 -1
  327. package/kit/skills/supabase-edge-functions-limits/SKILL.md +1 -1
  328. package/kit/skills/supabase-edge-functions-mcp-server/SKILL.md +1 -1
  329. package/kit/skills/supabase-edge-functions-testing/SKILL.md +1 -1
  330. package/kit/skills/supabase-edge-runtime-builtins/SKILL.md +1 -1
  331. package/kit/skills/supabase-migration-repair/SKILL.md +823 -823
  332. package/kit/skills/supabase-migrations/SKILL.md +297 -297
  333. package/kit/skills/supabase-pgtap-testing/SKILL.md +1053 -1053
  334. package/kit/skills/supabase-postgres-roles/SKILL.md +392 -392
  335. package/kit/skills/supabase-realtime/SKILL.md +460 -460
  336. package/kit/skills/supabase-rls-defense-in-depth/SKILL.md +418 -418
  337. package/kit/skills/supabase-rls-policies/SKILL.md +635 -635
  338. package/kit/skills/super-admin-platform-pattern/SKILL.md +326 -326
  339. package/kit/skills/tenant-quente-mitigacao/SKILL.md +605 -605
  340. package/kit/skills/whatsapp-conversation-state-machine/SKILL.md +287 -287
  341. package/package.json +1 -1
  342. package/src/core/kit.js +216 -216
  343. package/src/core/reflect.js +247 -247
  344. package/src/core/reverse-sync.js +372 -372
  345. package/src/core/sync.js +437 -418
  346. package/src/core/watch.js +121 -121
  347. package/src/mcp-server/index.js +794 -746
@@ -1,880 +1,880 @@
1
- ---
2
- name: supabase-ci-cd-github-actions
3
- description: Use ao automatizar Supabase via GitHub Actions — 8 workflows canônicos da doc oficial (ci.yml, staging.yml, production.yml, generate-types.yml, database-tests.yml, functions-tests.yml, backup.
4
- ---
5
-
6
- # Supabase — CI/CD GitHub Actions
7
-
8
- ## Quando usar
9
-
10
- Esta skill cobre **8 workflows GitHub Actions canônicos** da doc oficial Supabase para automatizar lifecycle do projeto — validação em PR, deploy para staging/production, generação de types TypeScript, testes pgTAP + Deno, backup periódico, e propagação de failure check.
11
-
12
- Trigger phrases:
13
-
14
- - "CI Supabase GitHub Actions", "workflow Supabase CI"
15
- - "deploy Supabase staging", "deploy Supabase production"
16
- - "ci.yml Supabase", "staging.yml Supabase", "production.yml Supabase"
17
- - "generate-types.yml Supabase", "schema.gen.ts CI"
18
- - "database-tests.yml Supabase", "supabase test db CI"
19
- - "functions-tests.yml Supabase", "deno test --allow-all CI"
20
- - "backup.yml Supabase", "supabase db dump cron", "automated backup Supabase"
21
- - "notify-failure.yaml Supabase", "fountainhead/action-wait-for-check"
22
- - "Never backup your data to a public repository"
23
- - "supabase secrets set CI", "supabase link --project-ref CI"
24
-
25
- **Use APENAS para:**
26
-
27
- - Validar migrations + schema declarativo em PR (gate antes do merge)
28
- - Automatizar deploy para staging (branch develop) e production (branch main)
29
- - Verificar que `schema.gen.ts` (types TypeScript) está committed e up-to-date
30
- - Rodar testes pgTAP (`supabase test db`) + testes Deno (`deno test --allow-all`) em CI
31
- - Backup periódico do schema/data/roles via cron midnight em repo **PRIVADO**
32
- - Propagar falha do check "Supabase Preview" para o status do PR
33
-
34
- **NÃO use para:**
35
-
36
- - Substituir Supabase Branching (cross-ref skill `supabase-branching-workflow` Phase 149) — branching é gerenciado via Supabase Dashboard ou GitHub Integration (não GitHub Actions workflow customizado)
37
- - Backup de dados sensíveis em **repositório público** — sempre repositório **privado** com criptografia adicional se PII (cross-ref Anti-pattern 1)
38
- - Bypass de migration history — `db push` deve respeitar `supabase_migrations.schema_migrations` (cross-ref Anti-pattern 2)
39
- - `db push` concorrente de máquinas diferentes — race condition pode corromper migration history (cross-ref Anti-pattern 3)
40
-
41
- ## Princípio canônico
42
-
43
- Quatro princípios canônicos:
44
-
45
- 1. **CI/CD shift-left.** Cada PR valida migrations + types + tests **antes** do merge — sem surpresas em produção. Gate canônico = required status check enforced via branch protection rules.
46
-
47
- 2. **Cada PR gera preview branch isolado.** Workflows GitHub Actions são complementares ao Supabase Branching (cross-ref skill `supabase-branching-workflow` Phase 149) — branching gera o branch DB; GitHub Actions valida o código que define migrations e Edge Functions.
48
-
49
- 3. **Required check enforced.** Branch protection rule "Require status checks to pass before merging" + selecionar workflows críticos (CI-01 ci, CI-04 generate-types, CI-08 notify-failure) — sem ✓ verde, sem merge para `main`.
50
-
51
- 4. **3-dump backup separados (CI-07).** Roles + Schema + Data dumps em arquivos SEPARADOS — isolation de concerns:
52
- - `roles.sql` (--role-only) pode ser revisado independente
53
- - `schema.sql` cabe em git diff legível
54
- - `data.sql` (--data-only --use-copy) gera arquivo grande mas restaurável independente
55
-
56
- ### Distinção canônica vs Supabase Branching
57
-
58
- | | Supabase Branching | GitHub Actions workflows |
59
- |---|---|---|
60
- | Gerencia | Branch DB Postgres + Edge Functions config | Código (migrations, types, tests) |
61
- | Trigger | PR webhook (Branching) | PR events (workflows) |
62
- | Source of truth | Supabase Dashboard config | `.github/workflows/*.yml` versionado |
63
- | Validação | Deploy DAG 7 steps (cross-ref Phase 149 Pattern 2) | Type-check, pgTAP, Deno tests, db push |
64
- | Cobrança | Branching Compute Hours (fora Spend Cap) | GitHub Actions minutes (free 2k/mês) |
65
-
66
- Os dois são **complementares** — workflows GitHub Actions validam o **código** que vai para o branch DB; Branching gerencia o **ambiente** onde o código roda.
67
-
68
- ## Secrets GitHub Actions necessários
69
-
70
- Antes de adotar qualquer workflow desta skill, configurar os secrets no repositório GitHub:
71
-
72
- **Settings → Secrets and variables → Actions → New repository secret**
73
-
74
- | Secret | Origem | Workflows que usam | Caso de uso |
75
- |--------|--------|---------------------|-------------|
76
- | `SUPABASE_ACCESS_TOKEN` | Personal access token (Dashboard → Account → Access Tokens) | staging.yml, production.yml | Autenticação do CLI Supabase em GitHub Actions runner |
77
- | `STAGING_DB_PASSWORD` | Dashboard → Project Settings → Database (staging project) | staging.yml | Password do `postgres` role no staging — usado por `supabase link` |
78
- | `STAGING_PROJECT_ID` | Dashboard → Project Settings → General → Reference ID (staging project) | staging.yml | Project reference do staging — usado por `supabase link --project-ref` |
79
- | `PRODUCTION_DB_PASSWORD` | Dashboard → Project Settings → Database (production project) | production.yml | Password do `postgres` role no production |
80
- | `PRODUCTION_PROJECT_ID` | Dashboard → Project Settings → General → Reference ID (production project) | production.yml | Project reference do production |
81
- | `SUPABASE_DB_URL` | Connection string do production (`postgresql://postgres:pwd@host/db`) | backup.yml | URL completa para `supabase db dump --db-url` |
82
-
83
- ### Caveat — `SUPABASE_ACCESS_TOKEN` é per-user
84
-
85
- Personal access tokens são vinculados ao **usuário** que os criou — se este usuário sair da organização, o token fica órfão e workflows quebram silenciosamente.
86
-
87
- **Mitigação canônica:** criar token vinculado a uma **service account** dedicada da empresa (ex: `ci@company.com`) em vez de conta pessoal do dev.
88
-
89
- ### Caveat — Rotacionar passwords periodicamente
90
-
91
- `PRODUCTION_DB_PASSWORD` e `STAGING_DB_PASSWORD` devem ser rotacionados a cada 90 dias (best practice). Após rotação no Dashboard, atualizar o secret em GitHub Actions — workflows quebram silenciosamente se o secret estiver stale.
92
-
93
- ### Caveat — `SUPABASE_DB_URL` contém password — encrypted by default
94
-
95
- GitHub Actions encripta secrets automaticamente em rest e nos logs (mascaramento). NUNCA ecoar o secret em `run:` step — mesmo mascarado, pode vazar em error logs ou crash dumps.
96
-
97
- ## Pattern 1: `ci.yml` — validation on pull request (CI-01)
98
-
99
- Workflow canônico que valida migrations + types em todo PR aberto:
100
-
101
- ```yaml
102
- name: CI
103
- on:
104
- pull_request:
105
- workflow_dispatch:
106
- jobs:
107
- test:
108
- runs-on: ubuntu-latest
109
- steps:
110
- - uses: actions/checkout@v4
111
- - uses: supabase/setup-cli@v1
112
- with:
113
- version: latest
114
- - name: Start Supabase local development setup
115
- run: supabase db start
116
- - name: Verify generated types are checked in
117
- run: |
118
- supabase gen types typescript --local > types.gen.ts
119
- if ! git diff --ignore-space-at-eol --exit-code --quiet types.gen.ts; then
120
- echo "Detected uncommitted changes after build. See status below:"
121
- git diff
122
- exit 1
123
- fi
124
- ```
125
-
126
- ### Explicação line-by-line
127
-
128
- - **`on: pull_request`** — trigger automático em todo PR aberto/atualizado
129
- - **`workflow_dispatch`** — permite re-run manual via Actions tab (útil para debug)
130
- - **`actions/checkout@v4`** — clona o repo no runner; v4 é a versão canônica atual (v3 ainda funciona mas sem features recentes)
131
- - **`supabase/setup-cli@v1`** — instala CLI Supabase no runner (Docker layer cached); `version: latest` pega última release estável
132
- - **`supabase db start`** — sobe instância Postgres + Auth + Realtime local via Docker
133
- - **`supabase gen types typescript --local`** — gera tipos TypeScript a partir do schema do DB local (que aplicou as migrations no `db start`)
134
- - **`git diff --ignore-space-at-eol --exit-code --quiet types.gen.ts`** — compara `types.gen.ts` gerado vs versionado em git; se diff existir, falha com exit 1
135
-
136
- ### Caveats canônicos
137
-
138
- - **`--ignore-space-at-eol`** previne false positives causados por diferenças LF vs CRLF entre runner Linux e dev Windows
139
- - **`--exit-code`** força exit 1 se diff (default `git diff` retorna 0 mesmo com diff)
140
- - **`--quiet`** suprime output redundante (já temos `echo` + `git diff` manuais)
141
- - O workflow só falha se `types.gen.ts` está **stale** — dev deve `supabase gen types typescript --local > types.gen.ts && git add types.gen.ts && git commit` localmente antes do PR
142
-
143
- ### Por que validar types committed
144
-
145
- Consumer projetos TypeScript (clientes do projeto Supabase) **importam** `types.gen.ts` para type-safety em queries (`createClient<Database>()`). Se types estão stale:
146
-
147
- - Compilação consumer falha silenciosamente em produção
148
- - Type assertions ficam erradas (campo `created_at` ainda `string`, mas DB já é `timestamp`)
149
- - Refactor downstream quebra sem warning
150
-
151
- Required check `CI / test` deve ser obrigatório em branch protection rules para `main`.
152
-
153
- ## Pattern 2: `staging.yml` — deploy migrations to staging (CI-02)
154
-
155
- Workflow para deploy automático de migrations ao staging Supabase project quando push para branch `develop`:
156
-
157
- ```yaml
158
- name: Deploy Migrations to Staging
159
- on:
160
- push:
161
- branches:
162
- - develop
163
- workflow_dispatch:
164
- jobs:
165
- deploy:
166
- runs-on: ubuntu-latest
167
- env:
168
- SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
169
- SUPABASE_DB_PASSWORD: ${{ secrets.STAGING_DB_PASSWORD }}
170
- SUPABASE_PROJECT_ID: ${{ secrets.STAGING_PROJECT_ID }}
171
- steps:
172
- - uses: actions/checkout@v4
173
- - uses: supabase/setup-cli@v1
174
- with:
175
- version: latest
176
- - run: supabase link --project-ref $SUPABASE_PROJECT_ID
177
- - run: supabase db push
178
- ```
179
-
180
- ### Explicação line-by-line
181
-
182
- - **`on: push: branches: [develop]`** — trigger quando alguém faz push direto em `develop` (ou merge de PR para `develop`)
183
- - **`workflow_dispatch`** — re-run manual via Actions tab
184
- - **`env: SUPABASE_ACCESS_TOKEN`** — secret do GitHub setado como env var no job (CLI lê este env var para autenticar)
185
- - **`env: SUPABASE_DB_PASSWORD`** — password do `postgres` role; `supabase link` consome este env var implicitamente
186
- - **`env: SUPABASE_PROJECT_ID`** — reference ID do staging project; usado no `--project-ref`
187
- - **`supabase link --project-ref $SUPABASE_PROJECT_ID`** — associa CLI ao projeto remoto staging (escreve `.supabase/config.json` no runner)
188
- - **`supabase db push`** — aplica migrations pendentes (que não estão em `supabase_migrations.schema_migrations` do remote) em ordem cronológica
189
-
190
- ### Caveats canônicos
191
-
192
- - **`develop` como branch de staging** é convenção GitFlow; alguns times usam `main` para staging e tag-based deploy para production — adapte conforme convention
193
- - `db push` consulta `supabase_migrations.schema_migrations` (tabela do Supabase) para determinar quais migrations aplicar — se há drift entre history local e remote, o push falha (cross-ref skill futura `supabase-migration-repair` Phase 153)
194
- - Permissões: o token `SUPABASE_ACCESS_TOKEN` precisa de permissão `db` no projeto staging (default em personal tokens)
195
-
196
- ### Idempotência
197
-
198
- `db push` é **idempotente** — se rodar 2× consecutivos no mesmo commit, a 2ª execução não faz nada (já aplicado). Mesmo trigger acidental (re-run) é seguro.
199
-
200
- ## Pattern 3: `production.yml` — deploy migrations to production (CI-03)
201
-
202
- Workflow para deploy automático de migrations ao production Supabase project quando push para branch `main`:
203
-
204
- ```yaml
205
- name: Deploy Migrations to Production
206
- on:
207
- push:
208
- branches:
209
- - main
210
- workflow_dispatch:
211
- jobs:
212
- deploy:
213
- runs-on: ubuntu-latest
214
- env:
215
- SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
216
- SUPABASE_DB_PASSWORD: ${{ secrets.PRODUCTION_DB_PASSWORD }}
217
- SUPABASE_PROJECT_ID: ${{ secrets.PRODUCTION_PROJECT_ID }}
218
- steps:
219
- - uses: actions/checkout@v4
220
- - uses: supabase/setup-cli@v1
221
- with:
222
- version: latest
223
- - run: supabase link --project-ref $SUPABASE_PROJECT_ID
224
- - run: supabase db push
225
- ```
226
-
227
- ### Diferenças vs staging.yml
228
-
229
- | | staging.yml | production.yml |
230
- |---|---|---|
231
- | `on: push: branches` | `develop` | `main` |
232
- | `SUPABASE_DB_PASSWORD` | `${{ secrets.STAGING_DB_PASSWORD }}` | `${{ secrets.PRODUCTION_DB_PASSWORD }}` |
233
- | `SUPABASE_PROJECT_ID` | `${{ secrets.STAGING_PROJECT_ID }}` | `${{ secrets.PRODUCTION_PROJECT_ID }}` |
234
- | Caso de uso | Merge para develop = release candidate | Merge para main = release final |
235
- | Rollback | Re-deploy commit anterior (rebuild migration if needed) | Mais delicado — cross-ref `supabase-migration-repair` Phase 153 |
236
-
237
- ### Warning canônico — cautela em deploy production
238
-
239
- Production deploy via `db push` automático é **conveniência ao custo de risco**:
240
-
241
- - Migrations destrutivas (DROP COLUMN, ALTER TYPE) aplicam imediatamente em production após merge
242
- - Sem janela de aprovação manual
243
- - Rollback de migration é complexo (cross-ref skill `evolucao-schema-compativel` v1.22 — pattern 3-step expand/migrate/contract)
244
-
245
- **Mitigações canônicas:**
246
-
247
- 1. **Required check `CI / test` (Pattern 1) obrigatório** em branch protection para `main` — sem ✓ verde, sem merge
248
- 2. **Required check `database-tests` (Pattern 5)** — pgTAP testes passando antes do merge
249
- 3. **Manual approval para PRs com label `migration`** — extra gate de revisão humana
250
- 4. **Pre-deploy hook personalizado** — adicionar step `supabase db diff --linked` para preview da mudança antes do `db push`
251
-
252
- ### Alternativa — deploy manual via tag
253
-
254
- Alguns times preferem deploy production só via tag versionada:
255
-
256
- ```yaml
257
- on:
258
- push:
259
- tags:
260
- - 'v*.*.*'
261
- ```
262
-
263
- Este pattern desacopla "merge para main" de "deploy production" — release manager cria tag explicitamente quando pronto.
264
-
265
- ## Pattern 4: `generate-types.yml` — verify schema.gen.ts committed (CI-04)
266
-
267
- Workflow dedicado a verificar que os TypeScript types estão committed e up-to-date — alternativa mais leve ao Pattern 1 (CI-01) se quiser separar concerns:
268
-
269
- ```yaml
270
- name: 'generate-types'
271
- on:
272
- pull_request:
273
- jobs:
274
- build:
275
- runs-on: ubuntu-latest
276
- steps:
277
- - uses: supabase/setup-cli@v1
278
- with:
279
- version: latest
280
- - run: supabase init
281
- - run: supabase db start
282
- - name: Verify generated types match Postgres schema
283
- run: |
284
- supabase gen types typescript --local > schema.gen.ts
285
- if ! git diff --ignore-space-at-eol --exit-code --quiet schema.gen.ts; then
286
- echo "Detected uncommitted changes after build. See status below:"
287
- git diff
288
- exit 1
289
- fi
290
- ```
291
-
292
- ### Diferenças vs Pattern 1 (CI-01)
293
-
294
- - **`supabase init`** — inicializa estrutura `supabase/` se não existir (ci.yml assume já inicializada)
295
- - **`schema.gen.ts`** como nome do arquivo (CI-01 usa `types.gen.ts`) — naming convenção do time; canônico é qualquer um, **DESDE QUE consistente**
296
- - Não tem `actions/checkout@v4` explícito (algumas docs Supabase omitem; mas o checkout é necessário em prática — adicione se não tiver)
297
-
298
- ### Por que TypeScript types matter no CI
299
-
300
- Schema do Postgres é **source of truth** dos tipos. Quando schema muda (nova coluna, novo type ENUM), os tipos TypeScript precisam ser regenerados. Sem CI:
301
-
302
- - Dev esquece de regenerar tipos → consumer compila com tipos stale → runtime errors em queries
303
- - PR review humano detecta inconsistência? Difícil — types files são gerados automaticamente
304
- - Sem gate em CI, types stale propagam para produção
305
-
306
- ### Workflow para developer local
307
-
308
- ```bash
309
- # após criar migration que muda schema
310
- supabase db reset # aplica todas migrations em DB local clean
311
- supabase gen types typescript --local > types.gen.ts
312
- git add types.gen.ts
313
- git commit -m "chore: regenerate types after migration X"
314
- ```
315
-
316
- Se este workflow não rodar, CI Pattern 1 ou Pattern 4 falha — gate canônico.
317
-
318
- ### Caveat — naming convention
319
-
320
- Manter um único nome (`types.gen.ts` OU `schema.gen.ts`, não os dois) é importante:
321
-
322
- - Consumer apps importam: `import type { Database } from './types.gen.ts'`
323
- - Mudar o nome quebra todos consumers
324
- - Recomendação: padronizar `types.gen.ts` (mais explícito que `schema.gen.ts`)
325
-
326
- ## Pattern 5: `database-tests.yml` — pgTAP runner (CI-05)
327
-
328
- Workflow para rodar testes pgTAP no DB local em CI (cross-ref skill futura `supabase-pgtap-testing` Phase 152):
329
-
330
- ```yaml
331
- name: 'database-tests'
332
- on:
333
- pull_request:
334
- jobs:
335
- build:
336
- runs-on: ubuntu-latest
337
- steps:
338
- - uses: actions/checkout@v3
339
- - uses: supabase/setup-cli@v1
340
- with:
341
- version: latest
342
- - run: supabase db start
343
- - run: supabase test db
344
- ```
345
-
346
- ### Explicação line-by-line
347
-
348
- - **`actions/checkout@v3`** — versão da doc oficial; v4 também funciona (recomendado migrar)
349
- - **`supabase db start`** — sobe Postgres + aplica todas migrations + aplica `seed.sql` se configurado
350
- - **`supabase test db`** — runner pgTAP integrado do CLI Supabase; lê arquivos `supabase/tests/*.sql` em ordem alfabética e executa cada teste
351
-
352
- ### Anatomy de um teste pgTAP
353
-
354
- Arquivo `supabase/tests/users.test.sql` (cross-ref skill futura Phase 152 para detalhes):
355
-
356
- ```sql
357
- begin;
358
- select plan(2);
359
-
360
- -- Teste 1: usuário authenticated pode SELECT em sua própria org
361
- select results_eq(
362
- $$select count(*) from organizations where id = current_setting('app.test_org_id')::uuid$$,
363
- $$select 1::bigint$$,
364
- 'authenticated user can SELECT own org'
365
- );
366
-
367
- -- Teste 2: usuário NÃO pode SELECT em outra org
368
- select throws_like(
369
- $$select * from organizations where id = '00000000-0000-0000-0000-000000000000'::uuid$$,
370
- '%permission denied%',
371
- 'cross-org SELECT raises permission denied'
372
- );
373
-
374
- select * from finish();
375
- rollback;
376
- ```
377
-
378
- ### Cross-ref skill futura — supabase-pgtap-testing (Phase 152)
379
-
380
- Detalhes completos de pgTAP estarão em skill dedicada (Phase 152) — esta skill (Phase 151) cobre apenas a **integração CI**:
381
-
382
- - Setup pgTAP extension (`create extension pgtap`)
383
- - Sintaxe canônica de testes (plan, ok, is, throws_ok, finish)
384
- - Test fixtures + cleanup pattern
385
- - Cross-ref `legacy-characterizer` para characterization tests em PG functions
386
-
387
- Por enquanto, basta saber que `supabase test db` é o entrypoint canônico — workflow YAML acima é completo.
388
-
389
- ### Caveat — falhas pgTAP retornam exit code != 0
390
-
391
- Se algum teste falha, `supabase test db` retorna exit 1 → CI fails → required check fails → merge bloqueado (com branch protection rule).
392
-
393
- Required check `database-tests / build` deve ser obrigatório em branch protection para `main`.
394
-
395
- ## Pattern 6: `functions-tests.yml` — Deno tests for Edge Functions (CI-06)
396
-
397
- Workflow para rodar testes Deno de Edge Functions em CI:
398
-
399
- ```yaml
400
- name: 'functions-tests'
401
- on:
402
- pull_request:
403
- jobs:
404
- build:
405
- runs-on: ubuntu-latest
406
- steps:
407
- - uses: actions/checkout@v3
408
- - uses: supabase/setup-cli@v1
409
- with:
410
- version: latest
411
- - uses: denoland/setup-deno@v2
412
- with:
413
- deno-version: latest
414
- - run: supabase start
415
- - run: deno test --allow-all deno-test.ts --env-file .env.local
416
- ```
417
-
418
- ### Explicação line-by-line
419
-
420
- - **`denoland/setup-deno@v2`** — instala Deno runtime no runner (Edge Functions rodam em Deno, não Node)
421
- - **`deno-version: latest`** — última versão estável; alguns times pinam para evitar surprise (`deno-version: 1.45.0`)
422
- - **`supabase start`** — sobe stack completa (Postgres + Auth + Edge Functions runtime + Storage) — diferente de `db start` que sobe só DB
423
- - **`deno test --allow-all deno-test.ts --env-file .env.local`** — roda testes definidos em `deno-test.ts`
424
- - `--allow-all` permite acesso file system + network + env vars (Deno é sandboxed por default)
425
- - `--env-file .env.local` carrega env vars de arquivo local (URLs locais, anon key local)
426
-
427
- ### `.env.local` para CI
428
-
429
- Arquivo `.env.local` (gitignored — gerado pelo runner ou stub):
430
-
431
- ```bash
432
- SUPABASE_URL=http://127.0.0.1:54321
433
- SUPABASE_ANON_KEY=eyJ...local-anon-key-from-supabase-start...
434
- SUPABASE_SERVICE_ROLE_KEY=eyJ...local-service-role-key...
435
- ```
436
-
437
- **Caveat:** `supabase start` mostra anon/service keys no output — em CI, capture via:
438
-
439
- ```bash
440
- - run: |
441
- supabase start > /tmp/supabase-start.log
442
- echo "SUPABASE_URL=$(grep 'API URL' /tmp/supabase-start.log | awk '{print $NF}')" >> .env.local
443
- echo "SUPABASE_ANON_KEY=$(grep 'anon key' /tmp/supabase-start.log | awk '{print $NF}')" >> .env.local
444
- ```
445
-
446
- Ou — mais limpo — passar keys via env vars dinâmicas:
447
-
448
- ```bash
449
- - run: deno test --allow-all deno-test.ts
450
- env:
451
- SUPABASE_URL: ${{ env.SUPABASE_URL }}
452
- SUPABASE_ANON_KEY: ${{ env.SUPABASE_ANON_KEY }}
453
- ```
454
-
455
- ### Anatomy de um teste Deno para Edge Function
456
-
457
- Arquivo `supabase/functions/_tests/deno-test.ts`:
458
-
459
- ```typescript
460
- import { assertEquals } from "https://deno.land/std@0.224.0/assert/mod.ts";
461
- import { createClient } from "https://esm.sh/@supabase/supabase-js@2";
462
-
463
- Deno.test("invite endpoint creates org_invites row", async () => {
464
- const supabase = createClient(
465
- Deno.env.get("SUPABASE_URL")!,
466
- Deno.env.get("SUPABASE_ANON_KEY")!,
467
- );
468
-
469
- const { data, error } = await supabase.functions.invoke("create-invite", {
470
- body: { email: "newuser@example.com", role: "member" },
471
- });
472
-
473
- assertEquals(error, null);
474
- assertEquals(data.success, true);
475
- });
476
- ```
477
-
478
- ### Caveat — Edge Functions runtime fora do test
479
-
480
- Testes Deno **chamam** Edge Functions (via `supabase.functions.invoke`) ou **importam diretamente** o handler. Para testar handler isolado:
481
-
482
- ```typescript
483
- import { handler } from "../create-invite/index.ts";
484
-
485
- Deno.test("handler validates email format", async () => {
486
- const req = new Request("http://localhost/create-invite", {
487
- method: "POST",
488
- body: JSON.stringify({ email: "invalid", role: "member" }),
489
- });
490
- const res = await handler(req);
491
- assertEquals(res.status, 400);
492
- });
493
- ```
494
-
495
- Required check `functions-tests / build` deve ser obrigatório em branch protection para `main`.
496
-
497
- ## Pattern 7: `backup.yml` — automated 3-dump backup with auto-commit (CI-07)
498
-
499
- > ## WARNING CANÔNICO
500
- >
501
- > **Never backup your data to a public repository.**
502
- >
503
- > Backups contêm **dados sensíveis** (PII, emails, hashed passwords, tokens, IDs internos, schema completo). Repositório público expõe TODOS os dados históricos via git history — irreversível.
504
- >
505
- > Use **APENAS** repositório **privado** (GitHub Private repo ou GitHub Enterprise). Considere criptografia adicional (git-crypt, GPG) se backups contêm PII regulado (LGPD/GDPR).
506
-
507
- Workflow para backup periódico do projeto Supabase com 3 dumps separados + auto-commit:
508
-
509
- ```yaml
510
- name: Supa-backup
511
-
512
- on:
513
- push:
514
- branches: [ main ]
515
- pull_request:
516
- branches: [ main ]
517
- workflow_dispatch:
518
- schedule:
519
- - cron: '0 0 * * *' # Runs every day at midnight
520
- jobs:
521
- run_db_backup:
522
- runs-on: ubuntu-latest
523
- permissions:
524
- contents: write
525
- env:
526
- supabase_db_url: ${{ secrets.SUPABASE_DB_URL }}
527
- steps:
528
- - uses: actions/checkout@v3
529
- with:
530
- ref: ${{ github.head_ref }}
531
- - uses: supabase/setup-cli@v1
532
- with:
533
- version: latest
534
- - name: Backup roles
535
- run: supabase db dump --db-url "$supabase_db_url" -f roles.sql --role-only
536
- - name: Backup schema
537
- run: supabase db dump --db-url "$supabase_db_url" -f schema.sql
538
- - name: Backup data
539
- run: supabase db dump --db-url "$supabase_db_url" -f data.sql --data-only --use-copy
540
-
541
- - uses: stefanzweifel/git-auto-commit-action@v4
542
- with:
543
- commit_message: Supabase backup
544
- ```
545
-
546
- ### Explicação line-by-line
547
-
548
- - **`on: schedule: cron: '0 0 * * *'`** — roda diariamente à meia-noite UTC; cron canônico de backup periódico
549
- - **`on: push/pull_request: branches: [main]`** — backup também em push/PR para main (extra trigger de safety net)
550
- - **`workflow_dispatch`** — re-run manual via Actions tab
551
- - **`permissions: contents: write`** — necessário para `git-auto-commit-action` push de volta ao repo
552
- - **`actions/checkout@v3 with: ref: ${{ github.head_ref }}`** — checkout do branch do PR (não default branch)
553
- - **`supabase/setup-cli@v1`** — instala CLI
554
- - **`supabase db dump --db-url "$supabase_db_url" -f roles.sql --role-only`** — Dump 1: apenas Postgres roles (CREATE ROLE statements)
555
- - **`supabase db dump --db-url "$supabase_db_url" -f schema.sql`** — Dump 2: schema completo (CREATE TABLE, INDEX, FUNCTION, etc.)
556
- - **`supabase db dump --db-url "$supabase_db_url" -f data.sql --data-only --use-copy`** — Dump 3: apenas dados (INSERT/COPY statements); `--use-copy` é mais rápido para tabelas grandes
557
- - **`stefanzweifel/git-auto-commit-action@v4 with: commit_message: Supabase backup`** — auto-commit dos 3 arquivos `.sql` se houver diferenças
558
-
559
- ### Por que 3 dumps separados — isolation de concerns
560
-
561
- | Arquivo | Conteúdo | Por que separar |
562
- |---------|----------|-----------------|
563
- | `roles.sql` | CREATE ROLE statements | Roles são lifecycle separado do schema — review independente; cross-ref skill `supabase-postgres-roles` (v1.26) |
564
- | `schema.sql` | CREATE TABLE, INDEX, FUNCTION, RLS policies, GRANTs | Schema cabe em git diff legível — review de mudanças facilitada |
565
- | `data.sql` | INSERT/COPY de dados | Arquivo grande; restaurável independente do schema; permite restaurar dados sem alterar schema |
566
-
567
- ### Caveats adicionais
568
-
569
- - **Rotação de backups** — git não trunca automaticamente; arquivo `data.sql` cresce indefinidamente. Mitigação: criar branch dedicado `supabase-backups` + workflow separado para rotation (`git filter-repo` periódico)
570
- - **Retention policy externa** — para compliance LGPD/GDPR (cross-ref skill `lgpd-multi-tenant-compliance` v1.21), considerar backup paralelo a S3 com lifecycle policy (delete após 30/90 dias)
571
- - **Criptografia adicional para PII** — git-crypt encripta arquivos no repo (chave separada em vault corporativo); GPG é alternativa para encryption-at-rest
572
- - **Restore procedure documentado** — backup sem restore testado é pior que sem backup; documentar em runbook (`.planning/RUNBOOK.md`) o processo de restore
573
- - **Frequência** — `cron '0 0 * * *'` = 1× por dia midnight UTC. Para alta criticidade, considere `0 */6 * * *` (6h) ou `0 */4 * * *` (4h)
574
- - **Branching workflow** — backup workflow roda no project **principal** (production), não em preview branches; verificar `SUPABASE_DB_URL` aponta para production
575
-
576
- ### Diferença vs Supabase managed backups
577
-
578
- Supabase Pro plan oferece **PITR (Point-in-Time Recovery)** managed — backup contínuo até 7 dias atrás. Workflow `backup.yml` é **complementar** (não substituto):
579
-
580
- | | PITR managed (Supabase) | backup.yml (custom) |
581
- |---|---|---|
582
- | Frequência | Contínuo (WAL streaming) | Daily midnight |
583
- | Retention | 7-28 dias (depende do plan) | Indefinido (git history) |
584
- | Custo | Incluído no Pro plan | GitHub Actions minutes + repo storage |
585
- | Granularidade | Point-in-time (segundo) | Daily snapshot |
586
- | Visibilidade | Dashboard apenas | Git diff visível |
587
- | Caso de uso | Disaster recovery rápido | Audit trail + cross-region backup |
588
-
589
- Recomendação canônica: usar **AMBOS** — PITR para recovery operacional, `backup.yml` para audit trail histórico.
590
-
591
- > ## WARNING CANÔNICO (REPETIDO)
592
- >
593
- > **Never backup your data to a public repository.**
594
- >
595
- > Mesmo workflow privado pode acidentalmente expor backup se o repo for tornado público posteriormente. Verificar via:
596
- >
597
- > 1. **Settings → General → Danger Zone → "Change repository visibility"** está em **Private**
598
- > 2. **Settings → Branches → Branch protection** restringe push para `main`
599
- > 3. **Auditar org members** com `Admin` permission no repo (podem mudar visibility)
600
- > 4. **Considerar repo DEDICADO para backups** — separar de código fonte; reduz surface area de exposição acidental
601
-
602
- ## Pattern 8: `notify-failure.yaml` — propagate Supabase Preview check failure (CI-08)
603
-
604
- Workflow que **propaga** o status do check "Supabase Preview" (gerado pelo Supabase Branching GitHub integration, cross-ref Phase 149 Pattern 3) para o status final do PR:
605
-
606
- ```yaml
607
- name: Branch Status
608
-
609
- on:
610
- pull_request:
611
- types:
612
- - opened
613
- - reopened
614
- - synchronize
615
- branches:
616
- - main
617
- - develop
618
- paths:
619
- - 'supabase/**'
620
-
621
- jobs:
622
- failed:
623
- runs-on: ubuntu-latest
624
- steps:
625
- - uses: fountainhead/action-wait-for-check@v1.2.0
626
- id: check
627
- with:
628
- checkName: Supabase Preview
629
- ref: ${{ github.event.pull_request.head.sha || github.sha }}
630
- token: ${{ secrets.GITHUB_TOKEN }}
631
-
632
- - if: ${{ steps.check.outputs.conclusion == 'failure' }}
633
- run: exit 1
634
- ```
635
-
636
- ### Explicação line-by-line
637
-
638
- - **`on: pull_request: types: [opened, reopened, synchronize]`** — trigger em todos eventos PR relevantes
639
- - **`on: pull_request: branches: [main, develop]`** — apenas PRs targeting main ou develop (filtra noise de feature → feature PRs)
640
- - **`on: pull_request: paths: ['supabase/**']`** — apenas PRs que tocam `supabase/` (filtra PRs de docs/frontend que não trigam Supabase Preview)
641
- - **`fountainhead/action-wait-for-check@v1.2.0`** — third-party action que espera um check específico aparecer no commit + retorna `conclusion`
642
- - **`checkName: Supabase Preview`** — nome do check gerado pelo Supabase GitHub integration (gerado automaticamente quando preview branch é criado)
643
- - **`ref: ${{ github.event.pull_request.head.sha || github.sha }}`** — SHA do commit alvo (head do PR ou SHA do push); fallback `github.sha` cobre edge cases
644
- - **`token: ${{ secrets.GITHUB_TOKEN }}`** — token automático do GitHub Actions (sem precisar configurar secret manual)
645
- - **`if: ${{ steps.check.outputs.conclusion == 'failure' }} run: exit 1`** — falha o workflow se Supabase Preview falhou
646
-
647
- ### Por que separar este workflow
648
-
649
- Sem este workflow:
650
-
651
- - "Supabase Preview" check aparece como external check no PR
652
- - Status mostra falha **isolado**, mas merge button pode estar habilitado se branch protection não selecionou explicitamente "Supabase Preview"
653
-
654
- Com este workflow:
655
-
656
- - `notify-failure / failed` aparece como check **do próprio repo**
657
- - Branch protection rule "require status checks" pode selecionar `notify-failure / failed`
658
- - Sem ✓ verde em `notify-failure / failed` → merge bloqueado mesmo se merge button parece habilitado
659
-
660
- ### Caveats canônicos
661
-
662
- - **`fountainhead/action-wait-for-check` é third-party** — auditar versão pinada (`@v1.2.0` específico, não `@v1`); supply chain attack surface
663
- - **Timeout** — action default espera até timeout do workflow (60min); para reduzir, usar `timeoutSeconds: 600` no with
664
- - **Check name exato** — `Supabase Preview` deve match exato (case-sensitive); se Supabase muda o nome do check, este workflow quebra silenciosamente
665
- - **`paths` filter** — se PR não tocar `supabase/`, workflow não roda, mas check fica ausente → branch protection pode bloquear merge incorretamente. Mitigação: usar `paths-ignore` em vez de `paths` para inverter lógica
666
-
667
- ### Required checks recomendados em branch protection (main)
668
-
669
- Lista canônica de required checks após adotar todos os workflows desta skill:
670
-
671
- 1. `CI / test` (Pattern 1)
672
- 2. `generate-types / build` (Pattern 4)
673
- 3. `database-tests / build` (Pattern 5)
674
- 4. `functions-tests / build` (Pattern 6)
675
- 5. `notify-failure / failed` (Pattern 8 — propaga Supabase Preview)
676
-
677
- Workflows que NÃO devem ser required:
678
- - `Supa-backup` (Pattern 7) — backup é write side-effect; falha ≠ bloquear merge
679
- - `Deploy Migrations to Staging` (Pattern 2) — deploy só após merge
680
- - `Deploy Migrations to Production` (Pattern 3) — deploy só após merge
681
-
682
- ## Anti-patterns
683
-
684
- ### Anti-pattern 1: Backup em repo público
685
-
686
- **Errado:**
687
-
688
- ```yaml
689
- # .github/workflows/backup.yml em repo PÚBLICO
690
- - name: Backup data
691
- run: supabase db dump --db-url "$supabase_db_url" -f data.sql --data-only --use-copy
692
- - uses: stefanzweifel/git-auto-commit-action@v4
693
- ```
694
-
695
- Workflow funciona, mas repo é público — `data.sql` committed contém **todos os dados** (emails, hashed passwords, PII).
696
-
697
- **Por quê:** dados sensíveis ficam expostos publicamente para sempre (git history é permanente); compliance LGPD/GDPR violado; surface de ataque massiva (qualquer um pode clonar e analisar offline); breach notification obrigatória.
698
-
699
- **Certo:**
700
-
701
- 1. **Repo PRIVADO** — `Settings → General → Danger Zone → Visibility: Private`
702
- 2. **Verificar via API:**
703
- ```bash
704
- gh repo view <org>/<repo> --json visibility
705
- # esperado: {"visibility": "PRIVATE"}
706
- ```
707
- 3. **Auditar admins** com permissão para mudar visibility — restringir
708
- 4. **Para PII regulado** — git-crypt encryption-at-rest:
709
- ```bash
710
- git-crypt init
711
- git-crypt add-gpg-user user@company.com
712
- # .gitattributes:
713
- # *.sql filter=git-crypt diff=git-crypt
714
- ```
715
- 5. **Considerar repo DEDICADO** apenas para backups (não compartilhar com código fonte) — reduz surface area de exposição acidental
716
-
717
- ### Anti-pattern 2: Schema changes direto no remote (bypass migration history)
718
-
719
- **Errado:**
720
-
721
- ```bash
722
- # dev faz mudança via Dashboard SQL Editor em production
723
- ALTER TABLE users ADD COLUMN avatar_url text;
724
-
725
- # nenhuma migration arquivo criada
726
- # supabase_migrations.schema_migrations sem entry para esta mudança
727
- ```
728
-
729
- Próximo `db push` via workflow (Pattern 2 ou 3):
730
-
731
- - CLI compara local migrations vs remote `schema_migrations` — não detecta a mudança "fantasma" feita via Dashboard
732
- - Migration subsequente pode falhar se assume estado anterior do schema
733
-
734
- **Por quê:** quebra migration history → drift entre git e DB → próximas migrations falham com `column already exists` ou similar → debugging pesadelo; rollback impossível porque a mudança não tem migration reversa.
735
-
736
- **Certo:**
737
-
738
- 1. **Sempre criar migration** via CLI:
739
- ```bash
740
- supabase migration new add_avatar_url_to_users
741
- # editar arquivo gerado em supabase/migrations/YYYYMMDDHHmmss_add_avatar_url_to_users.sql:
742
- # alter table public.users add column avatar_url text;
743
- ```
744
- 2. **Aplicar via PR** + workflow Pattern 1 (CI) valida + workflow Pattern 3 (production.yml) aplica
745
- 3. **Se mudança emergencial via Dashboard foi inevitável** — criar migration arquivo retrospectivo + usar `supabase migration repair` (cross-ref skill futura `supabase-migration-repair` Phase 153) para sincronizar history
746
-
747
- ### Anti-pattern 3: Concurrent `db push` from different machines
748
-
749
- **Errado:** dois devs rodam `supabase db push` simultaneamente — um do laptop, outro do GitHub Actions workflow:
750
-
751
- ```bash
752
- # Dev A — laptop
753
- $ supabase db push
754
- # aplicando migration_001...
755
-
756
- # Workflow (paralelo)
757
- $ supabase db push
758
- # também aplicando migration_001...
759
- ```
760
-
761
- **Por quê:** race condition em `supabase_migrations.schema_migrations` — duas conexões competem por lock, podem inserir duplicates, corromper history, ou deixar migration aplicada parcialmente; debugging pesadelo (state inconsistente entre history e schema real).
762
-
763
- **Certo:**
764
-
765
- 1. **Workflows GitHub Actions são source of truth** — devs NÃO rodam `db push` em production manualmente
766
- 2. **Concurrency control nos workflows:**
767
- ```yaml
768
- # staging.yml e production.yml
769
- concurrency:
770
- group: deploy-${{ github.workflow }}
771
- cancel-in-progress: false
772
- ```
773
- `cancel-in-progress: false` enfileira execuções em vez de cancelar → previne race
774
- 3. **Para emergencial** — anunciar no Slack `#engineering` antes; verificar via Actions tab que nenhum workflow está running
775
-
776
- ### Anti-pattern 4: Secrets sem encryption nas configurações GitHub (plaintext em workflow)
777
-
778
- **Errado:**
779
-
780
- ```yaml
781
- # .github/workflows/staging.yml
782
- jobs:
783
- deploy:
784
- runs-on: ubuntu-latest
785
- env:
786
- SUPABASE_DB_PASSWORD: my-actual-password-here # PLAINTEXT
787
- SUPABASE_ACCESS_TOKEN: sbp_actual_token_here # PLAINTEXT
788
- ```
789
-
790
- **Por quê:** workflow file é committed em git → password e access token expostos publicamente em git history → mesmo se removidos depois, git log preserva → rotação manual necessária + compromisso de qualquer secret encontrado.
791
-
792
- **Certo:**
793
-
794
- 1. **Sempre via `secrets`:**
795
- ```yaml
796
- env:
797
- SUPABASE_DB_PASSWORD: ${{ secrets.STAGING_DB_PASSWORD }}
798
- SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
799
- ```
800
- 2. **Configurar via UI:** `Settings → Secrets and variables → Actions → New repository secret`
801
- 3. **Auditar histórico** — buscar acidentes:
802
- ```bash
803
- git log -p | grep -E '(password|token|secret|key)' | head -50
804
- ```
805
- 4. **Se vazou:** rotacionar TODOS os secrets imediatamente (Dashboard → reset DB password + revoke access token + create new token + update GitHub secret)
806
-
807
- ### Anti-pattern 5: Workflows sem `concurrency` control causando race em deploy
808
-
809
- **Errado:** dois PRs mergem para `main` em rápida sucessão; workflow `production.yml` dispara 2× concorrentemente:
810
-
811
- ```yaml
812
- # production.yml SEM concurrency
813
- on:
814
- push:
815
- branches: [main]
816
- ```
817
-
818
- PR #100 mergeado → workflow run #1 inicia → ainda rodando.
819
- PR #101 mergeado → workflow run #2 inicia paralelo → `db push` concorrente → race em `supabase_migrations.schema_migrations`.
820
-
821
- **Por quê:** Anti-pattern 3 manifestado em produção real; corrupção de migration history em produção; pode resultar em deploy parcial → schema inconsistente → app quebra.
822
-
823
- **Certo:**
824
-
825
- ```yaml
826
- # production.yml COM concurrency
827
- on:
828
- push:
829
- branches: [main]
830
-
831
- concurrency:
832
- group: deploy-production
833
- cancel-in-progress: false # enfileira, não cancela
834
- ```
835
-
836
- `cancel-in-progress: false` é canônico — cancel-in-progress: true poderia abortar uma migration aplicação parcial → estado pior.
837
-
838
- ## Cross-suite integration (v1.27)
839
-
840
- Esta skill é o **3º pilar do CI/CD canônico Supabase**:
841
-
842
- - **`supabase-branching-workflow` (Phase 149)** — descreve **quando** preview branches são criados (PR webhook → branch DB isolado)
843
- - **`supabase-config-toml-remotes` (Phase 150)** — descreve **como** configurar branch-specific overrides + secrets per-branch
844
- - **`supabase-ci-cd-github-actions` (Phase 151, ESTA)** — descreve **como** automatizar via GitHub Actions workflows
845
-
846
- Cross-refs com skills futuras v1.27:
847
-
848
- - **`supabase-pgtap-testing` (Phase 152, futura)** — detalhes completos pgTAP que CI-05 (`database-tests.yml`) executa
849
- - **`supabase-migration-repair` (Phase 153, futura)** — `migration repair` em workflow para recovery quando `db push` falha drift
850
-
851
- Cross-refs com skills existentes v1.x:
852
-
853
- - **`hermetic-builds`** — auditar workflows GitHub Actions para reproducibility (`actions/checkout@v4` pinado, `supabase/setup-cli@v1` pinado, `denoland/setup-deno@v2` pinado, lockfile committed)
854
- - **`release-engineering`** — deployment philosophy (canary, feature flags, gradual rollout); `production.yml` Pattern 3 é deploy automático que pode evoluir para tag-based
855
- - **`eliminating-toil`** — workflows substituem toil manual (deploy manual → automated push; backup manual → cron midnight)
856
- - **`supabase-migrations` (v1.23)** — migration arquivos que `db push` consome
857
- - **`supabase-postgres-roles` (v1.26)** — roles dumps em `backup.yml` Pattern 7
858
-
859
- Base para agent novo v1.27:
860
-
861
- - **`supabase-cicd-pipeline-implementer` (Phase 154, futura)** — recebe spec via `Task()` e materializa `.github/workflows/*.yml` + `[remotes.<branch>]` blocks + secrets configuration
862
-
863
- Pattern de handoff cooperativo herdado v1.23-v1.26: **architect** projeta strategy → **cicd-pipeline-implementer** materializa workflows → **release-pipeline-auditor** (v1.10) audita hermeticidade do pipeline final. Nenhum agente descarta upstream — handoff cooperativo (princípio canônico v1.23).
864
-
865
- ## Ver também
866
-
867
- - [supabase-branching-workflow](../supabase-branching-workflow/SKILL.md) (v1.27, Phase 149) — preview branches que ci.yml + notify-failure.yaml validam
868
- - [supabase-config-toml-remotes](../supabase-config-toml-remotes/SKILL.md) (v1.27, Phase 150) — secrets management dotenvx + `[remotes]` blocks per-branch que workflows consomem
869
- - [supabase-pgtap-testing](../supabase-pgtap-testing/SKILL.md) (v1.27, Phase 152, futura) — sintaxe pgTAP + setup que database-tests.yml roda
870
- - [supabase-migration-repair](../supabase-migration-repair/SKILL.md) (v1.27, Phase 153, futura) — recovery quando db push falha em CI por drift
871
- - [supabase-migrations](../supabase-migrations/SKILL.md) (v1.23) — migration files que db push aplica
872
- - [supabase-postgres-roles](../supabase-postgres-roles/SKILL.md) (v1.26) — roles dumps em backup.yml Pattern 7
873
- - [supabase-edge-functions](../supabase-edge-functions/SKILL.md) — Edge Functions que functions-tests.yml testa via Deno
874
- - [hermetic-builds](../hermetic-builds/SKILL.md) — auditar workflows para reproducibility (actions pinned + lockfile + frozen-install)
875
- - [release-engineering](../release-engineering/SKILL.md) — deployment philosophy + canary + rollback strategies
876
- - [eliminating-toil](../eliminating-toil/SKILL.md) — workflows substituem toil manual (deploy + backup + types regen)
877
- - [evolucao-schema-compativel](../evolucao-schema-compativel/SKILL.md) (v1.22) — 3-step migration safe pattern para mudanças destrutivas em production.yml
878
- - [lgpd-multi-tenant-compliance](../lgpd-multi-tenant-compliance/SKILL.md) (v1.21) — backup criptografado per-tenant para compliance LGPD
879
- - [glossário compartilhado](../_shared-supabase/glossary.md) — termos GitHub Actions Supabase, ci.yml, staging.yml, production.yml, backup 3-dump, fountainhead/action-wait-for-check, never backup to public repo
880
- - Doc oficial: [Supabase GitHub Actions](https://supabase.com/docs/guides/deployment/ci), [GitHub Actions docs](https://docs.github.com/en/actions), [denoland/setup-deno](https://github.com/denoland/setup-deno), [stefanzweifel/git-auto-commit-action](https://github.com/stefanzweifel/git-auto-commit-action), [fountainhead/action-wait-for-check](https://github.com/fountainhead/action-wait-for-check)
1
+ ---
2
+ name: supabase-ci-cd-github-actions
3
+ description: Use ao automatizar Supabase via GitHub Actions — 8 workflows canônicos da doc oficial (ci.yml, staging.yml, production.yml, generate-types.yml, database-tests.yml, functions-tests.yml, backup.
4
+ ---
5
+
6
+ # Supabase — CI/CD GitHub Actions
7
+
8
+ ## Quando usar
9
+
10
+ Esta skill cobre **8 workflows GitHub Actions canônicos** da doc oficial Supabase para automatizar lifecycle do projeto — validação em PR, deploy para staging/production, generação de types TypeScript, testes pgTAP + Deno, backup periódico, e propagação de failure check.
11
+
12
+ Trigger phrases:
13
+
14
+ - "CI Supabase GitHub Actions", "workflow Supabase CI"
15
+ - "deploy Supabase staging", "deploy Supabase production"
16
+ - "ci.yml Supabase", "staging.yml Supabase", "production.yml Supabase"
17
+ - "generate-types.yml Supabase", "schema.gen.ts CI"
18
+ - "database-tests.yml Supabase", "supabase test db CI"
19
+ - "functions-tests.yml Supabase", "deno test --allow-all CI"
20
+ - "backup.yml Supabase", "supabase db dump cron", "automated backup Supabase"
21
+ - "notify-failure.yaml Supabase", "fountainhead/action-wait-for-check"
22
+ - "Never backup your data to a public repository"
23
+ - "supabase secrets set CI", "supabase link --project-ref CI"
24
+
25
+ **Use APENAS para:**
26
+
27
+ - Validar migrations + schema declarativo em PR (gate antes do merge)
28
+ - Automatizar deploy para staging (branch develop) e production (branch main)
29
+ - Verificar que `schema.gen.ts` (types TypeScript) está committed e up-to-date
30
+ - Rodar testes pgTAP (`supabase test db`) + testes Deno (`deno test --allow-all`) em CI
31
+ - Backup periódico do schema/data/roles via cron midnight em repo **PRIVADO**
32
+ - Propagar falha do check "Supabase Preview" para o status do PR
33
+
34
+ **NÃO use para:**
35
+
36
+ - Substituir Supabase Branching (cross-ref skill `supabase-branching-workflow` Phase 149) — branching é gerenciado via Supabase Dashboard ou GitHub Integration (não GitHub Actions workflow customizado)
37
+ - Backup de dados sensíveis em **repositório público** — sempre repositório **privado** com criptografia adicional se PII (cross-ref Anti-pattern 1)
38
+ - Bypass de migration history — `db push` deve respeitar `supabase_migrations.schema_migrations` (cross-ref Anti-pattern 2)
39
+ - `db push` concorrente de máquinas diferentes — race condition pode corromper migration history (cross-ref Anti-pattern 3)
40
+
41
+ ## Princípio canônico
42
+
43
+ Quatro princípios canônicos:
44
+
45
+ 1. **CI/CD shift-left.** Cada PR valida migrations + types + tests **antes** do merge — sem surpresas em produção. Gate canônico = required status check enforced via branch protection rules.
46
+
47
+ 2. **Cada PR gera preview branch isolado.** Workflows GitHub Actions são complementares ao Supabase Branching (cross-ref skill `supabase-branching-workflow` Phase 149) — branching gera o branch DB; GitHub Actions valida o código que define migrations e Edge Functions.
48
+
49
+ 3. **Required check enforced.** Branch protection rule "Require status checks to pass before merging" + selecionar workflows críticos (CI-01 ci, CI-04 generate-types, CI-08 notify-failure) — sem ✓ verde, sem merge para `main`.
50
+
51
+ 4. **3-dump backup separados (CI-07).** Roles + Schema + Data dumps em arquivos SEPARADOS — isolation de concerns:
52
+ - `roles.sql` (--role-only) pode ser revisado independente
53
+ - `schema.sql` cabe em git diff legível
54
+ - `data.sql` (--data-only --use-copy) gera arquivo grande mas restaurável independente
55
+
56
+ ### Distinção canônica vs Supabase Branching
57
+
58
+ | | Supabase Branching | GitHub Actions workflows |
59
+ |---|---|---|
60
+ | Gerencia | Branch DB Postgres + Edge Functions config | Código (migrations, types, tests) |
61
+ | Trigger | PR webhook (Branching) | PR events (workflows) |
62
+ | Source of truth | Supabase Dashboard config | `.github/workflows/*.yml` versionado |
63
+ | Validação | Deploy DAG 7 steps (cross-ref Phase 149 Pattern 2) | Type-check, pgTAP, Deno tests, db push |
64
+ | Cobrança | Branching Compute Hours (fora Spend Cap) | GitHub Actions minutes (free 2k/mês) |
65
+
66
+ Os dois são **complementares** — workflows GitHub Actions validam o **código** que vai para o branch DB; Branching gerencia o **ambiente** onde o código roda.
67
+
68
+ ## Secrets GitHub Actions necessários
69
+
70
+ Antes de adotar qualquer workflow desta skill, configurar os secrets no repositório GitHub:
71
+
72
+ **Settings → Secrets and variables → Actions → New repository secret**
73
+
74
+ | Secret | Origem | Workflows que usam | Caso de uso |
75
+ |--------|--------|---------------------|-------------|
76
+ | `SUPABASE_ACCESS_TOKEN` | Personal access token (Dashboard → Account → Access Tokens) | staging.yml, production.yml | Autenticação do CLI Supabase em GitHub Actions runner |
77
+ | `STAGING_DB_PASSWORD` | Dashboard → Project Settings → Database (staging project) | staging.yml | Password do `postgres` role no staging — usado por `supabase link` |
78
+ | `STAGING_PROJECT_ID` | Dashboard → Project Settings → General → Reference ID (staging project) | staging.yml | Project reference do staging — usado por `supabase link --project-ref` |
79
+ | `PRODUCTION_DB_PASSWORD` | Dashboard → Project Settings → Database (production project) | production.yml | Password do `postgres` role no production |
80
+ | `PRODUCTION_PROJECT_ID` | Dashboard → Project Settings → General → Reference ID (production project) | production.yml | Project reference do production |
81
+ | `SUPABASE_DB_URL` | Connection string do production (`postgresql://postgres:pwd@host/db`) | backup.yml | URL completa para `supabase db dump --db-url` |
82
+
83
+ ### Caveat — `SUPABASE_ACCESS_TOKEN` é per-user
84
+
85
+ Personal access tokens são vinculados ao **usuário** que os criou — se este usuário sair da organização, o token fica órfão e workflows quebram silenciosamente.
86
+
87
+ **Mitigação canônica:** criar token vinculado a uma **service account** dedicada da empresa (ex: `ci@company.com`) em vez de conta pessoal do dev.
88
+
89
+ ### Caveat — Rotacionar passwords periodicamente
90
+
91
+ `PRODUCTION_DB_PASSWORD` e `STAGING_DB_PASSWORD` devem ser rotacionados a cada 90 dias (best practice). Após rotação no Dashboard, atualizar o secret em GitHub Actions — workflows quebram silenciosamente se o secret estiver stale.
92
+
93
+ ### Caveat — `SUPABASE_DB_URL` contém password — encrypted by default
94
+
95
+ GitHub Actions encripta secrets automaticamente em rest e nos logs (mascaramento). NUNCA ecoar o secret em `run:` step — mesmo mascarado, pode vazar em error logs ou crash dumps.
96
+
97
+ ## Pattern 1: `ci.yml` — validation on pull request (CI-01)
98
+
99
+ Workflow canônico que valida migrations + types em todo PR aberto:
100
+
101
+ ```yaml
102
+ name: CI
103
+ on:
104
+ pull_request:
105
+ workflow_dispatch:
106
+ jobs:
107
+ test:
108
+ runs-on: ubuntu-latest
109
+ steps:
110
+ - uses: actions/checkout@v4
111
+ - uses: supabase/setup-cli@v1
112
+ with:
113
+ version: latest
114
+ - name: Start Supabase local development setup
115
+ run: supabase db start
116
+ - name: Verify generated types are checked in
117
+ run: |
118
+ supabase gen types typescript --local > types.gen.ts
119
+ if ! git diff --ignore-space-at-eol --exit-code --quiet types.gen.ts; then
120
+ echo "Detected uncommitted changes after build. See status below:"
121
+ git diff
122
+ exit 1
123
+ fi
124
+ ```
125
+
126
+ ### Explicação line-by-line
127
+
128
+ - **`on: pull_request`** — trigger automático em todo PR aberto/atualizado
129
+ - **`workflow_dispatch`** — permite re-run manual via Actions tab (útil para debug)
130
+ - **`actions/checkout@v4`** — clona o repo no runner; v4 é a versão canônica atual (v3 ainda funciona mas sem features recentes)
131
+ - **`supabase/setup-cli@v1`** — instala CLI Supabase no runner (Docker layer cached); `version: latest` pega última release estável
132
+ - **`supabase db start`** — sobe instância Postgres + Auth + Realtime local via Docker
133
+ - **`supabase gen types typescript --local`** — gera tipos TypeScript a partir do schema do DB local (que aplicou as migrations no `db start`)
134
+ - **`git diff --ignore-space-at-eol --exit-code --quiet types.gen.ts`** — compara `types.gen.ts` gerado vs versionado em git; se diff existir, falha com exit 1
135
+
136
+ ### Caveats canônicos
137
+
138
+ - **`--ignore-space-at-eol`** previne false positives causados por diferenças LF vs CRLF entre runner Linux e dev Windows
139
+ - **`--exit-code`** força exit 1 se diff (default `git diff` retorna 0 mesmo com diff)
140
+ - **`--quiet`** suprime output redundante (já temos `echo` + `git diff` manuais)
141
+ - O workflow só falha se `types.gen.ts` está **stale** — dev deve `supabase gen types typescript --local > types.gen.ts && git add types.gen.ts && git commit` localmente antes do PR
142
+
143
+ ### Por que validar types committed
144
+
145
+ Consumer projetos TypeScript (clientes do projeto Supabase) **importam** `types.gen.ts` para type-safety em queries (`createClient<Database>()`). Se types estão stale:
146
+
147
+ - Compilação consumer falha silenciosamente em produção
148
+ - Type assertions ficam erradas (campo `created_at` ainda `string`, mas DB já é `timestamp`)
149
+ - Refactor downstream quebra sem warning
150
+
151
+ Required check `CI / test` deve ser obrigatório em branch protection rules para `main`.
152
+
153
+ ## Pattern 2: `staging.yml` — deploy migrations to staging (CI-02)
154
+
155
+ Workflow para deploy automático de migrations ao staging Supabase project quando push para branch `develop`:
156
+
157
+ ```yaml
158
+ name: Deploy Migrations to Staging
159
+ on:
160
+ push:
161
+ branches:
162
+ - develop
163
+ workflow_dispatch:
164
+ jobs:
165
+ deploy:
166
+ runs-on: ubuntu-latest
167
+ env:
168
+ SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
169
+ SUPABASE_DB_PASSWORD: ${{ secrets.STAGING_DB_PASSWORD }}
170
+ SUPABASE_PROJECT_ID: ${{ secrets.STAGING_PROJECT_ID }}
171
+ steps:
172
+ - uses: actions/checkout@v4
173
+ - uses: supabase/setup-cli@v1
174
+ with:
175
+ version: latest
176
+ - run: supabase link --project-ref $SUPABASE_PROJECT_ID
177
+ - run: supabase db push
178
+ ```
179
+
180
+ ### Explicação line-by-line
181
+
182
+ - **`on: push: branches: [develop]`** — trigger quando alguém faz push direto em `develop` (ou merge de PR para `develop`)
183
+ - **`workflow_dispatch`** — re-run manual via Actions tab
184
+ - **`env: SUPABASE_ACCESS_TOKEN`** — secret do GitHub setado como env var no job (CLI lê este env var para autenticar)
185
+ - **`env: SUPABASE_DB_PASSWORD`** — password do `postgres` role; `supabase link` consome este env var implicitamente
186
+ - **`env: SUPABASE_PROJECT_ID`** — reference ID do staging project; usado no `--project-ref`
187
+ - **`supabase link --project-ref $SUPABASE_PROJECT_ID`** — associa CLI ao projeto remoto staging (escreve `.supabase/config.json` no runner)
188
+ - **`supabase db push`** — aplica migrations pendentes (que não estão em `supabase_migrations.schema_migrations` do remote) em ordem cronológica
189
+
190
+ ### Caveats canônicos
191
+
192
+ - **`develop` como branch de staging** é convenção GitFlow; alguns times usam `main` para staging e tag-based deploy para production — adapte conforme convention
193
+ - `db push` consulta `supabase_migrations.schema_migrations` (tabela do Supabase) para determinar quais migrations aplicar — se há drift entre history local e remote, o push falha (cross-ref skill futura `supabase-migration-repair` Phase 153)
194
+ - Permissões: o token `SUPABASE_ACCESS_TOKEN` precisa de permissão `db` no projeto staging (default em personal tokens)
195
+
196
+ ### Idempotência
197
+
198
+ `db push` é **idempotente** — se rodar 2× consecutivos no mesmo commit, a 2ª execução não faz nada (já aplicado). Mesmo trigger acidental (re-run) é seguro.
199
+
200
+ ## Pattern 3: `production.yml` — deploy migrations to production (CI-03)
201
+
202
+ Workflow para deploy automático de migrations ao production Supabase project quando push para branch `main`:
203
+
204
+ ```yaml
205
+ name: Deploy Migrations to Production
206
+ on:
207
+ push:
208
+ branches:
209
+ - main
210
+ workflow_dispatch:
211
+ jobs:
212
+ deploy:
213
+ runs-on: ubuntu-latest
214
+ env:
215
+ SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
216
+ SUPABASE_DB_PASSWORD: ${{ secrets.PRODUCTION_DB_PASSWORD }}
217
+ SUPABASE_PROJECT_ID: ${{ secrets.PRODUCTION_PROJECT_ID }}
218
+ steps:
219
+ - uses: actions/checkout@v4
220
+ - uses: supabase/setup-cli@v1
221
+ with:
222
+ version: latest
223
+ - run: supabase link --project-ref $SUPABASE_PROJECT_ID
224
+ - run: supabase db push
225
+ ```
226
+
227
+ ### Diferenças vs staging.yml
228
+
229
+ | | staging.yml | production.yml |
230
+ |---|---|---|
231
+ | `on: push: branches` | `develop` | `main` |
232
+ | `SUPABASE_DB_PASSWORD` | `${{ secrets.STAGING_DB_PASSWORD }}` | `${{ secrets.PRODUCTION_DB_PASSWORD }}` |
233
+ | `SUPABASE_PROJECT_ID` | `${{ secrets.STAGING_PROJECT_ID }}` | `${{ secrets.PRODUCTION_PROJECT_ID }}` |
234
+ | Caso de uso | Merge para develop = release candidate | Merge para main = release final |
235
+ | Rollback | Re-deploy commit anterior (rebuild migration if needed) | Mais delicado — cross-ref `supabase-migration-repair` Phase 153 |
236
+
237
+ ### Warning canônico — cautela em deploy production
238
+
239
+ Production deploy via `db push` automático é **conveniência ao custo de risco**:
240
+
241
+ - Migrations destrutivas (DROP COLUMN, ALTER TYPE) aplicam imediatamente em production após merge
242
+ - Sem janela de aprovação manual
243
+ - Rollback de migration é complexo (cross-ref skill `evolucao-schema-compativel` v1.22 — pattern 3-step expand/migrate/contract)
244
+
245
+ **Mitigações canônicas:**
246
+
247
+ 1. **Required check `CI / test` (Pattern 1) obrigatório** em branch protection para `main` — sem ✓ verde, sem merge
248
+ 2. **Required check `database-tests` (Pattern 5)** — pgTAP testes passando antes do merge
249
+ 3. **Manual approval para PRs com label `migration`** — extra gate de revisão humana
250
+ 4. **Pre-deploy hook personalizado** — adicionar step `supabase db diff --linked` para preview da mudança antes do `db push`
251
+
252
+ ### Alternativa — deploy manual via tag
253
+
254
+ Alguns times preferem deploy production só via tag versionada:
255
+
256
+ ```yaml
257
+ on:
258
+ push:
259
+ tags:
260
+ - 'v*.*.*'
261
+ ```
262
+
263
+ Este pattern desacopla "merge para main" de "deploy production" — release manager cria tag explicitamente quando pronto.
264
+
265
+ ## Pattern 4: `generate-types.yml` — verify schema.gen.ts committed (CI-04)
266
+
267
+ Workflow dedicado a verificar que os TypeScript types estão committed e up-to-date — alternativa mais leve ao Pattern 1 (CI-01) se quiser separar concerns:
268
+
269
+ ```yaml
270
+ name: 'generate-types'
271
+ on:
272
+ pull_request:
273
+ jobs:
274
+ build:
275
+ runs-on: ubuntu-latest
276
+ steps:
277
+ - uses: supabase/setup-cli@v1
278
+ with:
279
+ version: latest
280
+ - run: supabase init
281
+ - run: supabase db start
282
+ - name: Verify generated types match Postgres schema
283
+ run: |
284
+ supabase gen types typescript --local > schema.gen.ts
285
+ if ! git diff --ignore-space-at-eol --exit-code --quiet schema.gen.ts; then
286
+ echo "Detected uncommitted changes after build. See status below:"
287
+ git diff
288
+ exit 1
289
+ fi
290
+ ```
291
+
292
+ ### Diferenças vs Pattern 1 (CI-01)
293
+
294
+ - **`supabase init`** — inicializa estrutura `supabase/` se não existir (ci.yml assume já inicializada)
295
+ - **`schema.gen.ts`** como nome do arquivo (CI-01 usa `types.gen.ts`) — naming convenção do time; canônico é qualquer um, **DESDE QUE consistente**
296
+ - Não tem `actions/checkout@v4` explícito (algumas docs Supabase omitem; mas o checkout é necessário em prática — adicione se não tiver)
297
+
298
+ ### Por que TypeScript types matter no CI
299
+
300
+ Schema do Postgres é **source of truth** dos tipos. Quando schema muda (nova coluna, novo type ENUM), os tipos TypeScript precisam ser regenerados. Sem CI:
301
+
302
+ - Dev esquece de regenerar tipos → consumer compila com tipos stale → runtime errors em queries
303
+ - PR review humano detecta inconsistência? Difícil — types files são gerados automaticamente
304
+ - Sem gate em CI, types stale propagam para produção
305
+
306
+ ### Workflow para developer local
307
+
308
+ ```bash
309
+ # após criar migration que muda schema
310
+ supabase db reset # aplica todas migrations em DB local clean
311
+ supabase gen types typescript --local > types.gen.ts
312
+ git add types.gen.ts
313
+ git commit -m "chore: regenerate types after migration X"
314
+ ```
315
+
316
+ Se este workflow não rodar, CI Pattern 1 ou Pattern 4 falha — gate canônico.
317
+
318
+ ### Caveat — naming convention
319
+
320
+ Manter um único nome (`types.gen.ts` OU `schema.gen.ts`, não os dois) é importante:
321
+
322
+ - Consumer apps importam: `import type { Database } from './types.gen.ts'`
323
+ - Mudar o nome quebra todos consumers
324
+ - Recomendação: padronizar `types.gen.ts` (mais explícito que `schema.gen.ts`)
325
+
326
+ ## Pattern 5: `database-tests.yml` — pgTAP runner (CI-05)
327
+
328
+ Workflow para rodar testes pgTAP no DB local em CI (cross-ref skill futura `supabase-pgtap-testing` Phase 152):
329
+
330
+ ```yaml
331
+ name: 'database-tests'
332
+ on:
333
+ pull_request:
334
+ jobs:
335
+ build:
336
+ runs-on: ubuntu-latest
337
+ steps:
338
+ - uses: actions/checkout@v3
339
+ - uses: supabase/setup-cli@v1
340
+ with:
341
+ version: latest
342
+ - run: supabase db start
343
+ - run: supabase test db
344
+ ```
345
+
346
+ ### Explicação line-by-line
347
+
348
+ - **`actions/checkout@v3`** — versão da doc oficial; v4 também funciona (recomendado migrar)
349
+ - **`supabase db start`** — sobe Postgres + aplica todas migrations + aplica `seed.sql` se configurado
350
+ - **`supabase test db`** — runner pgTAP integrado do CLI Supabase; lê arquivos `supabase/tests/*.sql` em ordem alfabética e executa cada teste
351
+
352
+ ### Anatomy de um teste pgTAP
353
+
354
+ Arquivo `supabase/tests/users.test.sql` (cross-ref skill futura Phase 152 para detalhes):
355
+
356
+ ```sql
357
+ begin;
358
+ select plan(2);
359
+
360
+ -- Teste 1: usuário authenticated pode SELECT em sua própria org
361
+ select results_eq(
362
+ $$select count(*) from organizations where id = current_setting('app.test_org_id')::uuid$$,
363
+ $$select 1::bigint$$,
364
+ 'authenticated user can SELECT own org'
365
+ );
366
+
367
+ -- Teste 2: usuário NÃO pode SELECT em outra org
368
+ select throws_like(
369
+ $$select * from organizations where id = '00000000-0000-0000-0000-000000000000'::uuid$$,
370
+ '%permission denied%',
371
+ 'cross-org SELECT raises permission denied'
372
+ );
373
+
374
+ select * from finish();
375
+ rollback;
376
+ ```
377
+
378
+ ### Cross-ref skill futura — supabase-pgtap-testing (Phase 152)
379
+
380
+ Detalhes completos de pgTAP estarão em skill dedicada (Phase 152) — esta skill (Phase 151) cobre apenas a **integração CI**:
381
+
382
+ - Setup pgTAP extension (`create extension pgtap`)
383
+ - Sintaxe canônica de testes (plan, ok, is, throws_ok, finish)
384
+ - Test fixtures + cleanup pattern
385
+ - Cross-ref `legacy-characterizer` para characterization tests em PG functions
386
+
387
+ Por enquanto, basta saber que `supabase test db` é o entrypoint canônico — workflow YAML acima é completo.
388
+
389
+ ### Caveat — falhas pgTAP retornam exit code != 0
390
+
391
+ Se algum teste falha, `supabase test db` retorna exit 1 → CI fails → required check fails → merge bloqueado (com branch protection rule).
392
+
393
+ Required check `database-tests / build` deve ser obrigatório em branch protection para `main`.
394
+
395
+ ## Pattern 6: `functions-tests.yml` — Deno tests for Edge Functions (CI-06)
396
+
397
+ Workflow para rodar testes Deno de Edge Functions em CI:
398
+
399
+ ```yaml
400
+ name: 'functions-tests'
401
+ on:
402
+ pull_request:
403
+ jobs:
404
+ build:
405
+ runs-on: ubuntu-latest
406
+ steps:
407
+ - uses: actions/checkout@v3
408
+ - uses: supabase/setup-cli@v1
409
+ with:
410
+ version: latest
411
+ - uses: denoland/setup-deno@v2
412
+ with:
413
+ deno-version: latest
414
+ - run: supabase start
415
+ - run: deno test --allow-all deno-test.ts --env-file .env.local
416
+ ```
417
+
418
+ ### Explicação line-by-line
419
+
420
+ - **`denoland/setup-deno@v2`** — instala Deno runtime no runner (Edge Functions rodam em Deno, não Node)
421
+ - **`deno-version: latest`** — última versão estável; alguns times pinam para evitar surprise (`deno-version: 1.45.0`)
422
+ - **`supabase start`** — sobe stack completa (Postgres + Auth + Edge Functions runtime + Storage) — diferente de `db start` que sobe só DB
423
+ - **`deno test --allow-all deno-test.ts --env-file .env.local`** — roda testes definidos em `deno-test.ts`
424
+ - `--allow-all` permite acesso file system + network + env vars (Deno é sandboxed por default)
425
+ - `--env-file .env.local` carrega env vars de arquivo local (URLs locais, anon key local)
426
+
427
+ ### `.env.local` para CI
428
+
429
+ Arquivo `.env.local` (gitignored — gerado pelo runner ou stub):
430
+
431
+ ```bash
432
+ SUPABASE_URL=http://127.0.0.1:54321
433
+ SUPABASE_ANON_KEY=eyJ...local-anon-key-from-supabase-start...
434
+ SUPABASE_SERVICE_ROLE_KEY=eyJ...local-service-role-key...
435
+ ```
436
+
437
+ **Caveat:** `supabase start` mostra anon/service keys no output — em CI, capture via:
438
+
439
+ ```bash
440
+ - run: |
441
+ supabase start > /tmp/supabase-start.log
442
+ echo "SUPABASE_URL=$(grep 'API URL' /tmp/supabase-start.log | awk '{print $NF}')" >> .env.local
443
+ echo "SUPABASE_ANON_KEY=$(grep 'anon key' /tmp/supabase-start.log | awk '{print $NF}')" >> .env.local
444
+ ```
445
+
446
+ Ou — mais limpo — passar keys via env vars dinâmicas:
447
+
448
+ ```bash
449
+ - run: deno test --allow-all deno-test.ts
450
+ env:
451
+ SUPABASE_URL: ${{ env.SUPABASE_URL }}
452
+ SUPABASE_ANON_KEY: ${{ env.SUPABASE_ANON_KEY }}
453
+ ```
454
+
455
+ ### Anatomy de um teste Deno para Edge Function
456
+
457
+ Arquivo `supabase/functions/_tests/deno-test.ts`:
458
+
459
+ ```typescript
460
+ import { assertEquals } from "https://deno.land/std@0.224.0/assert/mod.ts";
461
+ import { createClient } from "https://esm.sh/@supabase/supabase-js@2";
462
+
463
+ Deno.test("invite endpoint creates org_invites row", async () => {
464
+ const supabase = createClient(
465
+ Deno.env.get("SUPABASE_URL")!,
466
+ Deno.env.get("SUPABASE_ANON_KEY")!,
467
+ );
468
+
469
+ const { data, error } = await supabase.functions.invoke("create-invite", {
470
+ body: { email: "newuser@example.com", role: "member" },
471
+ });
472
+
473
+ assertEquals(error, null);
474
+ assertEquals(data.success, true);
475
+ });
476
+ ```
477
+
478
+ ### Caveat — Edge Functions runtime fora do test
479
+
480
+ Testes Deno **chamam** Edge Functions (via `supabase.functions.invoke`) ou **importam diretamente** o handler. Para testar handler isolado:
481
+
482
+ ```typescript
483
+ import { handler } from "../create-invite/index.ts";
484
+
485
+ Deno.test("handler validates email format", async () => {
486
+ const req = new Request("http://localhost/create-invite", {
487
+ method: "POST",
488
+ body: JSON.stringify({ email: "invalid", role: "member" }),
489
+ });
490
+ const res = await handler(req);
491
+ assertEquals(res.status, 400);
492
+ });
493
+ ```
494
+
495
+ Required check `functions-tests / build` deve ser obrigatório em branch protection para `main`.
496
+
497
+ ## Pattern 7: `backup.yml` — automated 3-dump backup with auto-commit (CI-07)
498
+
499
+ > ## WARNING CANÔNICO
500
+ >
501
+ > **Never backup your data to a public repository.**
502
+ >
503
+ > Backups contêm **dados sensíveis** (PII, emails, hashed passwords, tokens, IDs internos, schema completo). Repositório público expõe TODOS os dados históricos via git history — irreversível.
504
+ >
505
+ > Use **APENAS** repositório **privado** (GitHub Private repo ou GitHub Enterprise). Considere criptografia adicional (git-crypt, GPG) se backups contêm PII regulado (LGPD/GDPR).
506
+
507
+ Workflow para backup periódico do projeto Supabase com 3 dumps separados + auto-commit:
508
+
509
+ ```yaml
510
+ name: Supa-backup
511
+
512
+ on:
513
+ push:
514
+ branches: [ main ]
515
+ pull_request:
516
+ branches: [ main ]
517
+ workflow_dispatch:
518
+ schedule:
519
+ - cron: '0 0 * * *' # Runs every day at midnight
520
+ jobs:
521
+ run_db_backup:
522
+ runs-on: ubuntu-latest
523
+ permissions:
524
+ contents: write
525
+ env:
526
+ supabase_db_url: ${{ secrets.SUPABASE_DB_URL }}
527
+ steps:
528
+ - uses: actions/checkout@v3
529
+ with:
530
+ ref: ${{ github.head_ref }}
531
+ - uses: supabase/setup-cli@v1
532
+ with:
533
+ version: latest
534
+ - name: Backup roles
535
+ run: supabase db dump --db-url "$supabase_db_url" -f roles.sql --role-only
536
+ - name: Backup schema
537
+ run: supabase db dump --db-url "$supabase_db_url" -f schema.sql
538
+ - name: Backup data
539
+ run: supabase db dump --db-url "$supabase_db_url" -f data.sql --data-only --use-copy
540
+
541
+ - uses: stefanzweifel/git-auto-commit-action@v4
542
+ with:
543
+ commit_message: Supabase backup
544
+ ```
545
+
546
+ ### Explicação line-by-line
547
+
548
+ - **`on: schedule: cron: '0 0 * * *'`** — roda diariamente à meia-noite UTC; cron canônico de backup periódico
549
+ - **`on: push/pull_request: branches: [main]`** — backup também em push/PR para main (extra trigger de safety net)
550
+ - **`workflow_dispatch`** — re-run manual via Actions tab
551
+ - **`permissions: contents: write`** — necessário para `git-auto-commit-action` push de volta ao repo
552
+ - **`actions/checkout@v3 with: ref: ${{ github.head_ref }}`** — checkout do branch do PR (não default branch)
553
+ - **`supabase/setup-cli@v1`** — instala CLI
554
+ - **`supabase db dump --db-url "$supabase_db_url" -f roles.sql --role-only`** — Dump 1: apenas Postgres roles (CREATE ROLE statements)
555
+ - **`supabase db dump --db-url "$supabase_db_url" -f schema.sql`** — Dump 2: schema completo (CREATE TABLE, INDEX, FUNCTION, etc.)
556
+ - **`supabase db dump --db-url "$supabase_db_url" -f data.sql --data-only --use-copy`** — Dump 3: apenas dados (INSERT/COPY statements); `--use-copy` é mais rápido para tabelas grandes
557
+ - **`stefanzweifel/git-auto-commit-action@v4 with: commit_message: Supabase backup`** — auto-commit dos 3 arquivos `.sql` se houver diferenças
558
+
559
+ ### Por que 3 dumps separados — isolation de concerns
560
+
561
+ | Arquivo | Conteúdo | Por que separar |
562
+ |---------|----------|-----------------|
563
+ | `roles.sql` | CREATE ROLE statements | Roles são lifecycle separado do schema — review independente; cross-ref skill `supabase-postgres-roles` (v1.26) |
564
+ | `schema.sql` | CREATE TABLE, INDEX, FUNCTION, RLS policies, GRANTs | Schema cabe em git diff legível — review de mudanças facilitada |
565
+ | `data.sql` | INSERT/COPY de dados | Arquivo grande; restaurável independente do schema; permite restaurar dados sem alterar schema |
566
+
567
+ ### Caveats adicionais
568
+
569
+ - **Rotação de backups** — git não trunca automaticamente; arquivo `data.sql` cresce indefinidamente. Mitigação: criar branch dedicado `supabase-backups` + workflow separado para rotation (`git filter-repo` periódico)
570
+ - **Retention policy externa** — para compliance LGPD/GDPR (cross-ref skill `lgpd-multi-tenant-compliance` v1.21), considerar backup paralelo a S3 com lifecycle policy (delete após 30/90 dias)
571
+ - **Criptografia adicional para PII** — git-crypt encripta arquivos no repo (chave separada em vault corporativo); GPG é alternativa para encryption-at-rest
572
+ - **Restore procedure documentado** — backup sem restore testado é pior que sem backup; documentar em runbook (`.planning/RUNBOOK.md`) o processo de restore
573
+ - **Frequência** — `cron '0 0 * * *'` = 1× por dia midnight UTC. Para alta criticidade, considere `0 */6 * * *` (6h) ou `0 */4 * * *` (4h)
574
+ - **Branching workflow** — backup workflow roda no project **principal** (production), não em preview branches; verificar `SUPABASE_DB_URL` aponta para production
575
+
576
+ ### Diferença vs Supabase managed backups
577
+
578
+ Supabase Pro plan oferece **PITR (Point-in-Time Recovery)** managed — backup contínuo até 7 dias atrás. Workflow `backup.yml` é **complementar** (não substituto):
579
+
580
+ | | PITR managed (Supabase) | backup.yml (custom) |
581
+ |---|---|---|
582
+ | Frequência | Contínuo (WAL streaming) | Daily midnight |
583
+ | Retention | 7-28 dias (depende do plan) | Indefinido (git history) |
584
+ | Custo | Incluído no Pro plan | GitHub Actions minutes + repo storage |
585
+ | Granularidade | Point-in-time (segundo) | Daily snapshot |
586
+ | Visibilidade | Dashboard apenas | Git diff visível |
587
+ | Caso de uso | Disaster recovery rápido | Audit trail + cross-region backup |
588
+
589
+ Recomendação canônica: usar **AMBOS** — PITR para recovery operacional, `backup.yml` para audit trail histórico.
590
+
591
+ > ## WARNING CANÔNICO (REPETIDO)
592
+ >
593
+ > **Never backup your data to a public repository.**
594
+ >
595
+ > Mesmo workflow privado pode acidentalmente expor backup se o repo for tornado público posteriormente. Verificar via:
596
+ >
597
+ > 1. **Settings → General → Danger Zone → "Change repository visibility"** está em **Private**
598
+ > 2. **Settings → Branches → Branch protection** restringe push para `main`
599
+ > 3. **Auditar org members** com `Admin` permission no repo (podem mudar visibility)
600
+ > 4. **Considerar repo DEDICADO para backups** — separar de código fonte; reduz surface area de exposição acidental
601
+
602
+ ## Pattern 8: `notify-failure.yaml` — propagate Supabase Preview check failure (CI-08)
603
+
604
+ Workflow que **propaga** o status do check "Supabase Preview" (gerado pelo Supabase Branching GitHub integration, cross-ref Phase 149 Pattern 3) para o status final do PR:
605
+
606
+ ```yaml
607
+ name: Branch Status
608
+
609
+ on:
610
+ pull_request:
611
+ types:
612
+ - opened
613
+ - reopened
614
+ - synchronize
615
+ branches:
616
+ - main
617
+ - develop
618
+ paths:
619
+ - 'supabase/**'
620
+
621
+ jobs:
622
+ failed:
623
+ runs-on: ubuntu-latest
624
+ steps:
625
+ - uses: fountainhead/action-wait-for-check@v1.2.0
626
+ id: check
627
+ with:
628
+ checkName: Supabase Preview
629
+ ref: ${{ github.event.pull_request.head.sha || github.sha }}
630
+ token: ${{ secrets.GITHUB_TOKEN }}
631
+
632
+ - if: ${{ steps.check.outputs.conclusion == 'failure' }}
633
+ run: exit 1
634
+ ```
635
+
636
+ ### Explicação line-by-line
637
+
638
+ - **`on: pull_request: types: [opened, reopened, synchronize]`** — trigger em todos eventos PR relevantes
639
+ - **`on: pull_request: branches: [main, develop]`** — apenas PRs targeting main ou develop (filtra noise de feature → feature PRs)
640
+ - **`on: pull_request: paths: ['supabase/**']`** — apenas PRs que tocam `supabase/` (filtra PRs de docs/frontend que não trigam Supabase Preview)
641
+ - **`fountainhead/action-wait-for-check@v1.2.0`** — third-party action que espera um check específico aparecer no commit + retorna `conclusion`
642
+ - **`checkName: Supabase Preview`** — nome do check gerado pelo Supabase GitHub integration (gerado automaticamente quando preview branch é criado)
643
+ - **`ref: ${{ github.event.pull_request.head.sha || github.sha }}`** — SHA do commit alvo (head do PR ou SHA do push); fallback `github.sha` cobre edge cases
644
+ - **`token: ${{ secrets.GITHUB_TOKEN }}`** — token automático do GitHub Actions (sem precisar configurar secret manual)
645
+ - **`if: ${{ steps.check.outputs.conclusion == 'failure' }} run: exit 1`** — falha o workflow se Supabase Preview falhou
646
+
647
+ ### Por que separar este workflow
648
+
649
+ Sem este workflow:
650
+
651
+ - "Supabase Preview" check aparece como external check no PR
652
+ - Status mostra falha **isolado**, mas merge button pode estar habilitado se branch protection não selecionou explicitamente "Supabase Preview"
653
+
654
+ Com este workflow:
655
+
656
+ - `notify-failure / failed` aparece como check **do próprio repo**
657
+ - Branch protection rule "require status checks" pode selecionar `notify-failure / failed`
658
+ - Sem ✓ verde em `notify-failure / failed` → merge bloqueado mesmo se merge button parece habilitado
659
+
660
+ ### Caveats canônicos
661
+
662
+ - **`fountainhead/action-wait-for-check` é third-party** — auditar versão pinada (`@v1.2.0` específico, não `@v1`); supply chain attack surface
663
+ - **Timeout** — action default espera até timeout do workflow (60min); para reduzir, usar `timeoutSeconds: 600` no with
664
+ - **Check name exato** — `Supabase Preview` deve match exato (case-sensitive); se Supabase muda o nome do check, este workflow quebra silenciosamente
665
+ - **`paths` filter** — se PR não tocar `supabase/`, workflow não roda, mas check fica ausente → branch protection pode bloquear merge incorretamente. Mitigação: usar `paths-ignore` em vez de `paths` para inverter lógica
666
+
667
+ ### Required checks recomendados em branch protection (main)
668
+
669
+ Lista canônica de required checks após adotar todos os workflows desta skill:
670
+
671
+ 1. `CI / test` (Pattern 1)
672
+ 2. `generate-types / build` (Pattern 4)
673
+ 3. `database-tests / build` (Pattern 5)
674
+ 4. `functions-tests / build` (Pattern 6)
675
+ 5. `notify-failure / failed` (Pattern 8 — propaga Supabase Preview)
676
+
677
+ Workflows que NÃO devem ser required:
678
+ - `Supa-backup` (Pattern 7) — backup é write side-effect; falha ≠ bloquear merge
679
+ - `Deploy Migrations to Staging` (Pattern 2) — deploy só após merge
680
+ - `Deploy Migrations to Production` (Pattern 3) — deploy só após merge
681
+
682
+ ## Anti-patterns
683
+
684
+ ### Anti-pattern 1: Backup em repo público
685
+
686
+ **Errado:**
687
+
688
+ ```yaml
689
+ # .github/workflows/backup.yml em repo PÚBLICO
690
+ - name: Backup data
691
+ run: supabase db dump --db-url "$supabase_db_url" -f data.sql --data-only --use-copy
692
+ - uses: stefanzweifel/git-auto-commit-action@v4
693
+ ```
694
+
695
+ Workflow funciona, mas repo é público — `data.sql` committed contém **todos os dados** (emails, hashed passwords, PII).
696
+
697
+ **Por quê:** dados sensíveis ficam expostos publicamente para sempre (git history é permanente); compliance LGPD/GDPR violado; surface de ataque massiva (qualquer um pode clonar e analisar offline); breach notification obrigatória.
698
+
699
+ **Certo:**
700
+
701
+ 1. **Repo PRIVADO** — `Settings → General → Danger Zone → Visibility: Private`
702
+ 2. **Verificar via API:**
703
+ ```bash
704
+ gh repo view <org>/<repo> --json visibility
705
+ # esperado: {"visibility": "PRIVATE"}
706
+ ```
707
+ 3. **Auditar admins** com permissão para mudar visibility — restringir
708
+ 4. **Para PII regulado** — git-crypt encryption-at-rest:
709
+ ```bash
710
+ git-crypt init
711
+ git-crypt add-gpg-user user@company.com
712
+ # .gitattributes:
713
+ # *.sql filter=git-crypt diff=git-crypt
714
+ ```
715
+ 5. **Considerar repo DEDICADO** apenas para backups (não compartilhar com código fonte) — reduz surface area de exposição acidental
716
+
717
+ ### Anti-pattern 2: Schema changes direto no remote (bypass migration history)
718
+
719
+ **Errado:**
720
+
721
+ ```bash
722
+ # dev faz mudança via Dashboard SQL Editor em production
723
+ ALTER TABLE users ADD COLUMN avatar_url text;
724
+
725
+ # nenhuma migration arquivo criada
726
+ # supabase_migrations.schema_migrations sem entry para esta mudança
727
+ ```
728
+
729
+ Próximo `db push` via workflow (Pattern 2 ou 3):
730
+
731
+ - CLI compara local migrations vs remote `schema_migrations` — não detecta a mudança "fantasma" feita via Dashboard
732
+ - Migration subsequente pode falhar se assume estado anterior do schema
733
+
734
+ **Por quê:** quebra migration history → drift entre git e DB → próximas migrations falham com `column already exists` ou similar → debugging pesadelo; rollback impossível porque a mudança não tem migration reversa.
735
+
736
+ **Certo:**
737
+
738
+ 1. **Sempre criar migration** via CLI:
739
+ ```bash
740
+ supabase migration new add_avatar_url_to_users
741
+ # editar arquivo gerado em supabase/migrations/YYYYMMDDHHmmss_add_avatar_url_to_users.sql:
742
+ # alter table public.users add column avatar_url text;
743
+ ```
744
+ 2. **Aplicar via PR** + workflow Pattern 1 (CI) valida + workflow Pattern 3 (production.yml) aplica
745
+ 3. **Se mudança emergencial via Dashboard foi inevitável** — criar migration arquivo retrospectivo + usar `supabase migration repair` (cross-ref skill futura `supabase-migration-repair` Phase 153) para sincronizar history
746
+
747
+ ### Anti-pattern 3: Concurrent `db push` from different machines
748
+
749
+ **Errado:** dois devs rodam `supabase db push` simultaneamente — um do laptop, outro do GitHub Actions workflow:
750
+
751
+ ```bash
752
+ # Dev A — laptop
753
+ $ supabase db push
754
+ # aplicando migration_001...
755
+
756
+ # Workflow (paralelo)
757
+ $ supabase db push
758
+ # também aplicando migration_001...
759
+ ```
760
+
761
+ **Por quê:** race condition em `supabase_migrations.schema_migrations` — duas conexões competem por lock, podem inserir duplicates, corromper history, ou deixar migration aplicada parcialmente; debugging pesadelo (state inconsistente entre history e schema real).
762
+
763
+ **Certo:**
764
+
765
+ 1. **Workflows GitHub Actions são source of truth** — devs NÃO rodam `db push` em production manualmente
766
+ 2. **Concurrency control nos workflows:**
767
+ ```yaml
768
+ # staging.yml e production.yml
769
+ concurrency:
770
+ group: deploy-${{ github.workflow }}
771
+ cancel-in-progress: false
772
+ ```
773
+ `cancel-in-progress: false` enfileira execuções em vez de cancelar → previne race
774
+ 3. **Para emergencial** — anunciar no Slack `#engineering` antes; verificar via Actions tab que nenhum workflow está running
775
+
776
+ ### Anti-pattern 4: Secrets sem encryption nas configurações GitHub (plaintext em workflow)
777
+
778
+ **Errado:**
779
+
780
+ ```yaml
781
+ # .github/workflows/staging.yml
782
+ jobs:
783
+ deploy:
784
+ runs-on: ubuntu-latest
785
+ env:
786
+ SUPABASE_DB_PASSWORD: my-actual-password-here # PLAINTEXT
787
+ SUPABASE_ACCESS_TOKEN: sbp_actual_token_here # PLAINTEXT
788
+ ```
789
+
790
+ **Por quê:** workflow file é committed em git → password e access token expostos publicamente em git history → mesmo se removidos depois, git log preserva → rotação manual necessária + compromisso de qualquer secret encontrado.
791
+
792
+ **Certo:**
793
+
794
+ 1. **Sempre via `secrets`:**
795
+ ```yaml
796
+ env:
797
+ SUPABASE_DB_PASSWORD: ${{ secrets.STAGING_DB_PASSWORD }}
798
+ SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
799
+ ```
800
+ 2. **Configurar via UI:** `Settings → Secrets and variables → Actions → New repository secret`
801
+ 3. **Auditar histórico** — buscar acidentes:
802
+ ```bash
803
+ git log -p | grep -E '(password|token|secret|key)' | head -50
804
+ ```
805
+ 4. **Se vazou:** rotacionar TODOS os secrets imediatamente (Dashboard → reset DB password + revoke access token + create new token + update GitHub secret)
806
+
807
+ ### Anti-pattern 5: Workflows sem `concurrency` control causando race em deploy
808
+
809
+ **Errado:** dois PRs mergem para `main` em rápida sucessão; workflow `production.yml` dispara 2× concorrentemente:
810
+
811
+ ```yaml
812
+ # production.yml SEM concurrency
813
+ on:
814
+ push:
815
+ branches: [main]
816
+ ```
817
+
818
+ PR #100 mergeado → workflow run #1 inicia → ainda rodando.
819
+ PR #101 mergeado → workflow run #2 inicia paralelo → `db push` concorrente → race em `supabase_migrations.schema_migrations`.
820
+
821
+ **Por quê:** Anti-pattern 3 manifestado em produção real; corrupção de migration history em produção; pode resultar em deploy parcial → schema inconsistente → app quebra.
822
+
823
+ **Certo:**
824
+
825
+ ```yaml
826
+ # production.yml COM concurrency
827
+ on:
828
+ push:
829
+ branches: [main]
830
+
831
+ concurrency:
832
+ group: deploy-production
833
+ cancel-in-progress: false # enfileira, não cancela
834
+ ```
835
+
836
+ `cancel-in-progress: false` é canônico — cancel-in-progress: true poderia abortar uma migration aplicação parcial → estado pior.
837
+
838
+ ## Cross-suite integration (v1.27)
839
+
840
+ Esta skill é o **3º pilar do CI/CD canônico Supabase**:
841
+
842
+ - **`supabase-branching-workflow` (Phase 149)** — descreve **quando** preview branches são criados (PR webhook → branch DB isolado)
843
+ - **`supabase-config-toml-remotes` (Phase 150)** — descreve **como** configurar branch-specific overrides + secrets per-branch
844
+ - **`supabase-ci-cd-github-actions` (Phase 151, ESTA)** — descreve **como** automatizar via GitHub Actions workflows
845
+
846
+ Cross-refs com skills futuras v1.27:
847
+
848
+ - **`supabase-pgtap-testing` (Phase 152, futura)** — detalhes completos pgTAP que CI-05 (`database-tests.yml`) executa
849
+ - **`supabase-migration-repair` (Phase 153, futura)** — `migration repair` em workflow para recovery quando `db push` falha drift
850
+
851
+ Cross-refs com skills existentes v1.x:
852
+
853
+ - **`hermetic-builds`** — auditar workflows GitHub Actions para reproducibility (`actions/checkout@v4` pinado, `supabase/setup-cli@v1` pinado, `denoland/setup-deno@v2` pinado, lockfile committed)
854
+ - **`release-engineering`** — deployment philosophy (canary, feature flags, gradual rollout); `production.yml` Pattern 3 é deploy automático que pode evoluir para tag-based
855
+ - **`eliminating-toil`** — workflows substituem toil manual (deploy manual → automated push; backup manual → cron midnight)
856
+ - **`supabase-migrations` (v1.23)** — migration arquivos que `db push` consome
857
+ - **`supabase-postgres-roles` (v1.26)** — roles dumps em `backup.yml` Pattern 7
858
+
859
+ Base para agent novo v1.27:
860
+
861
+ - **`supabase-cicd-pipeline-implementer` (Phase 154, futura)** — recebe spec via `Task()` e materializa `.github/workflows/*.yml` + `[remotes.<branch>]` blocks + secrets configuration
862
+
863
+ Pattern de handoff cooperativo herdado v1.23-v1.26: **architect** projeta strategy → **cicd-pipeline-implementer** materializa workflows → **release-pipeline-auditor** (v1.10) audita hermeticidade do pipeline final. Nenhum agente descarta upstream — handoff cooperativo (princípio canônico v1.23).
864
+
865
+ ## Ver também
866
+
867
+ - [supabase-branching-workflow](../supabase-branching-workflow/SKILL.md) (v1.27, Phase 149) — preview branches que ci.yml + notify-failure.yaml validam
868
+ - [supabase-config-toml-remotes](../supabase-config-toml-remotes/SKILL.md) (v1.27, Phase 150) — secrets management dotenvx + `[remotes]` blocks per-branch que workflows consomem
869
+ - [supabase-pgtap-testing](../supabase-pgtap-testing/SKILL.md) (v1.27, Phase 152, futura) — sintaxe pgTAP + setup que database-tests.yml roda
870
+ - [supabase-migration-repair](../supabase-migration-repair/SKILL.md) (v1.27, Phase 153, futura) — recovery quando db push falha em CI por drift
871
+ - [supabase-migrations](../supabase-migrations/SKILL.md) (v1.23) — migration files que db push aplica
872
+ - [supabase-postgres-roles](../supabase-postgres-roles/SKILL.md) (v1.26) — roles dumps em backup.yml Pattern 7
873
+ - [supabase-edge-functions](../supabase-edge-functions/SKILL.md) — Edge Functions que functions-tests.yml testa via Deno
874
+ - [hermetic-builds](../hermetic-builds/SKILL.md) — auditar workflows para reproducibility (actions pinned + lockfile + frozen-install)
875
+ - [release-engineering](../release-engineering/SKILL.md) — deployment philosophy + canary + rollback strategies
876
+ - [eliminating-toil](../eliminating-toil/SKILL.md) — workflows substituem toil manual (deploy + backup + types regen)
877
+ - [evolucao-schema-compativel](../evolucao-schema-compativel/SKILL.md) (v1.22) — 3-step migration safe pattern para mudanças destrutivas em production.yml
878
+ - [lgpd-multi-tenant-compliance](../lgpd-multi-tenant-compliance/SKILL.md) (v1.21) — backup criptografado per-tenant para compliance LGPD
879
+ - [glossário compartilhado](../_shared-supabase/glossary.md) — termos GitHub Actions Supabase, ci.yml, staging.yml, production.yml, backup 3-dump, fountainhead/action-wait-for-check, never backup to public repo
880
+ - Doc oficial: [Supabase GitHub Actions](https://supabase.com/docs/guides/deployment/ci), [GitHub Actions docs](https://docs.github.com/en/actions), [denoland/setup-deno](https://github.com/denoland/setup-deno), [stefanzweifel/git-auto-commit-action](https://github.com/stefanzweifel/git-auto-commit-action), [fountainhead/action-wait-for-check](https://github.com/fountainhead/action-wait-for-check)