Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/schema-drift.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
- name: Build the expected schema from committed migrations
env:
DATABASE_URL: postgres://postgres:postgres@localhost:5432/postgres
run: yarn db:migrate
run: yarn db:drift:seed-expected
- name: Compare production against it
env:
EXPECTED_DATABASE_URL: postgres://postgres:postgres@localhost:5432/postgres
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"db:generate": "drizzle-kit generate",
"db:migrate": "drizzle-kit migrate",
"db:drift": "tsx scripts/schema-drift/check.ts",
"db:drift:seed-expected": "tsx scripts/schema-drift/apply-migrations.ts",
"db:push": "drizzle-kit push"
},
"dependencies": {
Expand Down
30 changes: 30 additions & 0 deletions scripts/schema-drift/apply-migrations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Build the "expected" schema for drift comparison using the exact same migration
* mechanism production uses (app/lib/db/migrations.ts -> public.__clawproxy_migrations),
* rather than `drizzle-kit migrate` which tracks in a different table
* (drizzle.__drizzle_migrations) that production never creates.
*/
import postgres from 'postgres';

import { applyCommittedMigrations } from '../../app/lib/db/migrations';

async function main() {
const url = process.env.DATABASE_URL;
if (!url) {
console.error('DATABASE_URL is required');
process.exit(2);
}

const sql = postgres(url, { max: 1 });
try {
await applyCommittedMigrations(sql);
console.log('[schema-drift] applied committed migrations to the expected database');
} finally {
await sql.end({ timeout: 5 });
}
}

main().catch((error) => {
console.error('[schema-drift] failed to apply migrations:', error);
process.exit(2);
});
6 changes: 5 additions & 1 deletion scripts/schema-drift/collect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,12 @@ export async function collectSnapshot(databaseUrl: string): Promise<SchemaSnapsh
ORDER BY tablename, indexname
`) as unknown as IndexInfo[];

// The app's own migrator (app/lib/db/migrations.ts) tracks applied migrations in
// public.__clawproxy_migrations, not drizzle's own drizzle.__drizzle_migrations table
// (that table only exists when `drizzle-kit migrate` was run directly against a DB,
// which production never does).
const migrationRows = await sql<{ hash: string }[]>`
SELECT hash FROM drizzle.__drizzle_migrations ORDER BY created_at, id
SELECT hash FROM public.__clawproxy_migrations ORDER BY applied_at, name
`;

return {
Expand Down
Loading