环境管理

概述

Supabase CLI 提供了你所需要的工具来管理多个环境。 本指南向您介绍如何设置您的本地 Supabase 开发环境,该环境与 GitHub Actions 集成,以自动 测试和发布模式变化到暂存和生产Supabase项目。

要开始使用。

  • 安装Supabase CLI](/docs/guides/cli)
  • 创建一个MemFire Cloud项目或使用一个现有的项目
  • 初始化一个本地的 Git 仓库

设置本地环境

第一步是用Supabase CLI设置你的本地存储库。

supabase init

你应该看到一个新的supabase目录。然后你需要将你的本地存储库与你的Supabase项目连接起来。

supabase login
supabase link --project-ref $PROJECT_ID

你可以从你项目的仪表盘URL中获得你的$PROJECT_ID

https://app.supabase.com/project/<project-id>

如果你正在使用一个现有的Supabase项目,你可能已经通过Dashboard进行了模式更改。 在从 CLI 进行本地模式更改之前,请运行下面的命令来提取这些更改。

1supabase db remote commit

这个命令在supabase/migrations/<timestamp>_remote_commit.sql中创建了一个新的迁移,反映了你之前所做的模式改变。

现在将你的本地修改提交给Git,并运行本地开发设置。

git add .
git commit -m "init supabase"
supabase start

现在你已经准备好在本地开发模式变化,并创建你的第一次迁移。

创建一个新的迁移

有两种方法可以对模式进行修改。

  1. 手动迁移。手动将DDL语句写进迁移文件
  2. 自动模式差异。通过Studio用户界面进行修改,并自动生成一个模式差异。

手动迁移

手动迁移

通过运行创建一个新的迁移脚本。

supabase migration new new_employee

你应该看到一个新的文件被创建。supabase/migrations/<timestamp>_new_employee.sql。然后你可以用文本编辑器在这个脚本中写SQL语句。

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

将新的迁移应用到你的本地数据库。

supabase db reset

这个命令从头开始重新创建你的本地数据库,并应用supabase/migrations目录下的所有迁移脚本。现在你的本地数据库是最新的了。

tip

新的迁移命令还支持stdin作为输入。 这允许你从另一个文件或stdout管入一个现有的脚本。

supabase migration new new_employee < create_employees_table.sql

自动模式差异

与手动迁移不同,自动模式差异是从已经应用于本地数据库的***变化中创建一个新的迁移脚本。

自动模式差异

使用Studio UI在 public模式下创建一个 employees表,默认情况下可以在localhost:54323访问。

接下来,通过运行以下命令生成一个模式差异。

supabase db diff -f new_employee

你应该看到一个新文件supabase/migrations/<timestamp>_new_employee.sql被创建。打开该文件并验证生成的DDL语句与下面的相同。

1-- This script was generated by the Schema Diff utility in pgAdmin 4
2-- For the circular dependencies, the order in which Schema Diff writes the objects is not very sophisticated
3-- and may require manual changes to the script to ensure changes are applied in the correct order.
4-- Please report an issue for any failure with the reproduction steps.
5
6CREATE TABLE IF NOT EXISTS public.employees
7(
8    id integer NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
9    name text COLLATE pg_catalog."default",
10    CONSTRAINT employees_pkey PRIMARY KEY (id)
11)
12
13TABLESPACE pg_default;
14
15ALTER TABLE IF EXISTS public.employees
16    OWNER to postgres;
17
18GRANT ALL ON TABLE public.employees TO anon;
19
20GRANT ALL ON TABLE public.employees TO authenticated;
21
22GRANT ALL ON TABLE public.employees TO postgres;
23
24GRANT ALL ON TABLE public.employees TO service_role;

你可能会注意到,自动生成的迁移脚本比手工编写的脚本更加冗长。 这是因为默认的模式差异工具并没有考虑到初始模式所增加的默认权限。

将新的迁移脚本提交到git,就可以进行部署了。

tip

另外,你也可以传入--use-migra实验性标志,使用migra生成一个更简洁的迁移。 如果没有-f文件标志,默认情况下输出会写到stdout。

supabase db diff --use-migra

部署迁移

在生产环境中,我们建议使用CI/CD管道来部署带有GitHub Actions的新迁移,而不是从你的本地机器上进行部署。

部署迁移

这个例子使用了两个Supabase项目,一个用于生产,一个用于暂存。

通过以下方式准备你的环境。

  • 创建独立的Supabase项目,用于暂存和生产
  • 将你的 git 仓库推送到 GitHub 并启用 GitHub 操作

caution

你需要一个新的项目来进行暂存。一个已经被修改以反映生产项目模式的项目不能被使用,因为CLI会重新应用这些修改。

配置GitHub操作#

