Supabase Edge Functions を github actions でデプロイする

前回 Deno で supabase の postgreSQL へ接続とマイグレーションを試みました。

今回はそれらをgithub actionsで自動化するとともに、マイグレーション先のpostgreSQLを参照する Supabase Edge
Functions も併せてデプロイを自動化します。

参考

環境構築

Dockerfile
1
2
3
4
5
6
7
8
9
10
11
FROM denoland/deno:1.25.1

RUN apt-get update && apt-get install -y wget &&\
wget https://github.com/supabase/cli/releases/download/v0.24.5/supabase_0.24.5_linux_amd64.deb &&\
dpkg -i supabase_0.24.5_linux_amd64.deb

RUN mkdir /usr/src/app
WORKDIR /usr/src/app


EXPOSE 8080
docker-compose.yml
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
29
30
31
32
33
34
35
version: "3"
services:
app:
build:
context: .
dockerfile: Dockerfile
privileged: true
command: tail -f /dev/null
ports:
- "8080:8080"
- "35729:35729"
volumes:
- .:/usr/src/app:cached
tty: true
supabase:
image: "supabase/postgres"
ports:
- "5432:5432"
- "3000:3000"
volumes:
- "./supabase-postgresql/postgresql/data/postgres:/var/lib/postgresql/data"
environment:
POSTGRES_PASSWORD: postgres
pgadmin:
image: dpage/pgadmin4
restart: always
ports:
- 8081:80
environment:
PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL:-test@test.com}
PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD:-password}
volumes:
- ./pgadmin:/var/lib/pgadmin
depends_on:
- supabase

実装

supabase edge functions 関数の準備

supabase-cli を導入したdockerコンテナに入って作業します。

1
2
3
4
5
6
7
8
9
10
11
12
$ docker conmpose up -d
$ docker conmpose exec app bash

# 以下コンテナ内
$ which supabase
/usr/local/bin/supabase

$ supabase init
# supabase\config.toml が作成

$ supabase functions new get-database-data
# supabase\functions\get-database-data\index.ts が作成

supabase\functions\get-database-data\index.ts は次のようにしました。

supabase\functions\get-database-data\index.ts
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
29
import { createClient } from "https://esm.sh/@supabase/supabase-js@^1.33.2";
import { serve } from "https://deno.land/std@0.131.0/http/server.ts";

export const supabaseClient = createClient(
Deno.env.get("SUPABASE_URL")!,
Deno.env.get("SUPABASE_ANON_KEY")!,
);

serve(async (req) => {
const reqData = await(async () => {
try{
return await req.json()
}catch(e){
console.error(e)
return {}
}
})();

const { data, error } = await( reqData.id
? supabaseClient.from("users").select().eq("id", reqData.id)
: supabaseClient.from("users").select());

if(error) throw error

return new Response(
JSON.stringify(data),
{ headers: { "Content-Type": "application/json" } },
);
});

workflow の準備

workflowの用意が必要なので、.github/workflows/deploy.yml を用意します。
今回は、すべてのpush操作をトリガーとしていますが、本番運用相当ならブランチ/タグなど、絞ることにはなる認識です。

.github/workflows/deploy.yml
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
name: supabase-deploy

on: push

jobs:
supabase-deploy:
runs-on: ubuntu-latest
timeout-minutes: 600

steps:
- uses: actions/checkout@v3
- uses: supabase/setup-cli@v1
with:
version: 1.0.0

# ここから データベースのマイグレーション
# Denoコンテナ準備
- name: Do `container preparation`
run: |
docker-compose build
docker-compose up -d

- name: Do `migrate`
env:
SUPABASE_POSTGRES_HOST: ${{secrets.SUPABASE_POSTGRES_HOST}}
SUPABASE_POSTGRES_DB: ${{secrets.SUPABASE_POSTGRES_DB}}
SUPABASE_POSTGRES_USER: ${{secrets.SUPABASE_POSTGRES_USER}}
SUPABASE_POSTGRES_PASSWORD: ${{secrets.SUPABASE_POSTGRES_PASSWORD}}
run: |
echo POSTGRES_HOST=$SUPABASE_POSTGRES_HOST >> ./.env
echo POSTGRES_USER=$SUPABASE_POSTGRES_USER >> ./.env
echo POSTGRES_PASSWORD=$SUPABASE_POSTGRES_PASSWORD >> ./.env
echo POSTGRES_DB=$SUPABASE_POSTGRES_DB >> ./.env
cat ./.env

docker-compose exec -T app deno task db:migrate

# ここから Edge functions デプロイ
- uses: supabase/setup-cli@v1
with:
version: 1.0.0

