mirror of
https://github.com/whekin/household-bot.git
synced 2026-03-31 15:54:03 +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
|
||||||
DATABASE_URL=postgres://postgres:postgres@127.0.0.1:54322/postgres
|
DATABASE_URL=postgres://postgres:postgres@127.0.0.1:54322/postgres
|
||||||
|
DB_SCHEMA=public
|
||||||
|
|
||||||
# Telegram
|
# Telegram
|
||||||
TELEGRAM_BOT_TOKEN=your-telegram-bot-token
|
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
|
- name: Run database migrations
|
||||||
env:
|
env:
|
||||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||||
|
DB_SCHEMA: ${{ github.ref == 'refs/heads/main' && 'public' || 'test' }}
|
||||||
run: bun run db:migrate
|
run: bun run db:migrate
|
||||||
|
|
||||||
- name: Setup gcloud
|
- name: Setup gcloud
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ module "bot_api_service" {
|
|||||||
env = merge(
|
env = merge(
|
||||||
{
|
{
|
||||||
NODE_ENV = var.environment
|
NODE_ENV = var.environment
|
||||||
|
DB_SCHEMA = var.db_schema
|
||||||
},
|
},
|
||||||
var.bot_purchase_parser_model == null ? {} : {
|
var.bot_purchase_parser_model == null ? {} : {
|
||||||
PURCHASE_PARSER_MODEL = var.bot_purchase_parser_model
|
PURCHASE_PARSER_MODEL = var.bot_purchase_parser_model
|
||||||
|
|||||||
@@ -259,3 +259,9 @@ variable "github_deploy_service_account_id" {
|
|||||||
type = string
|
type = string
|
||||||
default = "github-deployer"
|
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 .",
|
"format:check": "bunx oxfmt --check .",
|
||||||
"db:generate": "bunx drizzle-kit generate --config packages/db/drizzle.config.ts",
|
"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: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:check": "bun run scripts/check-migration-hygiene.ts",
|
||||||
"db:migrations:manifest": "bun run scripts/update-migration-checksums.ts",
|
"db:migrations:manifest": "bun run scripts/update-migration-checksums.ts",
|
||||||
"db:push": "bunx drizzle-kit push --config packages/db/drizzle.config.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: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",
|
"review:coderabbit": "coderabbit --prompt-only --base main || ~/.local/bin/coderabbit --prompt-only --base main",
|
||||||
"infra:fmt": "terraform -chdir=infra/terraform fmt -recursive",
|
"infra:fmt": "terraform -chdir=infra/terraform fmt -recursive",
|
||||||
"infra:fmt:check": "terraform -chdir=infra/terraform fmt -check -recursive",
|
"infra:fmt:check": "terraform -chdir=infra/terraform fmt -check -recursive",
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { defineConfig } from 'drizzle-kit'
|
import { defineConfig } from 'drizzle-kit'
|
||||||
|
|
||||||
const dbCredentials = process.env.DATABASE_URL
|
|
||||||
? {
|
|
||||||
url: process.env.DATABASE_URL
|
|
||||||
}
|
|
||||||
: undefined
|
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
dialect: 'postgresql',
|
dialect: 'postgresql',
|
||||||
schema: './packages/db/src/schema.ts',
|
schema: './packages/db/src/schema.ts',
|
||||||
out: './packages/db/drizzle',
|
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,
|
"when": 1773327708167,
|
||||||
"tag": "0019_faithful_madame_masque",
|
"tag": "0019_faithful_madame_masque",
|
||||||
"breakpoints": true
|
"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 = {}) {
|
export function createDbClient(databaseUrl: string, options: DbClientOptions = {}) {
|
||||||
|
const dbSchema = process.env.DB_SCHEMA || 'public'
|
||||||
|
|
||||||
const queryClient = postgres(databaseUrl, {
|
const queryClient = postgres(databaseUrl, {
|
||||||
max: options.max ?? 5,
|
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)
|
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'
|
const PROJECT_ID = 'gen-lang-client-0200379851'
|
||||||
|
|
||||||
async function secretExists(name: string): Promise<boolean> {
|
async function secretExists(name: string): Promise<boolean> {
|
||||||
const result =
|
const result = await $`gcloud secrets describe ${name} --project=${PROJECT_ID}`.quiet().nothrow()
|
||||||
(await $`gcloud secrets describe ${name} --project=${PROJECT_ID}`.quiet().exitCode) === 0
|
return result.exitCode === 0
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createSecret(name: string, value: string) {
|
async function createSecret(name: string, value: string) {
|
||||||
|
|||||||
Reference in New Issue
Block a user