962bc48738
## What
Adds the ability to **automatically migrate the dedicated run-ops
database** (the NEW DB in the run-ops split), matching how every other
database in the system is migrated. Follow-up to the run-ops split
activation.
## Changes
- **Migrate runner** — new
`internal-packages/run-ops-database/scripts/migrate.mjs`, exposed as
`db:migrate:deploy` / `db:migrate:status`. Connects via
`RUN_OPS_DATABASE_URL` (the same var the app uses) and expands `${VAR}`
refs like Prisma's dotenv.
- **Self-host** — `docker/scripts/entrypoint.sh` runs the run-ops
migration on boot when the DB is configured, gated by
`SKIP_RUN_OPS_MIGRATIONS`. Single-DB installs never set the URL, so it's
a clean no-op.
- **Single env-var family** — the run-ops DB is now addressed by one
canonical `RUN_OPS_*` family, connect path and migrations resolving the
identical URL:
- `RUN_OPS_DATABASE_URL` (writer) — replaces `TASK_RUN_DATABASE_URL`
- `RUN_OPS_LEGACY_DATABASE_URL` — replaces
`TASK_RUN_LEGACY_DATABASE_URL`
- `RUN_OPS_DATABASE_READ_REPLICA_URL` — replaces
`TASK_RUN_DATABASE_READ_REPLICA_URL`
- the old `TASK_RUN_*` aliases, the `??` coalesce, the
`runOpsNewDatabaseUrl` indirection, and the migrate-only `directUrl` are
all removed (consumers read `env.RUN_OPS_DATABASE_URL` directly).
`directUrl` was dropped because it was only ever used by `prisma
migrate` (never the app runtime) to bypass a pooler for advisory locks —
premature here since the run-ops connection isn't wired to the app yet.
If a pooler is later introduced for the app, a direct URL can be
reintroduced then.
## Safety
- **Pure rename** — nothing deployed sets any `TASK_RUN_*` var (the
split isn't activated anywhere yet; `.env.example`, docker-compose, and
cloud already use `RUN_OPS_*`), so there is no config migration.
- **Single-DB / self-host** — no new required env var; entrypoint and
migrate are no-ops when `RUN_OPS_DATABASE_URL` is unset.
- **Cloud** — runs migrations as pre-deploy ECS tasks (companion cloud
PR), calling these same `db:migrate:deploy` / `db:migrate:status`
commands.
## Verification
- Live migration against a fresh scratch DB with only
`RUN_OPS_DATABASE_URL` set: both migrations applied, no `P1012`/`P1013`;
`${VAR}` expansion, idempotent re-run, `status`, and no-op skip all
pass.
- Schema parity 4/4; `typecheck --filter webapp` 18/18; affected
split/replication tests 34/34.
## Scope
This delivers automatic migrations only. Enabling the app to *use* the
new DB (setting `RUN_OPS_DATABASE_URL` + `RUN_OPS_SPLIT_ENABLED` on the
service) is a separate activation step.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
79 lines
2.7 KiB
Bash
Executable File
79 lines
2.7 KiB
Bash
Executable File
#!/bin/sh
|
||
set -xe
|
||
|
||
if [ -n "$DATABASE_HOST" ]; then
|
||
scripts/wait-for-it.sh ${DATABASE_HOST} -- echo "database is up"
|
||
fi
|
||
|
||
if [ "$SKIP_POSTGRES_MIGRATIONS" != "1" ]; then
|
||
echo "Running prisma migrations"
|
||
pnpm --filter @trigger.dev/database db:migrate:deploy
|
||
echo "Prisma migrations done"
|
||
else
|
||
echo "SKIP_POSTGRES_MIGRATIONS=1, skipping Postgres migrations."
|
||
fi
|
||
|
||
# Run-ops split: migrate the dedicated NEW run-ops database only when it is configured. Single-DB
|
||
# installs never set the URL, so this is a no-op there.
|
||
if [ -n "$RUN_OPS_DATABASE_URL" ]; then
|
||
if [ "$SKIP_RUN_OPS_MIGRATIONS" != "1" ]; then
|
||
echo "Running run-ops migrations"
|
||
pnpm --filter @internal/run-ops-database db:migrate:deploy
|
||
echo "Run-ops migrations done"
|
||
else
|
||
echo "SKIP_RUN_OPS_MIGRATIONS=1, skipping run-ops migrations."
|
||
fi
|
||
else
|
||
echo "RUN_OPS_DATABASE_URL not set, skipping run-ops migrations."
|
||
fi
|
||
|
||
if [ "$SKIP_DASHBOARD_AGENT_MIGRATIONS" != "1" ]; then
|
||
echo "Running dashboard agent migrations"
|
||
pnpm --filter @internal/dashboard-agent-db db:migrate:deploy
|
||
echo "Dashboard agent migrations done"
|
||
else
|
||
echo "SKIP_DASHBOARD_AGENT_MIGRATIONS=1, skipping dashboard agent migrations."
|
||
fi
|
||
|
||
if [ -n "$CLICKHOUSE_URL" ] && [ "$SKIP_CLICKHOUSE_MIGRATIONS" != "1" ]; then
|
||
# Run ClickHouse migrations
|
||
echo "Running ClickHouse migrations..."
|
||
export GOOSE_DRIVER=clickhouse
|
||
|
||
# Ensure secure=true is in the connection string
|
||
if echo "$CLICKHOUSE_URL" | grep -q "secure="; then
|
||
# secure parameter already exists, use as is
|
||
export GOOSE_DBSTRING="$CLICKHOUSE_URL"
|
||
elif echo "$CLICKHOUSE_URL" | grep -q "?"; then
|
||
# URL has query parameters, append secure=true
|
||
export GOOSE_DBSTRING="${CLICKHOUSE_URL}&secure=true"
|
||
else
|
||
# URL has no query parameters, add secure=true
|
||
export GOOSE_DBSTRING="${CLICKHOUSE_URL}?secure=true"
|
||
fi
|
||
|
||
export GOOSE_MIGRATION_DIR=/triggerdotdev/internal-packages/clickhouse/schema
|
||
/usr/local/bin/goose up
|
||
echo "ClickHouse migrations complete."
|
||
elif [ "$SKIP_CLICKHOUSE_MIGRATIONS" = "1" ]; then
|
||
echo "SKIP_CLICKHOUSE_MIGRATIONS=1, skipping ClickHouse migrations."
|
||
else
|
||
echo "CLICKHOUSE_URL not set, skipping ClickHouse migrations."
|
||
fi
|
||
|
||
# Copy over required prisma files
|
||
cp internal-packages/database/prisma/schema.prisma apps/webapp/prisma/
|
||
cp node_modules/@prisma/engines/*.node apps/webapp/prisma/
|
||
|
||
cd /triggerdotdev/apps/webapp
|
||
|
||
|
||
# Decide how much old-space memory Node should get.
|
||
# Use $NODE_MAX_OLD_SPACE_SIZE if it’s set; otherwise fall back to 8192.
|
||
MAX_OLD_SPACE_SIZE="${NODE_MAX_OLD_SPACE_SIZE:-8192}"
|
||
|
||
echo "Setting max old space size to ${MAX_OLD_SPACE_SIZE}"
|
||
|
||
NODE_PATH='/triggerdotdev/node_modules/.pnpm/node_modules' exec dumb-init node --max-old-space-size=${MAX_OLD_SPACE_SIZE} ./build/server.js
|
||
|