环境管理
使用数据库迁移和GitHub Actions管理多环境部署。
本指南将向您展示如何设置本地Supabase开发环境,并与GitHub Actions集成,实现自动测试并将模式变更发布到Supabase的暂存和生产环境。
设置本地环境
第一步是使用Supabase CLI初始化本地仓库:
1supabase init
您会看到新建的supabase
目录。接着需要将本地仓库与Supabase项目关联:
12supabase loginsupabase link --project-ref $PROJECT_ID
可以从项目仪表盘的URL获取$PROJECT_ID
:
1https://supabase.com/dashboard/project/<project-id>
如果使用的是现有Supabase项目,可能已通过仪表盘做过模式变更。 在通过CLI进行本地模式变更前,请运行以下命令拉取这些变更:
1supabase db pull
该命令会在supabase/migrations/<timestamp>_remote_schema.sql
中创建新迁移文件,反映您之前所做的模式变更。
现在提交本地变更到Git并运行本地开发设置:
123git add .git commit -m "init supabase"supabase start
现在您已准备好本地开发模式变更并创建第一个迁移了。
创建新迁移
有两种方式进行模式变更:
- 手动迁移:手动将DDL语句写入迁移文件
- 自动模式差异:通过Studio UI进行变更并自动生成模式差异
手动迁移
通过运行以下命令创建新的迁移脚本:
1supabase migration new new_employee
您将看到一个新文件被创建:supabase/migrations/<timestamp>_new_employee.sql
。然后您可以使用文本编辑器在此脚本中编写SQL语句:
1234create table public.employees ( id integer primary key generated always as identity, name text);
将新迁移应用到本地数据库:
1supabase db reset
此命令会从头开始重新创建本地数据库,并应用supabase/migrations
目录下的所有迁移脚本。现在您的本地数据库已是最新状态。
新的迁移命令也支持从stdin输入。这允许您从其他文件或stdout管道传入现有脚本:
supabase migration new new_employee < create_employees_table.sql
自动模式差异
与手动迁移不同,自动模式差异会从已经应用到本地数据库的变更中创建新的迁移脚本。
首先使用 Studio UI 在 public
模式下创建一个 employees
表,默认可通过 localhost:54323 访问。
接下来,运行以下命令生成模式差异:
1supabase db diff -f new_employee
您会看到一个新文件 supabase/migrations/<时间戳>_new_employee.sql
被创建。打开该文件并验证生成的 DDL 语句是否与下方一致。
123456789101112131415161718192021222324-- 此脚本由 pgAdmin 4 中的 Schema Diff 工具生成-- 对于循环依赖,Schema Diff 写入对象的顺序不够智能-- 可能需要手动修改脚本以确保变更按正确顺序应用-- 如遇任何失败,请提交问题并附上重现步骤CREATE TABLE IF NOT EXISTS public.employees( id integer NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ), name text COLLATE pg_catalog."default", CONSTRAINT employees_pkey PRIMARY KEY (id))TABLESPACE pg_default;ALTER TABLE IF EXISTS public.employees OWNER to postgres;GRANT ALL ON TABLE public.employees TO anon;GRANT ALL ON TABLE public.employees TO authenticated;GRANT ALL ON TABLE public.employees TO postgres;GRANT ALL ON TABLE public.employees TO service_role;
您可能会注意到自动生成的迁移脚本比手动编写的更为冗长。 这是因为默认的模式差异工具没有考虑初始模式添加的默认权限。
将新的迁移脚本提交到 git,您就可以准备部署了。
作为替代方案,您可以传入 --use-migra
实验性标志,使用 migra
生成更简洁的迁移。
如果不使用 -f
文件标志,默认会将输出写入 stdout。
supabase db diff --use-migra
部署迁移
在生产环境中,我们推荐使用 CI/CD 流水线通过 GitHub Actions 来部署新的迁移,而不是从本地机器直接部署。
本示例使用两个 Supabase 项目,一个用于生产环境,一个用于预发布环境。
准备环境的步骤如下:
- 为预发布和生产环境创建独立的 Supabase 项目
- 将 git 仓库推送到 GitHub 并启用 GitHub Actions
您需要一个_全新_的项目作为预发布环境。不能使用已经修改过以反映生产项目架构的项目,因为 CLI 会重新应用这些变更。
配置 GitHub Actions
Supabase CLI 在非交互模式下运行需要几个环境变量:
SUPABASE_ACCESS_TOKEN
是您的个人访问令牌SUPABASE_DB_PASSWORD
是项目特定的数据库密码SUPABASE_PROJECT_ID
是项目特定的引用字符串
我们建议将这些变量作为加密密钥添加到您的 GitHub Actions 运行器中。
在 .github/workflows
目录下创建以下文件:
12345678910111213141516171819202122232425262728name: CIon: pull_request: workflow_dispatch:jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: supabase/setup-cli@v1 with: version: latest - name: Start Supabase local development setup run: supabase db start - name: Verify generated types are checked in run: | supabase gen types typescript --local > types.gen.ts if ! git diff --ignore-space-at-eol --exit-code --quiet types.gen.ts; then echo "Detected uncommitted changes after build. See status below:" git diff exit 1 fi
完整示例代码可在演示仓库中获取。
将这些文件提交到 git 并推送到 GitHub 的 main
分支。更新以下环境变量以匹配您的 Supabase 项目:
SUPABASE_ACCESS_TOKEN
PRODUCTION_PROJECT_ID
PRODUCTION_DB_PASSWORD
STAGING_PROJECT_ID
STAGING_DB_PASSWORD
正确配置后,您的仓库将拥有 CI 和发布工作流,这些工作流会在向 main
和 develop
分支推送新提交时触发。
提交包含新迁移的 PR
按照迁移步骤创建 supabase/migrations/<timestamp>_new_employee.sql
文件。
从 develop
分支签出新分支 feat/employee
,提交迁移文件并推送到 GitHub。
1234git checkout -b feat/employeegit add supabase/migrations/<timestamp>_new_employee.sqlgit commit -m "添加员工表"git push --set-upstream origin feat/employee
从 feat/employee
向 develop
分支开启 PR,观察 CI 工作流是否被触发。
测试错误解决后,合并此 PR 并观察部署过程。
发布到生产环境
验证您的预发布项目成功迁移后,创建另一个从 develop
到 main
的 PR,合并后将迁移部署到生产项目。
release
作业会将 supabase/migrations
目录中所有新合并的迁移脚本应用到关联的 Supabase 项目。您可以通过 PROJECT_ID
环境变量控制作业关联的项目。
故障排查
将生产项目同步到预发布环境
在设置新的预发布项目时,可能需要将初始模式与之前应用于生产项目的迁移同步。
一种方法是利用 Release 工作流:
- 创建新分支
develop
并选择main
作为分支源 - 将
develop
分支推送到 GitHub
GitHub Actions 运行器会将您现有的迁移部署到预发布项目。
或者,您也可以通过本地 CLI 将迁移应用到关联的远程数据库。
1supabase db push
推送完成后,检查本地和远程数据库的迁移版本是否最新。
1supabase migration list
执行 db pull
时出现权限拒绝错误
如果您长期使用 Supabase 托管项目,在执行 db pull
命令时可能会遇到以下权限错误:
123Error: Error running pg_dump on remote database: pg_dump: error: query failed: ERROR: permission denied for table _typepg_dump: error: query was: LOCK TABLE "graphql"."_type" IN ACCESS SHARE MODE
要解决此错误,您需要为 postgres
角色授予 graphql
模式的权限。可以通过在 Supabase 仪表板的 SQL 编辑器中运行以下查询来实现:
123grant all on all tables in schema graphql to postgres, anon, authenticated, service_role;grant all on all functions in schema graphql to postgres, anon, authenticated, service_role;grant all on all sequences in schema graphql to postgres, anon, authenticated, service_role;
执行 db push
时出现权限拒绝错误
如果您通过 Supabase 仪表板创建了表,而新的迁移脚本包含 ALTER TABLE
语句,在应用到预发布或生产数据库时可能会遇到权限错误:
1ERROR: must be owner of table employees (SQLSTATE 42501); while executing migration <timestamp>
这是因为通过 Supabase 仪表板创建的表归 supabase_admin
角色所有,而通过 CLI 执行的迁移脚本是以 postgres
角色运行的。
解决方法之一是将这些表的所有者重新分配给 postgres
角色。例如,如果您的表名为 users
且位于 public 模式中,可以运行以下命令重新分配所有者:
1ALTER TABLE users OWNER TO postgres;
除了表之外,您还需要使用相应的命令重新分配其他实体的所有者,包括类型、函数和模式。
重新基址新迁移
有时您的队友可能将新的迁移文件合并到 git 主分支,现在您需要将本地模式变更重新基于这些新变更之上。
我们可以通过用新的时间戳重命名旧迁移文件来优雅处理这种情况。
123456git pullsupabase migration new dev_A# 假设新文件是: supabase/migrations/<t+2>_dev_A.sqlmv <time>_dev_A.sql <t+2>_dev_A.sqlsupabase db reset
如果 reset
失败,您可以通过编辑 <t+2>_dev_A.sql
文件手动解决冲突。
本地验证通过后,将变更提交到 Git 并推送到 GitHub。