From f3ea92103bc2e47826a5998db1928d53a3791061 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sun, 18 May 2025 22:38:39 +0000 Subject: [PATCH 01/13] Add GitHub Actions workflows for Supabase staging and production environments Co-Authored-By: kiet@onlook.dev --- .github/workflows/supabase-ci.yml | 29 +++++++++++++++++++++++ .github/workflows/supabase-production.yml | 25 +++++++++++++++++++ .github/workflows/supabase-staging.yml | 25 +++++++++++++++++++ README.md | 14 +++++++++++ 4 files changed, 93 insertions(+) create mode 100644 .github/workflows/supabase-ci.yml create mode 100644 .github/workflows/supabase-production.yml create mode 100644 .github/workflows/supabase-staging.yml diff --git a/.github/workflows/supabase-ci.yml b/.github/workflows/supabase-ci.yml new file mode 100644 index 0000000000..0974bb41bb --- /dev/null +++ b/.github/workflows/supabase-ci.yml @@ -0,0 +1,29 @@ +name: Validate Supabase Migrations + +on: + pull_request: + branches: + - develop + - main + workflow_dispatch: + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: supabase/setup-cli@v1 + with: + version: latest + + - name: Start Supabase local development environment + run: supabase start + + - name: Validate migrations + run: | + # Check if migrations can be applied without errors + supabase db reset + + # Additional validation can be added here + echo "Migrations validated successfully" diff --git a/.github/workflows/supabase-production.yml b/.github/workflows/supabase-production.yml new file mode 100644 index 0000000000..13ffa73f8e --- /dev/null +++ b/.github/workflows/supabase-production.yml @@ -0,0 +1,25 @@ +name: Deploy Supabase to Production + +on: + push: + branches: + - main + workflow_dispatch: + +jobs: + deploy: + 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 diff --git a/.github/workflows/supabase-staging.yml b/.github/workflows/supabase-staging.yml new file mode 100644 index 0000000000..5d181c3d4e --- /dev/null +++ b/.github/workflows/supabase-staging.yml @@ -0,0 +1,25 @@ +name: Deploy Supabase to Staging + +on: + push: + branches: + - develop + workflow_dispatch: + +jobs: + deploy: + runs-on: ubuntu-latest + env: + SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }} + SUPABASE_DB_PASSWORD: ${{ secrets.STAGING_DB_PASSWORD }} + SUPABASE_PROJECT_ID: ${{ secrets.STAGING_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 diff --git a/README.md b/README.md index 8c3f81811c..42b93d0559 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,20 @@ Projects we're inspired by: - [Supabase](https://github.com/supabase/supabase) +## CI/CD for Supabase + +Supabase environments are deployed automatically using GitHub Actions: + +- **Staging**: Changes to the `develop` branch are automatically deployed to the staging Supabase project +- **Production**: Changes to the `main` branch are automatically deployed to the production Supabase project + +Required GitHub Secrets: +- `SUPABASE_ACCESS_TOKEN` - Personal access token from Supabase +- `STAGING_DB_PASSWORD` - Database password for staging environment +- `STAGING_PROJECT_ID` - Project ID for staging environment +- `PRODUCTION_DB_PASSWORD` - Database password for production environment +- `PRODUCTION_PROJECT_ID` - Project ID for production environment + ## License Distributed under the Apache 2.0 License. See [LICENSE.md](LICENSE.md) for more From aff144da275e8b5a1266dca9e59e7f23d289b2bc Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 15:15:50 +0000 Subject: [PATCH 02/13] Update environment variable names to be more specific Co-Authored-By: kiet@onlook.dev --- .github/workflows/supabase-production.yml | 2 +- .github/workflows/supabase-staging.yml | 2 +- README.md | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/supabase-production.yml b/.github/workflows/supabase-production.yml index 13ffa73f8e..204fa3e5c5 100644 --- a/.github/workflows/supabase-production.yml +++ b/.github/workflows/supabase-production.yml @@ -12,7 +12,7 @@ jobs: env: SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }} SUPABASE_DB_PASSWORD: ${{ secrets.PRODUCTION_DB_PASSWORD }} - SUPABASE_PROJECT_ID: ${{ secrets.PRODUCTION_PROJECT_ID }} + SUPABASE_PROJECT_ID: ${{ secrets.SUPABASE_PRODUCTION_PROJECT_ID }} steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/supabase-staging.yml b/.github/workflows/supabase-staging.yml index 5d181c3d4e..f42b7af309 100644 --- a/.github/workflows/supabase-staging.yml +++ b/.github/workflows/supabase-staging.yml @@ -12,7 +12,7 @@ jobs: env: SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }} SUPABASE_DB_PASSWORD: ${{ secrets.STAGING_DB_PASSWORD }} - SUPABASE_PROJECT_ID: ${{ secrets.STAGING_PROJECT_ID }} + SUPABASE_PROJECT_ID: ${{ secrets.SUPABASE_STAGING_PROJECT_ID }} steps: - uses: actions/checkout@v4 diff --git a/README.md b/README.md index 42b93d0559..7b0426590b 100644 --- a/README.md +++ b/README.md @@ -128,9 +128,9 @@ Supabase environments are deployed automatically using GitHub Actions: Required GitHub Secrets: - `SUPABASE_ACCESS_TOKEN` - Personal access token from Supabase - `STAGING_DB_PASSWORD` - Database password for staging environment -- `STAGING_PROJECT_ID` - Project ID for staging environment +- `SUPABASE_STAGING_PROJECT_ID` - Project ID for staging environment - `PRODUCTION_DB_PASSWORD` - Database password for production environment -- `PRODUCTION_PROJECT_ID` - Project ID for production environment +- `SUPABASE_PRODUCTION_PROJECT_ID` - Project ID for production environment ## License From 01aae9117b3f34dd8a218771fa9bccf9a1471e8a Mon Sep 17 00:00:00 2001 From: Kiet Ho Date: Tue, 20 May 2025 13:31:14 -0700 Subject: [PATCH 03/13] update readme --- README.md | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/README.md b/README.md index 7b0426590b..8c3f81811c 100644 --- a/README.md +++ b/README.md @@ -118,20 +118,6 @@ Projects we're inspired by: - [Supabase](https://github.com/supabase/supabase) -## CI/CD for Supabase - -Supabase environments are deployed automatically using GitHub Actions: - -- **Staging**: Changes to the `develop` branch are automatically deployed to the staging Supabase project -- **Production**: Changes to the `main` branch are automatically deployed to the production Supabase project - -Required GitHub Secrets: -- `SUPABASE_ACCESS_TOKEN` - Personal access token from Supabase -- `STAGING_DB_PASSWORD` - Database password for staging environment -- `SUPABASE_STAGING_PROJECT_ID` - Project ID for staging environment -- `PRODUCTION_DB_PASSWORD` - Database password for production environment -- `SUPABASE_PRODUCTION_PROJECT_ID` - Project ID for production environment - ## License Distributed under the Apache 2.0 License. See [LICENSE.md](LICENSE.md) for more From 507a7d11d73d8cfbc618e0e51909650bc38353a6 Mon Sep 17 00:00:00 2001 From: Kiet Ho Date: Tue, 20 May 2025 15:21:33 -0700 Subject: [PATCH 04/13] add migration files --- .github/workflows/supabase-production.yml | 25 - .github/workflows/supabase-staging.yml | 23 +- .../db/src/migrations/0000_salty_blink.sql | 75 +++ .../db/src/migrations/meta/0000_snapshot.json | 482 ++++++++++++++++++ packages/db/src/migrations/meta/_journal.json | 13 + 5 files changed, 581 insertions(+), 37 deletions(-) delete mode 100644 .github/workflows/supabase-production.yml create mode 100644 packages/db/src/migrations/0000_salty_blink.sql create mode 100644 packages/db/src/migrations/meta/0000_snapshot.json create mode 100644 packages/db/src/migrations/meta/_journal.json diff --git a/.github/workflows/supabase-production.yml b/.github/workflows/supabase-production.yml deleted file mode 100644 index 204fa3e5c5..0000000000 --- a/.github/workflows/supabase-production.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Deploy Supabase to Production - -on: - push: - branches: - - main - workflow_dispatch: - -jobs: - deploy: - runs-on: ubuntu-latest - env: - SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }} - SUPABASE_DB_PASSWORD: ${{ secrets.PRODUCTION_DB_PASSWORD }} - SUPABASE_PROJECT_ID: ${{ secrets.SUPABASE_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 diff --git a/.github/workflows/supabase-staging.yml b/.github/workflows/supabase-staging.yml index f42b7af309..d488f8113f 100644 --- a/.github/workflows/supabase-staging.yml +++ b/.github/workflows/supabase-staging.yml @@ -1,25 +1,24 @@ -name: Deploy Supabase to Staging +name: Deploy Drizzle Migrations to Supabase Staging on: push: branches: - - develop + - main workflow_dispatch: jobs: deploy: runs-on: ubuntu-latest env: - SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }} - SUPABASE_DB_PASSWORD: ${{ secrets.STAGING_DB_PASSWORD }} - SUPABASE_PROJECT_ID: ${{ secrets.SUPABASE_STAGING_PROJECT_ID }} + DATABASE_URL: ${{ secrets.STAGING_SUPABASE_DATABASE_URL }} + steps: - uses: actions/checkout@v4 - - - uses: supabase/setup-cli@v1 + + - uses: oven-sh/setup-bun@v1 with: - version: latest - - - run: supabase link --project-ref $SUPABASE_PROJECT_ID - - - run: supabase db push + bun-version: latest + + - run: bun install + + - run: bun run drizzle:push diff --git a/packages/db/src/migrations/0000_salty_blink.sql b/packages/db/src/migrations/0000_salty_blink.sql new file mode 100644 index 0000000000..9eb09649a0 --- /dev/null +++ b/packages/db/src/migrations/0000_salty_blink.sql @@ -0,0 +1,75 @@ +CREATE TYPE "public"."frame_type" AS ENUM('web');--> statement-breakpoint +CREATE TYPE "public"."role" AS ENUM('user', 'assistant', 'system');--> statement-breakpoint +CREATE TABLE "canvas" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "project_id" uuid NOT NULL, + "scale" numeric NOT NULL, + "x" numeric NOT NULL, + "y" numeric NOT NULL +); +--> statement-breakpoint +ALTER TABLE "canvas" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint +CREATE TABLE "frames" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "canvas_id" uuid NOT NULL, + "type" "frame_type" NOT NULL, + "url" varchar NOT NULL, + "x" numeric NOT NULL, + "y" numeric NOT NULL, + "width" numeric NOT NULL, + "height" numeric NOT NULL +); +--> statement-breakpoint +ALTER TABLE "frames" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint +CREATE TABLE "conversations" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "project_id" uuid NOT NULL, + "display_name" varchar, + "created_at" timestamp with time zone DEFAULT now() NOT NULL, + "updated_at" timestamp with time zone DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "messages" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "conversation_id" uuid NOT NULL, + "content" text NOT NULL, + "created_at" timestamp with time zone DEFAULT now() NOT NULL, + "role" "role" NOT NULL, + "applied" boolean DEFAULT false NOT NULL, + "snapshots" jsonb DEFAULT '{}'::jsonb NOT NULL, + "context" jsonb DEFAULT '[]'::jsonb NOT NULL, + "parts" jsonb DEFAULT '[]'::jsonb NOT NULL +); +--> statement-breakpoint +CREATE TABLE "projects" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "name" varchar NOT NULL, + "sandbox_id" varchar NOT NULL, + "sandbox_url" varchar NOT NULL, + "created_at" timestamp with time zone DEFAULT now() NOT NULL, + "updated_at" timestamp with time zone DEFAULT now() NOT NULL, + "preview_img" varchar, + "description" text +); +--> statement-breakpoint +ALTER TABLE "projects" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint +CREATE TABLE "users" ( + "id" uuid PRIMARY KEY NOT NULL +); +--> statement-breakpoint +ALTER TABLE "users" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint +CREATE TABLE "user_projects" ( + "user_id" uuid NOT NULL, + "project_id" uuid NOT NULL, + "created_at" timestamp with time zone DEFAULT now(), + CONSTRAINT "user_projects_user_id_project_id_pk" PRIMARY KEY("user_id","project_id") +); +--> statement-breakpoint +ALTER TABLE "user_projects" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint +ALTER TABLE "canvas" ADD CONSTRAINT "canvas_project_id_projects_id_fk" FOREIGN KEY ("project_id") REFERENCES "public"."projects"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint +ALTER TABLE "frames" ADD CONSTRAINT "frames_canvas_id_canvas_id_fk" FOREIGN KEY ("canvas_id") REFERENCES "public"."canvas"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint +ALTER TABLE "conversations" ADD CONSTRAINT "conversations_project_id_projects_id_fk" FOREIGN KEY ("project_id") REFERENCES "public"."projects"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint +ALTER TABLE "messages" ADD CONSTRAINT "messages_conversation_id_conversations_id_fk" FOREIGN KEY ("conversation_id") REFERENCES "public"."conversations"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint +ALTER TABLE "users" ADD CONSTRAINT "users_id_users_id_fk" FOREIGN KEY ("id") REFERENCES "auth"."users"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint +ALTER TABLE "user_projects" ADD CONSTRAINT "user_projects_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint +ALTER TABLE "user_projects" ADD CONSTRAINT "user_projects_project_id_projects_id_fk" FOREIGN KEY ("project_id") REFERENCES "public"."projects"("id") ON DELETE cascade ON UPDATE cascade; \ No newline at end of file diff --git a/packages/db/src/migrations/meta/0000_snapshot.json b/packages/db/src/migrations/meta/0000_snapshot.json new file mode 100644 index 0000000000..9931fd3041 --- /dev/null +++ b/packages/db/src/migrations/meta/0000_snapshot.json @@ -0,0 +1,482 @@ +{ + "id": "d2cc3771-dfa2-4702-a665-776d2a2bf109", + "prevId": "00000000-0000-0000-0000-000000000000", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.canvas": { + "name": "canvas", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "project_id": { + "name": "project_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "scale": { + "name": "scale", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "x": { + "name": "x", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "y": { + "name": "y", + "type": "numeric", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "canvas_project_id_projects_id_fk": { + "name": "canvas_project_id_projects_id_fk", + "tableFrom": "canvas", + "tableTo": "projects", + "columnsFrom": [ + "project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.frames": { + "name": "frames", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "canvas_id": { + "name": "canvas_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "frame_type", + "primaryKey": false, + "notNull": true + }, + "url": { + "name": "url", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "x": { + "name": "x", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "y": { + "name": "y", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "width": { + "name": "width", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "height": { + "name": "height", + "type": "numeric", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "frames_canvas_id_canvas_id_fk": { + "name": "frames_canvas_id_canvas_id_fk", + "tableFrom": "frames", + "tableTo": "canvas", + "columnsFrom": [ + "canvas_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.conversations": { + "name": "conversations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "project_id": { + "name": "project_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "display_name": { + "name": "display_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "conversations_project_id_projects_id_fk": { + "name": "conversations_project_id_projects_id_fk", + "tableFrom": "conversations", + "tableTo": "projects", + "columnsFrom": [ + "project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.messages": { + "name": "messages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "conversation_id": { + "name": "conversation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "role": { + "name": "role", + "type": "role", + "primaryKey": false, + "notNull": true + }, + "applied": { + "name": "applied", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "snapshots": { + "name": "snapshots", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "context": { + "name": "context", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "parts": { + "name": "parts", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + } + }, + "indexes": {}, + "foreignKeys": { + "messages_conversation_id_conversations_id_fk": { + "name": "messages_conversation_id_conversations_id_fk", + "tableFrom": "messages", + "tableTo": "conversations", + "columnsFrom": [ + "conversation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.projects": { + "name": "projects", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "sandbox_id": { + "name": "sandbox_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "sandbox_url": { + "name": "sandbox_url", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "preview_img": { + "name": "preview_img", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "users_id_users_id_fk": { + "name": "users_id_users_id_fk", + "tableFrom": "users", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.user_projects": { + "name": "user_projects", + "schema": "", + "columns": { + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "user_projects_user_id_users_id_fk": { + "name": "user_projects_user_id_users_id_fk", + "tableFrom": "user_projects", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "user_projects_project_id_projects_id_fk": { + "name": "user_projects_project_id_projects_id_fk", + "tableFrom": "user_projects", + "tableTo": "projects", + "columnsFrom": [ + "project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "user_projects_user_id_project_id_pk": { + "name": "user_projects_user_id_project_id_pk", + "columns": [ + "user_id", + "project_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + } + }, + "enums": { + "public.frame_type": { + "name": "frame_type", + "schema": "public", + "values": [ + "web" + ] + }, + "public.role": { + "name": "role", + "schema": "public", + "values": [ + "user", + "assistant", + "system" + ] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/packages/db/src/migrations/meta/_journal.json b/packages/db/src/migrations/meta/_journal.json new file mode 100644 index 0000000000..e430f23985 --- /dev/null +++ b/packages/db/src/migrations/meta/_journal.json @@ -0,0 +1,13 @@ +{ + "version": "7", + "dialect": "postgresql", + "entries": [ + { + "idx": 0, + "version": "7", + "when": 1747779677817, + "tag": "0000_salty_blink", + "breakpoints": true + } + ] +} \ No newline at end of file From 87d75c44647bd04d4ddb768f83e561ef24f73c29 Mon Sep 17 00:00:00 2001 From: Kiet Ho Date: Tue, 20 May 2025 15:22:30 -0700 Subject: [PATCH 05/13] add branch --- .github/workflows/supabase-staging.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/supabase-staging.yml b/.github/workflows/supabase-staging.yml index d488f8113f..a59e69130a 100644 --- a/.github/workflows/supabase-staging.yml +++ b/.github/workflows/supabase-staging.yml @@ -4,6 +4,7 @@ on: push: branches: - main + - ci/supabase workflow_dispatch: jobs: From 638373dc1c2437216a57dae79f2f55ac6d4cc5d4 Mon Sep 17 00:00:00 2001 From: Kiet Ho Date: Tue, 20 May 2025 15:27:01 -0700 Subject: [PATCH 06/13] update command --- .github/workflows/supabase-staging.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/supabase-staging.yml b/.github/workflows/supabase-staging.yml index a59e69130a..0b9446e46a 100644 --- a/.github/workflows/supabase-staging.yml +++ b/.github/workflows/supabase-staging.yml @@ -11,7 +11,7 @@ jobs: deploy: runs-on: ubuntu-latest env: - DATABASE_URL: ${{ secrets.STAGING_SUPABASE_DATABASE_URL }} + SUPABASE_DATABASE_URL: ${{ secrets.STAGING_SUPABASE_DATABASE_URL }} steps: - uses: actions/checkout@v4 @@ -22,4 +22,4 @@ jobs: - run: bun install - - run: bun run drizzle:push + - run: bun run db:push From 6de6f0b8d5320d7fdd1296a8f39926115fcd7c60 Mon Sep 17 00:00:00 2001 From: Kiet Ho Date: Tue, 20 May 2025 15:27:47 -0700 Subject: [PATCH 07/13] remove schema validation --- .github/workflows/supabase-ci.yml | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100644 .github/workflows/supabase-ci.yml diff --git a/.github/workflows/supabase-ci.yml b/.github/workflows/supabase-ci.yml deleted file mode 100644 index 0974bb41bb..0000000000 --- a/.github/workflows/supabase-ci.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: Validate Supabase Migrations - -on: - pull_request: - branches: - - develop - - main - workflow_dispatch: - -jobs: - validate: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - uses: supabase/setup-cli@v1 - with: - version: latest - - - name: Start Supabase local development environment - run: supabase start - - - name: Validate migrations - run: | - # Check if migrations can be applied without errors - supabase db reset - - # Additional validation can be added here - echo "Migrations validated successfully" From 018115b59632244e109a3db835a356d3e7991c84 Mon Sep 17 00:00:00 2001 From: Kiet Ho Date: Tue, 20 May 2025 15:30:28 -0700 Subject: [PATCH 08/13] update migration path --- .../backend/supabase/migrations/0000_same_human_robot.sql | 0 .../backend/supabase}/migrations/meta/0000_snapshot.json | 2 +- .../backend/supabase}/migrations/meta/_journal.json | 4 ++-- packages/db/drizzle.config.ts | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) rename packages/db/src/migrations/0000_salty_blink.sql => apps/backend/supabase/migrations/0000_same_human_robot.sql (100%) rename {packages/db/src => apps/backend/supabase}/migrations/meta/0000_snapshot.json (99%) rename {packages/db/src => apps/backend/supabase}/migrations/meta/_journal.json (68%) diff --git a/packages/db/src/migrations/0000_salty_blink.sql b/apps/backend/supabase/migrations/0000_same_human_robot.sql similarity index 100% rename from packages/db/src/migrations/0000_salty_blink.sql rename to apps/backend/supabase/migrations/0000_same_human_robot.sql diff --git a/packages/db/src/migrations/meta/0000_snapshot.json b/apps/backend/supabase/migrations/meta/0000_snapshot.json similarity index 99% rename from packages/db/src/migrations/meta/0000_snapshot.json rename to apps/backend/supabase/migrations/meta/0000_snapshot.json index 9931fd3041..af17fcd408 100644 --- a/packages/db/src/migrations/meta/0000_snapshot.json +++ b/apps/backend/supabase/migrations/meta/0000_snapshot.json @@ -1,5 +1,5 @@ { - "id": "d2cc3771-dfa2-4702-a665-776d2a2bf109", + "id": "95612ed1-7374-41c8-8f07-1ee3b064226b", "prevId": "00000000-0000-0000-0000-000000000000", "version": "7", "dialect": "postgresql", diff --git a/packages/db/src/migrations/meta/_journal.json b/apps/backend/supabase/migrations/meta/_journal.json similarity index 68% rename from packages/db/src/migrations/meta/_journal.json rename to apps/backend/supabase/migrations/meta/_journal.json index e430f23985..892a52b851 100644 --- a/packages/db/src/migrations/meta/_journal.json +++ b/apps/backend/supabase/migrations/meta/_journal.json @@ -5,8 +5,8 @@ { "idx": 0, "version": "7", - "when": 1747779677817, - "tag": "0000_salty_blink", + "when": 1747780205535, + "tag": "0000_same_human_robot", "breakpoints": true } ] diff --git a/packages/db/drizzle.config.ts b/packages/db/drizzle.config.ts index d001b8ffaa..8adc520b82 100644 --- a/packages/db/drizzle.config.ts +++ b/packages/db/drizzle.config.ts @@ -3,10 +3,10 @@ import { defineConfig } from 'drizzle-kit'; const DEFAULT_DATABASE_URL = 'postgresql://postgres:postgres@127.0.0.1:54322/postgres'; export default defineConfig({ schema: './src/schema', - out: './src/migrations', + out: '../../apps/backend/supabase/migrations', dialect: "postgresql", schemaFilter: ["public"], dbCredentials: { url: process.env.SUPABASE_DATABASE_URL ?? DEFAULT_DATABASE_URL, }, -}); +}); \ No newline at end of file From 782eeb1405116a53a7e203cb4ca843e564edff19 Mon Sep 17 00:00:00 2001 From: Kiet Ho Date: Tue, 20 May 2025 15:36:51 -0700 Subject: [PATCH 09/13] update schema --- packages/db/src/schema/project/chat/conversation.ts | 2 +- packages/db/src/schema/project/chat/message.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/db/src/schema/project/chat/conversation.ts b/packages/db/src/schema/project/chat/conversation.ts index ae9cc23682..a5f0da0d4f 100644 --- a/packages/db/src/schema/project/chat/conversation.ts +++ b/packages/db/src/schema/project/chat/conversation.ts @@ -14,7 +14,7 @@ export const conversations = pgTable("conversations", { displayName: varchar("display_name"), createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(), updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(), -}); +}).enableRLS(); export const conversationInsertSchema = createInsertSchema(conversations); diff --git a/packages/db/src/schema/project/chat/message.ts b/packages/db/src/schema/project/chat/message.ts index 4b4995e260..cb8da3b8f3 100644 --- a/packages/db/src/schema/project/chat/message.ts +++ b/packages/db/src/schema/project/chat/message.ts @@ -20,7 +20,7 @@ export const messages = pgTable("messages", { snapshots: jsonb("snapshots").$type().default({}).notNull(), context: jsonb("context").$type().default([]).notNull(), parts: jsonb("parts").$type().default([]).notNull(), -}); +}).enableRLS(); export const messageInsertSchema = createInsertSchema(messages); From ced4fb7a30ed2df086a15a9f96015ef69a1ba4e0 Mon Sep 17 00:00:00 2001 From: Kiet Ho Date: Tue, 20 May 2025 15:38:25 -0700 Subject: [PATCH 10/13] pin bun version --- .github/workflows/supabase-staging.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/supabase-staging.yml b/.github/workflows/supabase-staging.yml index 0b9446e46a..9638c3c395 100644 --- a/.github/workflows/supabase-staging.yml +++ b/.github/workflows/supabase-staging.yml @@ -18,7 +18,7 @@ jobs: - uses: oven-sh/setup-bun@v1 with: - bun-version: latest + bun-version: 1.2.13 - run: bun install From 5e20fa35cf1c0d929bc6b7f9fd53a59cfc8a67aa Mon Sep 17 00:00:00 2001 From: Kiet Ho Date: Tue, 20 May 2025 15:39:04 -0700 Subject: [PATCH 11/13] pin bun version --- .github/workflows/supabase-staging.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/supabase-staging.yml b/.github/workflows/supabase-staging.yml index 9638c3c395..a04e63784a 100644 --- a/.github/workflows/supabase-staging.yml +++ b/.github/workflows/supabase-staging.yml @@ -18,7 +18,7 @@ jobs: - uses: oven-sh/setup-bun@v1 with: - bun-version: 1.2.13 + bun-version: 1.2.x - run: bun install From adbd45f0dd014383740fb2aff13ef8aa101c2899 Mon Sep 17 00:00:00 2001 From: Kiet Ho Date: Tue, 20 May 2025 15:39:50 -0700 Subject: [PATCH 12/13] add migration files --- .../migrations/0001_graceful_exodus.sql | 2 + .../migrations/meta/0001_snapshot.json | 482 ++++++++++++++++++ .../supabase/migrations/meta/_journal.json | 7 + 3 files changed, 491 insertions(+) create mode 100644 apps/backend/supabase/migrations/0001_graceful_exodus.sql create mode 100644 apps/backend/supabase/migrations/meta/0001_snapshot.json diff --git a/apps/backend/supabase/migrations/0001_graceful_exodus.sql b/apps/backend/supabase/migrations/0001_graceful_exodus.sql new file mode 100644 index 0000000000..4c1280ebc1 --- /dev/null +++ b/apps/backend/supabase/migrations/0001_graceful_exodus.sql @@ -0,0 +1,2 @@ +ALTER TABLE "conversations" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint +ALTER TABLE "messages" ENABLE ROW LEVEL SECURITY; \ No newline at end of file diff --git a/apps/backend/supabase/migrations/meta/0001_snapshot.json b/apps/backend/supabase/migrations/meta/0001_snapshot.json new file mode 100644 index 0000000000..a3600e599f --- /dev/null +++ b/apps/backend/supabase/migrations/meta/0001_snapshot.json @@ -0,0 +1,482 @@ +{ + "id": "7fab2c6f-cf80-420e-bad4-3d6065d58b9c", + "prevId": "95612ed1-7374-41c8-8f07-1ee3b064226b", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.canvas": { + "name": "canvas", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "project_id": { + "name": "project_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "scale": { + "name": "scale", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "x": { + "name": "x", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "y": { + "name": "y", + "type": "numeric", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "canvas_project_id_projects_id_fk": { + "name": "canvas_project_id_projects_id_fk", + "tableFrom": "canvas", + "tableTo": "projects", + "columnsFrom": [ + "project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.frames": { + "name": "frames", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "canvas_id": { + "name": "canvas_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "frame_type", + "primaryKey": false, + "notNull": true + }, + "url": { + "name": "url", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "x": { + "name": "x", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "y": { + "name": "y", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "width": { + "name": "width", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "height": { + "name": "height", + "type": "numeric", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "frames_canvas_id_canvas_id_fk": { + "name": "frames_canvas_id_canvas_id_fk", + "tableFrom": "frames", + "tableTo": "canvas", + "columnsFrom": [ + "canvas_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.conversations": { + "name": "conversations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "project_id": { + "name": "project_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "display_name": { + "name": "display_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "conversations_project_id_projects_id_fk": { + "name": "conversations_project_id_projects_id_fk", + "tableFrom": "conversations", + "tableTo": "projects", + "columnsFrom": [ + "project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.messages": { + "name": "messages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "conversation_id": { + "name": "conversation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "role": { + "name": "role", + "type": "role", + "primaryKey": false, + "notNull": true + }, + "applied": { + "name": "applied", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "snapshots": { + "name": "snapshots", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "context": { + "name": "context", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "parts": { + "name": "parts", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + } + }, + "indexes": {}, + "foreignKeys": { + "messages_conversation_id_conversations_id_fk": { + "name": "messages_conversation_id_conversations_id_fk", + "tableFrom": "messages", + "tableTo": "conversations", + "columnsFrom": [ + "conversation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.projects": { + "name": "projects", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "sandbox_id": { + "name": "sandbox_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "sandbox_url": { + "name": "sandbox_url", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "preview_img": { + "name": "preview_img", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "users_id_users_id_fk": { + "name": "users_id_users_id_fk", + "tableFrom": "users", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.user_projects": { + "name": "user_projects", + "schema": "", + "columns": { + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "user_projects_user_id_users_id_fk": { + "name": "user_projects_user_id_users_id_fk", + "tableFrom": "user_projects", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "user_projects_project_id_projects_id_fk": { + "name": "user_projects_project_id_projects_id_fk", + "tableFrom": "user_projects", + "tableTo": "projects", + "columnsFrom": [ + "project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "user_projects_user_id_project_id_pk": { + "name": "user_projects_user_id_project_id_pk", + "columns": [ + "user_id", + "project_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + } + }, + "enums": { + "public.frame_type": { + "name": "frame_type", + "schema": "public", + "values": [ + "web" + ] + }, + "public.role": { + "name": "role", + "schema": "public", + "values": [ + "user", + "assistant", + "system" + ] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/apps/backend/supabase/migrations/meta/_journal.json b/apps/backend/supabase/migrations/meta/_journal.json index 892a52b851..7cd5be3793 100644 --- a/apps/backend/supabase/migrations/meta/_journal.json +++ b/apps/backend/supabase/migrations/meta/_journal.json @@ -8,6 +8,13 @@ "when": 1747780205535, "tag": "0000_same_human_robot", "breakpoints": true + }, + { + "idx": 1, + "version": "7", + "when": 1747780749310, + "tag": "0001_graceful_exodus", + "breakpoints": true } ] } \ No newline at end of file From cb9df7ed71ed5b69b89fc1ea0dd013738b83c9be Mon Sep 17 00:00:00 2001 From: Kiet Ho Date: Tue, 20 May 2025 15:40:13 -0700 Subject: [PATCH 13/13] disable main --- .github/workflows/supabase-staging.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/supabase-staging.yml b/.github/workflows/supabase-staging.yml index a04e63784a..90789bd762 100644 --- a/.github/workflows/supabase-staging.yml +++ b/.github/workflows/supabase-staging.yml @@ -4,7 +4,6 @@ on: push: branches: - main - - ci/supabase workflow_dispatch: jobs: