mirror of
https://github.com/whekin/household-bot.git
synced 2026-03-31 13:54:02 +00:00
feat(db): add rent_payment_destinations column and multi-schema support
- Add migration 0020 for rent_payment_destinations jsonb column - Add DB_SCHEMA env var support for multi-schema deployments - Create custom migrate.ts script with proper search_path handling - Update drizzle.config.ts and client.ts to use DB_SCHEMA - Add db_schema variable to Terraform with dev=test/prod=public defaults - Update CD workflow to set DB_SCHEMA based on branch
This commit is contained in:
@@ -5,6 +5,7 @@ PORT=3000
|
||||
|
||||
# Database
|
||||
DATABASE_URL=postgres://postgres:postgres@127.0.0.1:54322/postgres
|
||||
DB_SCHEMA=public
|
||||
|
||||
# Telegram
|
||||
TELEGRAM_BOT_TOKEN=your-telegram-bot-token
|
||||
|
||||
1
.github/workflows/cd.yml
vendored
1
.github/workflows/cd.yml
vendored
@@ -100,6 +100,7 @@ jobs:
|
||||
- name: Run database migrations
|
||||
env:
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
DB_SCHEMA: ${{ github.ref == 'refs/heads/main' && 'public' || 'test' }}
|
||||
run: bun run db:migrate
|
||||
|
||||
- name: Setup gcloud
|
||||
|
||||
@@ -96,7 +96,8 @@ module "bot_api_service" {
|
||||
|
||||
env = merge(
|
||||
{
|
||||
NODE_ENV = var.environment
|
||||
NODE_ENV = var.environment
|
||||
DB_SCHEMA = var.db_schema
|
||||
},
|
||||
var.bot_purchase_parser_model == null ? {} : {
|
||||
PURCHASE_PARSER_MODEL = var.bot_purchase_parser_model
|
||||
|
||||
@@ -259,3 +259,9 @@ variable "github_deploy_service_account_id" {
|
||||
type = string
|
||||
default = "github-deployer"
|
||||
}
|
||||
|
||||
variable "db_schema" {
|
||||
description = "Database schema name for the application"
|
||||
type = string
|
||||
default = "public"
|
||||
}
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
"format:check": "bunx oxfmt --check .",
|
||||
"db:generate": "bunx drizzle-kit generate --config packages/db/drizzle.config.ts",
|
||||
"db:check": "bunx drizzle-kit check --config packages/db/drizzle.config.ts",
|
||||
"db:migrate": "bunx drizzle-kit migrate --config packages/db/drizzle.config.ts",
|
||||
"db:migrate": "bun run packages/db/src/migrate.ts",
|
||||
"db:migrations:check": "bun run scripts/check-migration-hygiene.ts",
|
||||
"db:migrations:manifest": "bun run scripts/update-migration-checksums.ts",
|
||||
"db:push": "bunx drizzle-kit push --config packages/db/drizzle.config.ts",
|
||||
"db:studio": "bunx drizzle-kit studio --config packages/db/drizzle.config.ts",
|
||||
"db:seed": "set -a; [ -f .env ] && . ./.env; set +a; bun run --filter @household/db seed",
|
||||
"db:seed": "set -a; [ -f .env ] && . ./.env; set +a; DB_SCHEMA=${DB_SCHEMA:-public} bun run --filter @household/db seed",
|
||||
"review:coderabbit": "coderabbit --prompt-only --base main || ~/.local/bin/coderabbit --prompt-only --base main",
|
||||
"infra:fmt": "terraform -chdir=infra/terraform fmt -recursive",
|
||||
"infra:fmt:check": "terraform -chdir=infra/terraform fmt -check -recursive",
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { defineConfig } from 'drizzle-kit'
|
||||
|
||||
const dbCredentials = process.env.DATABASE_URL
|
||||
? {
|
||||
url: process.env.DATABASE_URL
|
||||
}
|
||||
: undefined
|
||||
|
||||
export default defineConfig({
|
||||
dialect: 'postgresql',
|
||||
schema: './packages/db/src/schema.ts',
|
||||
out: './packages/db/drizzle',
|
||||
dbCredentials
|
||||
dbCredentials: {
|
||||
url: process.env.DATABASE_URL!
|
||||
},
|
||||
migrations: {
|
||||
schema: process.env.DB_SCHEMA || 'public',
|
||||
table: '__drizzle_migrations'
|
||||
}
|
||||
})
|
||||
|
||||
1
packages/db/drizzle/0020_natural_mauler.sql
Normal file
1
packages/db/drizzle/0020_natural_mauler.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE "household_billing_settings" ADD COLUMN "rent_payment_destinations" jsonb;
|
||||
3447
packages/db/drizzle/meta/0020_snapshot.json
Normal file
3447
packages/db/drizzle/meta/0020_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -141,6 +141,13 @@
|
||||
"when": 1773327708167,
|
||||
"tag": "0019_faithful_madame_masque",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 20,
|
||||
"version": "7",
|
||||
"when": 1773590603863,
|
||||
"tag": "0020_natural_mauler",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -7,9 +7,19 @@ export interface DbClientOptions {
|
||||
}
|
||||
|
||||
export function createDbClient(databaseUrl: string, options: DbClientOptions = {}) {
|
||||
const dbSchema = process.env.DB_SCHEMA || 'public'
|
||||
|
||||
const queryClient = postgres(databaseUrl, {
|
||||
max: options.max ?? 5,
|
||||
prepare: options.prepare ?? false
|
||||
prepare: options.prepare ?? false,
|
||||
onnotice: () => {},
|
||||
connection: {
|
||||
search_path: dbSchema
|
||||
},
|
||||
transform: {
|
||||
...postgres.camel,
|
||||
undefined: null
|
||||
}
|
||||
})
|
||||
|
||||
const db = drizzle(queryClient)
|
||||
|
||||
35
packages/db/src/migrate.ts
Normal file
35
packages/db/src/migrate.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import postgres from 'postgres'
|
||||
import { drizzle } from 'drizzle-orm/postgres-js'
|
||||
import { migrate } from 'drizzle-orm/postgres-js/migrator'
|
||||
import path from 'path'
|
||||
|
||||
const databaseUrl = process.env.DATABASE_URL
|
||||
if (!databaseUrl) {
|
||||
throw new Error('DATABASE_URL is not set')
|
||||
}
|
||||
|
||||
const dbSchema = process.env.DB_SCHEMA || 'public'
|
||||
|
||||
console.log(`Running migrations for schema: ${dbSchema}...`)
|
||||
|
||||
const migrationClient = postgres(databaseUrl, {
|
||||
max: 1,
|
||||
onnotice: () => {}
|
||||
})
|
||||
|
||||
// Explicitly set search_path to the target schema
|
||||
// This ensures that 'CREATE TABLE "x"' goes into the right schema
|
||||
await migrationClient.unsafe(`SET search_path TO ${dbSchema}`)
|
||||
|
||||
const db = drizzle(migrationClient)
|
||||
|
||||
// This runs migrations from the 'drizzle' folder
|
||||
await migrate(db, {
|
||||
migrationsFolder: path.resolve(__dirname, '../drizzle'),
|
||||
migrationsSchema: dbSchema,
|
||||
migrationsTable: '__drizzle_migrations'
|
||||
})
|
||||
|
||||
console.log('Migrations applied successfully!')
|
||||
await migrationClient.end()
|
||||
process.exit(0)
|
||||
@@ -3,9 +3,8 @@ import { $ } from 'bun'
|
||||
const PROJECT_ID = 'gen-lang-client-0200379851'
|
||||
|
||||
async function secretExists(name: string): Promise<boolean> {
|
||||
const result =
|
||||
(await $`gcloud secrets describe ${name} --project=${PROJECT_ID}`.quiet().exitCode) === 0
|
||||
return result
|
||||
const result = await $`gcloud secrets describe ${name} --project=${PROJECT_ID}`.quiet().nothrow()
|
||||
return result.exitCode === 0
|
||||
}
|
||||
|
||||
async function createSecret(name: string, value: string) {
|
||||
|
||||
Reference in New Issue
Block a user