Supabase CLI需要一些环境变量才能在非交互式模式下运行。

  • SUPABASE_ACCESS_TOKEN是你的个人访问令牌
  • SUPABASE_DB_PASSWORD是你的项目特定数据库密码

我们建议将这些作为加密的秘密添加到你的GitHub行动运行器中。

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

.github/workflows/ci.yml
1name: CI
2
3on:
4  pull_request:
5  workflow_dispatch:
6
7jobs:
8  test:
9    runs-on: ubuntu-22.04
10    steps:
11      - uses: actions/checkout@v3
12
13      - uses: supabase/setup-cli@v1
14        with:
15          version: 1.0.0
16
17      - name: Start Supabase local development setup
18        run: supabase start
19
20      - name: Verify generated types are up-to-date
21        run: |
22          supabase gen types typescript --local > types.ts
23          if [ "$(git diff --ignore-space-at-eol types.ts | wc -l)" -gt "0" ]; then
24            echo "Detected uncommitted changes after build. See status below:"
25            git diff
26            exit 1
27          fi

完整的示例代码可在demo repository中找到。

将这些文件提交到git,并推送到GitHub上的main分支。更新这些环境变量以匹配你的Supabase项目。

  • supabase_access_token
  • production_project_id(生产项目名称)
  • 生产数据库密码。
  • Staging_project_id
  • staging_db_password

当配置正确时,你的版本库将有CI和Release工作流,在推送到maindevelop分支的新提交时触发。

正确配置的版本库

用新的迁移方式打开一个PR#

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

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

git checkout -b feat/employee
git add supabase/migrations/<timestamp>_new_employee.sql
git commit -m "Add employee table"
git push --set-upstream origin feat/employee

feat/employee打开一个PR到develop分支,看看CI工作流程是否已经被触发。

一旦测试错误被解决,合并这个PR,观察部署的动作。

发布到生产

在确认你的暂存项目已经成功迁移后,从developmain创建另一个PR,并合并它,将迁移部署到生产项目中。

合并新的PR

release作业将所有合并在supabase/migrations目录下的新迁移脚本应用到一个被链接的Supabase项目。你可以通过PROJECT_ID环境变量来控制作业链接到哪个项目。

故障排除

将生产项目同步到暂存项目

在建立一个新的暂存项目时,你可能需要将初始模式与之前应用于生产项目的迁移同步。

一种方法是利用发布工作流程。

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

GitHub Actions runner会将你现有的迁移部署到暂存项目中。

另外,你也可以通过本地CLI将迁移应用到链接的远程数据库。

1supabase db push

一旦推送,检查本地和远程数据库的迁移版本是否为最新的。

1supabase migration list

db远程提交的权限被拒绝#

如果你已经使用Supabase托管的项目很长时间了,在执行db远程提交时可能会遇到以下权限错误。

Error: Error running pg_dump on remote database: pg_dump: error: query failed: ERROR:  permission denied for table _type

pg_dump: error: query was: LOCK TABLE "graphql"."_type" IN ACCESS SHARE MODE

为了解决这个错误,你需要授予postgres角色权限给graphql模式。你可以通过在Supabase仪表板的SQL编辑器中运行以下查询来实现。

1grant all on all tables in schema graphql to postgres, anon, authenticated, service_role;
2grant all on all functions in schema graphql to postgres, anon, authenticated, service_role;
3grant all on all sequences in schema graphql to postgres, anon, authenticated, service_role;

在数据库推送时被拒绝的权限

如果你通过Supabase仪表盘创建了一个表,并且你的新迁移脚本包含ALTER TABLE语句,当你在暂存数据库或生产数据库上应用这些语句时,可能会遇到权限错误。

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

这是因为通过Supabase仪表板创建的表是由supabase_admin角色拥有的,而通过CLI执行的迁移脚本是在postgres角色下。

解决这个问题的方法之一是将这些表的所有者重新分配给postgres角色。例如,如果你的表在公共模式中被命名为 "users",你可以运行以下命令来重新分配所有者。

1ALTER TABLE users OWNER TO postgres;

除了表之外,你还需要使用各自的命令来重新分配其他实体的所有者,包括types, function, 和schemas

重置新的迁移

有时候,你的队友可能会将一个新的迁移文件合并到git主分支上,现在你需要在上面重设你的本地模式修改。

Rebase on main

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

git pull
supabase migration new dev_A
# Assume the new file is: supabase/migrations/<t+2>_dev_A.sql
mv <time>_dev_A.sql <t+2>_dev_A.sql
supabase db reset

如果reset失败,你可以通过编辑<t+2>_dev_A.sql文件手动解决冲突。

本地验证后,将你的修改提交给Git并推送到GitHub。