feat: run pending DB migrations at startup with advisory lock #68

Closed
pook wants to merge 1 commit from feat/startup-migrations into main
Owner

Summary

  • Adds runMigrations() in packages/api/src/db/migrate.ts that runs pending Drizzle migrations before the HTTP server accepts traffic
  • Uses pg_advisory_lock to prevent concurrent migration runs across multiple instances
  • Failed migrations log structured JSON and call process.exit(1) (fail-fast)
  • Already-applied migrations are automatically skipped by Drizzle's built-in tracking
  • Wires up /health/ready endpoint to verify DB connectivity

Files changed

  • packages/api/src/db/migrate.ts — new migration runner
  • packages/api/src/index.ts — calls runMigrations() before app setup
  • packages/api/src/routes/health.ts — readiness probe checks DB

How it works

  1. On startup, a dedicated single-connection client acquires pg_advisory_lock(123456789)
  2. drizzle-orm/postgres-js/migrator runs all pending migrations from ./drizzle/
  3. Lock is released and migration connection is closed
  4. App proceeds to listen on the HTTP port
  5. If any migration fails, the process exits with code 1

Test plan

  • Start app with no pending migrations — logs applied with 0 duration
  • Add a new migration file, restart — migration is applied
  • Start two instances simultaneously — second waits for lock, skips already-applied
  • Introduce a broken migration SQL — app exits with code 1
  • Hit /health/ready — returns {ready: true} when DB is up

Closes #33

🤖 Generated with Claude Code

## Summary - Adds `runMigrations()` in `packages/api/src/db/migrate.ts` that runs pending Drizzle migrations before the HTTP server accepts traffic - Uses `pg_advisory_lock` to prevent concurrent migration runs across multiple instances - Failed migrations log structured JSON and call `process.exit(1)` (fail-fast) - Already-applied migrations are automatically skipped by Drizzle's built-in tracking - Wires up `/health/ready` endpoint to verify DB connectivity ## Files changed - `packages/api/src/db/migrate.ts` — new migration runner - `packages/api/src/index.ts` — calls `runMigrations()` before app setup - `packages/api/src/routes/health.ts` — readiness probe checks DB ## How it works 1. On startup, a dedicated single-connection client acquires `pg_advisory_lock(123456789)` 2. `drizzle-orm/postgres-js/migrator` runs all pending migrations from `./drizzle/` 3. Lock is released and migration connection is closed 4. App proceeds to listen on the HTTP port 5. If any migration fails, the process exits with code 1 ## Test plan - [ ] Start app with no pending migrations — logs `applied` with 0 duration - [ ] Add a new migration file, restart — migration is applied - [ ] Start two instances simultaneously — second waits for lock, skips already-applied - [ ] Introduce a broken migration SQL — app exits with code 1 - [ ] Hit `/health/ready` — returns `{ready: true}` when DB is up Closes #33 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat: run pending database migrations at startup with advisory lock
Some checks are pending
agent-worker/pr-tests Running PR tests...
d5c3cdcfa4
Adds a migration runner that executes before the HTTP server accepts
traffic. Uses pg_advisory_lock to prevent concurrent migration runs
across multiple instances. Failed migrations cause process.exit(1)
for fail-fast behavior. All migration activity is logged as structured
JSON. Also wires up the /health/ready endpoint to verify DB connectivity.

Closes #33

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Author
Owner

⚠️ No Test Suite Detected

Commit: d5c3cdcf

No test script found in package.json. Add a test script to enable automated testing.

## ⚠️ No Test Suite Detected **Commit:** `d5c3cdcf` No `test` script found in `package.json`. Add a test script to enable automated testing.
Author
Owner

Review notes (agent-bot):

  • Issue link: Closes #33 is present. ✓
  • Advisory lock pattern (pg_advisory_lock(123456789)) is correct for preventing concurrent migrations.
  • Hardcoded lock ID 123456789 works but consider defining it as a named constant for clarity.
  • process.exit(1) on migration failure is the right call for fail-fast startup.
  • The /health/ready endpoint checking DB connectivity is a good addition for orchestration (k8s readiness probes).
**Review notes (agent-bot):** - Issue link: Closes #33 is present. ✓ - Advisory lock pattern (`pg_advisory_lock(123456789)`) is correct for preventing concurrent migrations. - Hardcoded lock ID `123456789` works but consider defining it as a named constant for clarity. - `process.exit(1)` on migration failure is the right call for fail-fast startup. - The `/health/ready` endpoint checking DB connectivity is a good addition for orchestration (k8s readiness probes).
Author
Owner

Closed 2026-04-10 during pipeline triage.

Merge conflicts with current main were blocking the CEO agent's backlog view. The compliancebot repo had ~60 open PRs and 141 open agent-task issues. CEO couldn't see progress and kept duplicating work due to a git-push race in agent-worker (now fixed — runId threaded through dispatch pipeline for unique branch names).

Reopen / resubmit against current main if the work is still relevant. Shim /shim/ceo route now injects open issues + PRs into the CEO prompt and refuses dispatch when backlog exceeds 20.

Closed 2026-04-10 during pipeline triage. Merge conflicts with current main were blocking the CEO agent's backlog view. The compliancebot repo had ~60 open PRs and 141 open agent-task issues. CEO couldn't see progress and kept duplicating work due to a git-push race in agent-worker (now fixed — runId threaded through dispatch pipeline for unique branch names). Reopen / resubmit against current main if the work is still relevant. Shim `/shim/ceo` route now injects open issues + PRs into the CEO prompt and refuses dispatch when backlog exceeds 20.
pook closed this pull request 2026-04-10 15:08:20 -04:00
Some checks are pending
agent-worker/pr-tests Running PR tests...

Pull request closed

Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
pook/compliancebot!68
No description provided.