Update claude.md to push more tests. (#84)

* Update claude.md to push more tests.

* Archiving old plans.

* fix: run DB migrations programmatically on server startup

Replace unreliable drizzle-kit CLI migration with drizzle-orm's built-in
migrator running in the server process before accepting connections. This
ensures migrations are always applied on deploy and fails fast if they error.

- Add runMigrations() to server.ts using drizzle-orm/postgres-js/migrator
- Skip migrations in development (handled manually via db:migrate)
- Add DATABASE_URL guard with a clear error message
- Remove start:production script (now identical to start)
- Update Dockerfile CMD to use npm run start

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Chris Parsons 2026-03-07 22:31:04 -08:00 committed by GitHub
parent 8aa1726b12
commit 35fe84a1dd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 33 additions and 6 deletions

View file

@ -163,6 +163,15 @@ The draft system implements snake draft:
- **Fixtures**: Reusable test data in `app/test/fixtures/` - **Fixtures**: Reusable test data in `app/test/fixtures/`
- See `TESTING.md` for comprehensive testing guide - See `TESTING.md` for comprehensive testing guide
**IMPORTANT: Tests are required for new features.** When adding any new feature, you must include appropriate tests:
- New model functions → unit tests in a co-located `__tests__/` directory
- New route loaders/actions → unit or integration tests for the logic
- New utility functions → unit tests
- New components with non-trivial logic → component tests
- Critical user flows → Cypress E2E tests
Do not consider a feature complete until tests are written and passing.
## Common Workflows ## Common Workflows
### Adding a New Route ### Adding a New Route

View file

@ -22,4 +22,4 @@ COPY --from=build-env /app/dist /app/dist
COPY ./drizzle /app/drizzle COPY ./drizzle /app/drizzle
COPY ./drizzle.config.ts /app/drizzle.config.ts COPY ./drizzle.config.ts /app/drizzle.config.ts
WORKDIR /app WORKDIR /app
CMD ["npm", "run", "start:production"] CMD ["npm", "run", "start"]

View file

@ -10,7 +10,6 @@
"db:migrate": "dotenv -- drizzle-kit migrate", "db:migrate": "dotenv -- drizzle-kit migrate",
"dev": "dotenv -- tsx watch server.ts", "dev": "dotenv -- tsx watch server.ts",
"start": "node dist/server.js", "start": "node dist/server.js",
"start:production": "drizzle-kit migrate && node dist/server.js",
"test": "vitest", "test": "vitest",
"test:ui": "vitest --ui", "test:ui": "vitest --ui",
"test:coverage": "vitest --coverage", "test:coverage": "vitest --coverage",

View file

@ -6,6 +6,9 @@ import { createServer } from "http";
import type { ViteDevServer } from "vite"; import type { ViteDevServer } from "vite";
import path from "path"; import path from "path";
import { fileURLToPath } from "url"; import { fileURLToPath } from "url";
import { drizzle } from "drizzle-orm/postgres-js";
import { migrate } from "drizzle-orm/postgres-js/migrator";
import postgres from "postgres";
// ESM module resolution helpers // ESM module resolution helpers
const __filename = fileURLToPath(import.meta.url); const __filename = fileURLToPath(import.meta.url);
@ -20,6 +23,20 @@ const CLIENT_ASSETS_PATH = path.join(PROJECT_ROOT, "build/client/assets");
const DEVELOPMENT = process.env.NODE_ENV === "development"; const DEVELOPMENT = process.env.NODE_ENV === "development";
const PORT = Number.parseInt(process.env.PORT || "3000", 10); const PORT = Number.parseInt(process.env.PORT || "3000", 10);
async function runMigrations(): Promise<void> {
if (!process.env.DATABASE_URL) {
throw new Error("DATABASE_URL is required");
}
const client = postgres(process.env.DATABASE_URL);
try {
const db = drizzle(client);
await migrate(db, { migrationsFolder: path.join(PROJECT_ROOT, "drizzle") });
console.log("Migrations complete");
} finally {
await client.end();
}
}
async function createAppServer(): Promise<void> { async function createAppServer(): Promise<void> {
const app: Express = express(); const app: Express = express();
@ -82,7 +99,9 @@ async function createAppServer(): Promise<void> {
} }
// Start the server with error handling // Start the server with error handling
createAppServer().catch((error) => { (DEVELOPMENT ? Promise.resolve() : runMigrations())
.then(createAppServer)
.catch((error) => {
console.error("Failed to start server:", error); console.error("Failed to start server:", error);
process.exit(1); process.exit(1);
}); });