Files
optima/api/prisma/migrate-entrypoint.sh
T
HoloPanio f56c49e242 fix(migrate): handle existing Company/UnifiSite data in catch-up migration
Two bugs in the catch-up migration that only manifest with real production data:

1. Company (4520 rows): uid was added as TEXT NOT NULL DEFAULT '' causing
   all existing rows to get uid='' which makes the PRIMARY KEY constraint
   fail with 'could not create unique index, Key (uid)=() is duplicated'.
   Fix: add uid as nullable, UPDATE uid = id (copies the existing CUID text
   PK into uid), then SET NOT NULL, then swap PK. Also populate the new
   integer id column from cw_CompanyId (which is fully populated in prod).

2. UnifiSite (180 rows): old approach just dropped the text companyId and
   added a null integer column, destroying all company relationships.
   Fix: add companyId_int, UPDATE via JOIN on Company.uid (= old Company.id
   text), drop old text column, rename integer column.

Also fix the P3009 handler in migrate-entrypoint.sh: Prisma may emit ANSI
color codes even without a TTY, wrapping backticks in escape sequences and
breaking the regex match. Fix: strip ANSI codes with sed before extracting
the migration name. Also simplify the regex from a rigid format match to a
simpler backtick-content grep.

Production DB manually unblocked (migrate resolve --rolled-back) so the
next deploy will cleanly apply the corrected migration.
2026-04-08 18:07:16 +00:00

54 lines
2.0 KiB
Bash
Executable File

#!/bin/sh
set -e
# ---------------------------------------------------------------------------
# Run prisma migrate deploy. On P3009 (a failed migration is blocking deploy),
# extract the migration name from the error, resolve it as rolled-back, and
# retry. All migration SQL in this repo is idempotent so a re-run is safe.
# Loop handles multiple blocked migrations; max retries prevents infinite loops.
# ---------------------------------------------------------------------------
MAX_RETRIES=10
ATTEMPT=0
while [ $ATTEMPT -lt $MAX_RETRIES ]; do
ATTEMPT=$((ATTEMPT + 1))
echo "[migrate] Running prisma migrate deploy (attempt $ATTEMPT)..."
EXIT_CODE=0
DEPLOY_OUTPUT=$(bunx prisma migrate deploy 2>&1) || EXIT_CODE=$?
echo "$DEPLOY_OUTPUT"
if [ $EXIT_CODE -eq 0 ]; then
echo "[migrate] All migrations applied successfully."
exit 0
fi
# P3009: a previously-failed migration is blocking deploy.
# The error message contains the migration name in backticks:
# The `20260402000000_fix_severity_typo` migration started at ... failed
# Strip ANSI escape codes first (Prisma may colorize output even without TTY),
# then use a simple backtick-content regex rather than a rigid format match.
CLEAN_OUTPUT=$(printf '%s\n' "$DEPLOY_OUTPUT" | sed 's/\x1b\[[0-9;]*[mGKHFJr]//g')
if printf '%s\n' "$CLEAN_OUTPUT" | grep -q "P3009"; then
FAILED=$(printf '%s\n' "$CLEAN_OUTPUT" | grep -o '`[^`]*`' | grep '[0-9]' | tr -d '`' | head -1)
if [ -n "$FAILED" ]; then
echo "[migrate] Resolving failed migration as rolled-back: $FAILED"
RESOLVE_OUTPUT=""
RESOLVE_EXIT=0
RESOLVE_OUTPUT=$(bunx prisma migrate resolve --rolled-back "$FAILED" 2>&1) || RESOLVE_EXIT=$?
echo "$RESOLVE_OUTPUT"
if [ $RESOLVE_EXIT -ne 0 ]; then
echo "[migrate] Failed to resolve migration $FAILED (exit $RESOLVE_EXIT). Aborting."
exit 1
fi
continue
fi
fi
echo "[migrate] Migration failed with a non-recoverable error."
exit 1
done
echo "[migrate] Exceeded max retries ($MAX_RETRIES). Giving up."
exit 1