使用 webhooks 管理多环境开发设置中的边缘功能

问题描述 投票:0回答:1

我目前正在开发一个在多个环境(本地、临时和生产)中使用 Supabase 的项目。我的开发工作流程包括:

1.  Developing locally with Supabase CLI.
2.  Deploying changes to a staging environment for testing.
3.  Finally, pushing to a production environment.

Supabase Webhook 似乎保留了创建它们的环境的 URL,导致在环境之间迁移时出现问题。例如,如果我在本地创建一个 Webhook,即使在部署到临时或生产环境后,它也会继续指向本地边缘函数。有没有办法根据环境动态设置 webhook URL 以确保它们始终指向正确的边缘函数?

postgresql development-environment supabase supabase-database edge-function
1个回答
-1
投票

在 Supabase 中跨多个环境管理 Webhook 和边缘功能的最佳方法是利用 Vault 进行特定于环境的配置,正如社区中的各种讨论所建议的那样。

第 1 步:设置保管库机密

对于生产,导航到 Supabase 项目的设置,然后转到 Vault 部分。在这里,您可以添加保存边缘函数的基本 URL 的密钥。此 URL 会根据环境而有所不同。

Create productiion vault secret

对于本地开发,您可以在设置的播种阶段创建此秘密。将以下 SQL 添加到您的种子文件中:

SELECT vault.create_secret(
    'http://host.docker.internal:54321', 
    'supabase_project_url', 
    'URL to be used for calling edge functions, this is set here because we want to develop edge functions with webhohks from database triggers in multiple environments');
);

第 2 步:用自定义触发器替换 Supabase Webhooks

您可以创建直接调用边缘函数的自定义触发器,而不是使用 Supabase 的内置 Webhook(这在多环境设置中可能很麻烦)。

首先,为本地开发环境创建触发器并将其包含在迁移文件中。您可以使用

supabase db diff -f <new-migration>
:

自动生成迁移文件
CREATE OR REPLACE TRIGGER name_of_my_trigger
AFTER INSERT ON "public"."words"
FOR EACH ROW 
EXECUTE FUNCTION public.call_edge_function(
  '/functions/v1/name-of-my-edge-function', 
  'POST', 
  '{"Content-type":"application/json","x-supabase-webhook-source":"whatever"}', 
  '{}', 
  '5000'
);

第 3 步:实现自定义函数来处理边缘函数调用

我提取了 Supabase 用于 webhook 的函数以保持兼容性,并添加了一个额外的步骤来读取 Vault 密钥并动态构建完整的 URL。功能如下:

CREATE OR REPLACE FUNCTION public.call_edge_function()
 RETURNS trigger
 LANGUAGE plpgsql
 SECURITY DEFINER
 SET search_path TO 'supabase_functions'
AS $function$
  DECLARE
    request_id bigint;
    payload jsonb;
    url_path text := TG_ARGV[0]::text;
    method text := TG_ARGV[1]::text;
    headers jsonb DEFAULT '{}'::jsonb;
    params jsonb DEFAULT '{}'::jsonb;
    timeout_ms integer DEFAULT 1000;
    supabase_project_url text;
    full_url text;
  BEGIN
    IF url_path IS NULL OR url_path = 'null' THEN
      RAISE EXCEPTION 'url_path argument is missing';
    END IF;

    -- Retrieve the base URL from the Vault
    SELECT decrypted_secret INTO supabase_project_url 
    FROM vault.decrypted_secrets 
    WHERE name = 'supabase_project_url';

    IF supabase_project_url IS NULL OR supabase_project_url = 'null' THEN
      RAISE EXCEPTION 'supabase_project_url secret is missing or invalid';
    END IF;
    -- Construct the full URL by concatenating base_url with url_path
    full_url := supabase_project_url || url_path;

    IF method IS NULL OR method = 'null' THEN
      RAISE EXCEPTION 'method argument is missing';
    END IF;

    IF TG_ARGV[2] IS NULL OR TG_ARGV[2] = 'null' THEN
      headers = '{"Content-Type": "application/json"}'::jsonb;
    ELSE
      headers = TG_ARGV[2]::jsonb;
    END IF;

    IF TG_ARGV[3] IS NULL OR TG_ARGV[3] = 'null' THEN
      params = '{}'::jsonb;
    ELSE
      params = TG_ARGV[3]::jsonb;
    END IF;

    IF TG_ARGV[4] IS NULL OR TG_ARGV[4] = 'null' THEN
      timeout_ms = 1000;
    ELSE
      timeout_ms = TG_ARGV[4]::integer;
    END IF;

    CASE
      WHEN method = 'GET' THEN
        SELECT http_get INTO request_id FROM net.http_get(
          full_url,
          params,
          headers,
          timeout_ms
        );
      WHEN method = 'POST' THEN
        payload = jsonb_build_object(
          'old_record', OLD,
          'record', NEW,
          'type', TG_OP,
          'table', TG_TABLE_NAME,
          'schema', TG_TABLE_SCHEMA
        );

        SELECT http_post INTO request_id FROM net.http_post(
          full_url,
          payload,
          params,
          headers,
          timeout_ms
        );
      ELSE
        RAISE EXCEPTION 'method argument % is invalid', method;
    END CASE;

    INSERT INTO supabase_functions.hooks
      (hook_table_id, hook_name, request_id)
    VALUES
      (TG_RELID, TG_NAME, request_id);

    RETURN NEW;
  END;
$function$;

在本地数据库上执行此函数并将其也包含在迁移文件中。

第 4 步:集成到您的 CI/CD 管道中

最后,使用 CI/CD 管道将数据库迁移和边缘功能自动部署到生产环境。对于 GitHub Actions,您的工作流程可能如下所示:

jobs:
  deploy-to-supabase:
    runs-on: ubuntu-latest
    env:
      SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
      SUPABASE_DB_PASSWORD: ${{ secrets.PRODUCTION_DB_PASSWORD }}
      SUPABASE_PROJECT_ID: ${{ secrets.PRODUCTION_PROJECT_ID }}

    steps:
      - uses: actions/checkout@v4
      - uses: supabase/setup-cli@v1
        with:
          version: latest

      - run: supabase link --project-ref $SUPABASE_PROJECT_ID
      - run: supabase db push
      - run: supabase functions deploy

通过这些步骤,您将准备好征服 Supabase 中的多环境疯狂。

© www.soinside.com 2019 - 2024. All rights reserved.