首页

环境管理

使用数据库迁移和GitHub Actions管理多环境部署。


本指南将向您展示如何设置本地Supabase开发环境,并与GitHub Actions集成,实现自动测试并将模式变更发布到Supabase的暂存和生产环境。

设置本地环境

第一步是使用Supabase CLI初始化本地仓库:

1
supabase init

您会看到新建的supabase目录。接着需要将本地仓库与Supabase项目关联:

1
2
supabase loginsupabase link --project-ref $PROJECT_ID

可以从项目仪表盘的URL获取$PROJECT_ID

1
https://supabase.com/dashboard/project/<project-id>

如果使用的是现有Supabase项目,可能已通过仪表盘做过模式变更。 在通过CLI进行本地模式变更前,请运行以下命令拉取这些变更:

1
supabase db pull

该命令会在supabase/migrations/<timestamp>_remote_schema.sql中创建新迁移文件,反映您之前所做的模式变更。

现在提交本地变更到Git并运行本地开发设置:

1
2
3
git add .git commit -m "init supabase"supabase start

现在您已准备好本地开发模式变更并创建第一个迁移了。

创建新迁移

有两种方式进行模式变更:

  1. 手动迁移:手动将DDL语句写入迁移文件
  2. 自动模式差异:通过Studio UI进行变更并自动生成模式差异

手动迁移

通过运行以下命令创建新的迁移脚本:

1
supabase migration new new_employee

您将看到一个新文件被创建:supabase/migrations/<timestamp>_new_employee.sql。然后您可以使用文本编辑器在此脚本中编写SQL语句:

1
2
3
4
create table public.employees ( id integer primary key generated always as identity, name text);

将新迁移应用到本地数据库:

1
supabase db reset

此命令会从头开始重新创建本地数据库,并应用supabase/migrations目录下的所有迁移脚本。现在您的本地数据库已是最新状态。

自动模式差异

与手动迁移不同,自动模式差异会从已经应用到本地数据库的变更中创建新的迁移脚本。

首先使用 Studio UI 在 public 模式下创建一个 employees 表,默认可通过 localhost:54323 访问。

接下来,运行以下命令生成模式差异:

1
supabase db diff -f new_employee

您会看到一个新文件 supabase/migrations/<时间戳>_new_employee.sql 被创建。打开该文件并验证生成的 DDL 语句是否与下方一致。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
-- 此脚本由 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,您就可以准备部署了。

部署迁移

在生产环境中,我们推荐使用 CI/CD 流水线通过 GitHub Actions 来部署新的迁移,而不是从本地机器直接部署。

本示例使用两个 Supabase 项目,一个用于生产环境,一个用于预发布环境。

准备环境的步骤如下:

  • 为预发布和生产环境创建独立的 Supabase 项目
  • 将 git 仓库推送到 GitHub 并启用 GitHub Actions

配置 GitHub Actions

Supabase CLI 在非交互模式下运行需要几个环境变量:

  • SUPABASE_ACCESS_TOKEN 是您的个人访问令牌
  • SUPABASE_DB_PASSWORD 是项目特定的数据库密码
  • SUPABASE_PROJECT_ID 是项目特定的引用字符串

我们建议将这些变量作为加密密钥添加到您的 GitHub Actions 运行器中。

.github/workflows 目录下创建以下文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
name: 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 和发布工作流,这些工作流会在向 maindevelop 分支推送新提交时触发。

正确配置的仓库

提交包含新迁移的 PR

按照迁移步骤创建 supabase/migrations/<timestamp>_new_employee.sql 文件。

develop 分支签出新分支 feat/employee,提交迁移文件并推送到 GitHub。

1
2
3
4
git checkout -b feat/employeegit add supabase/migrations/<timestamp>_new_employee.sqlgit commit -m "添加员工表"git push --set-upstream origin feat/employee

feat/employeedevelop 分支开启 PR,观察 CI 工作流是否被触发。

测试错误解决后,合并此 PR 并观察部署过程。

发布到生产环境

验证您的预发布项目成功迁移后,创建另一个从 developmain 的 PR,合并后将迁移部署到生产项目。

release 作业会将 supabase/migrations 目录中所有新合并的迁移脚本应用到关联的 Supabase 项目。您可以通过 PROJECT_ID 环境变量控制作业关联的项目。

故障排查

将生产项目同步到预发布环境

在设置新的预发布项目时,可能需要将初始模式与之前应用于生产项目的迁移同步。

一种方法是利用 Release 工作流:

  • 创建新分支 develop 并选择 main 作为分支源
  • develop 分支推送到 GitHub

GitHub Actions 运行器会将您现有的迁移部署到预发布项目。

或者,您也可以通过本地 CLI 将迁移应用到关联的远程数据库。

1
supabase db push

推送完成后,检查本地和远程数据库的迁移版本是否最新。

1
supabase migration list

执行 db pull 时出现权限拒绝错误

如果您长期使用 Supabase 托管项目,在执行 db pull 命令时可能会遇到以下权限错误:

1
2
3
Error: 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 编辑器中运行以下查询来实现:

1
2
3
grant 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 语句,在应用到预发布或生产数据库时可能会遇到权限错误:

1
ERROR: must be owner of table employees (SQLSTATE 42501); while executing migration <timestamp>

这是因为通过 Supabase 仪表板创建的表归 supabase_admin 角色所有,而通过 CLI 执行的迁移脚本是以 postgres 角色运行的。

解决方法之一是将这些表的所有者重新分配给 postgres 角色。例如,如果您的表名为 users 且位于 public 模式中,可以运行以下命令重新分配所有者:

1
ALTER TABLE users OWNER TO postgres;

除了表之外,您还需要使用相应的命令重新分配其他实体的所有者,包括类型函数模式

重新基址新迁移

有时您的队友可能将新的迁移文件合并到 git 主分支,现在您需要将本地模式变更重新基于这些新变更之上。

我们可以通过用新的时间戳重命名旧迁移文件来优雅处理这种情况。

1
2
3
4
5
6
git 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。