- name: supabase edge functions deploy
env:
SUPABASE_ACCESS_TOKEN: ${{secrets.SUPABASE_ACCESS_TOKEN}}
SUPABASE_STAGING_PROJECT_ID: ${{secrets.SUPABASE_STAGING_PROJECT_ID}}
SUPABASE_DB_PASSWORD: ${{ secrets.SUPABASE_POSTGRES_PASSWORD }}
run: |
supabase link --project-ref $SUPABASE_STAGING_PROJECT_ID
supabase functions deploy get-database-data --project-ref $SUPABASE_STAGING_PROJECT_ID

supabase edge functions のデプロイのデプロイのためだけに、supabase-cli を使用するのですが、database
のパスワードを要求されるというのが注意事項。

マイグレーションのコマンドは、長くなりがちなので、deno.json でまとめて定義してあります。

deno.json
1
2
3
4
5
6
7
8
9
{
"tasks": {
"make:migration": "deno run --allow-env --allow-net --allow-read=./ --allow-write=./ --unstable https://deno.land/x/nessie/cli.ts make:migration",
"db:migrate": "deno run --allow-env --allow-net --allow-read=./ --unstable https://deno.land/x/nessie/cli.ts migrate",
"db:rollback": "deno run --allow-env --allow-net --allow-read=./ --unstable https://deno.land/x/nessie/cli.ts rollback",
"db:create": "deno run --allow-env --allow-net --allow-read=./ script/create_db.ts",
"db:drop": "deno run --allow-env --allow-net --allow-read=./ script/drop_db.ts"
}
}

github Actions secrets の設定

先の、.github/workflows/deploy.yml で使用している環境変数が有るので、こちらを github Actions secrets
に設定します。

設定の対象は以下の通りです。

1
2
3
4
5
6
7
8
9
# データベースマイグレーション用
SUPABASE_POSTGRES_DB # <= supabase の DB の データベース名
SUPABASE_POSTGRES_HOST # <= supabase の DB の ホスト名
SUPABASE_POSTGRES_USER # <= supabase の DB の ユーザー名
SUPABASE_POSTGRES_PASSWORD # <= supabase の DB の パスワード

# supabase edge functions デプロイ用
SUPABASE_ACCESS_TOKEN # <= supabase のanno トークン
SUPABASE_STAGING_PROJECT_ID # <= supabase のプロジェクトID

デプロイ

githubにpushすれば、github actions で定義したワークフローが動き始めます。

動作確認

別途データを登録してから、アクセスすると次のように動きます。

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
29
30
31
32
33
34
35
36
37
$ curl -L -X POST 'https://[プロジェクト].functions.supabase.co/get-database-data' -H 'Authorization: Bearer [トークン文字列]'|jq . 
[
{
"id": 2,
"name": "AAA2",
"created_at": "2022-09-16T06:25:53.912903",
"updated_at": "2022-09-16T06:25:53.912903"
},
{
"id": 3,
"name": "AAA1",
"created_at": "2022-09-16T08:09:04.047731",
"updated_at": "2022-09-16T08:09:04.047731"
},
{
"id": 4,
"name": "AAA2",
"created_at": "2022-09-16T08:09:04.225362",
"updated_at": "2022-09-16T08:09:04.225362"
},
{
"id": 1,
"name": "BBB111111",
"created_at": "2022-09-16T06:25:53.737534",
"updated_at": "2022-09-16T08:10:33.509975"
}
]

$ curl -L -X POST 'https://[プロジェクト].functions.supabase.co/get-database-data' -H 'Authorization: Bearer [トークン文字列]' --data '{"id":3}'|jq .
[
{
"id": 3,
"name": "AAA1",
"created_at": "2022-09-16T08:09:04.047731",
"updated_at": "2022-09-16T08:09:04.047731"
}
]

以上、supabaseのDBへのマイグレーションと supabase Edge Functions のデプロイをまとめて github actions
で実行できました。

最終的なディレクトリの構成は次のようになります。(githubにpushするものだけ)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ tree
.
|-- Dockerfile
|-- db
| |-- migrations
| | |-- 20220916004331_create_users.ts
| | `-- 20220916004415_create_users_function.ts
| `-- seeds
|-- deno.json
|-- docker-compose.yml
|-- nessie.config.ts
`-- supabase
|-- config.toml
`-- functions
`-- get-database-data
`-- index.ts

Supabase Edge Functions では接続ユーザー名を使用しないということもあり、nessie の設定情報と共通化はできないです。
しかし、一般化した方法として成立させたいですし、nessieでのマイグレーションにも一定の意味があると考えます。
(例えば、postgreSQLを別に作る時とかね。)

では。