#!/bin/sh # Create necessary directories mkdir -p /app/data mkdir -p /app/public/uploads mkdir -p /app/public/uploads/backgrounds # Function to deploy migrations with automatic failure resolution deploy_migrations() { echo "Deploying migrations..." # Try to deploy migrations and capture both output and exit code # Use a temporary file to capture exit code since tee masks it pnpm dlx prisma migrate deploy > /tmp/migrate.log 2>&1 MIGRATE_EXIT=$? cat /tmp/migrate.log # Display output if [ $MIGRATE_EXIT -eq 0 ]; then echo "Migrations deployed successfully" return 0 fi # Check if error is about failed migrations (P3009) if ! grep -q "P3009" /tmp/migrate.log && ! grep -q "failed migrations" /tmp/migrate.log; then echo "Migration error is not about failed migrations" return 1 fi echo "Found failed migrations, attempting to resolve..." # Extract migration name from error - look for text between backticks # Pattern: The `20251210120000_add_event_feedback` migration MIGRATION_NAME=$(grep -oE "\`[0-9_]+[a-zA-Z_]+\`" /tmp/migrate.log | tr -d '\`' | head -1) # If still not found, try without backticks (fallback) if [ -z "$MIGRATION_NAME" ]; then MIGRATION_NAME=$(grep "failed" /tmp/migrate.log | grep -oE "[0-9]{14}_[a-zA-Z_]+" | head -1) fi if [ -z "$MIGRATION_NAME" ]; then echo "Could not extract migration name from error. Log content:" cat /tmp/migrate.log return 1 fi echo "Resolving failed migration: $MIGRATION_NAME" # First, try the standard Prisma resolve command RESOLVE_OUTPUT=$(pnpm dlx prisma migrate resolve --applied "$MIGRATION_NAME" 2>&1) RESOLVE_EXIT=$? echo "$RESOLVE_OUTPUT" # If Prisma resolve fails (e.g., migration files not found), resolve directly in database if [ $RESOLVE_EXIT -ne 0 ]; then if echo "$RESOLVE_OUTPUT" | grep -q "P3017\|could not be found"; then echo "Migration files not found, resolving directly in database..." # Use sqlite3 to mark migration as applied directly in _prisma_migrations table # Check if sqlite3 is available if command -v sqlite3 >/dev/null 2>&1; then # Extract database path from DATABASE_URL (format: file:/app/data/dev.db) DB_PATH=$(echo "$DATABASE_URL" | sed 's|file:||') if [ -z "$DB_PATH" ] || [ "$DB_PATH" = "$DATABASE_URL" ]; then DB_PATH="/app/data/dev.db" fi # Ensure database file exists if [ ! -f "$DB_PATH" ]; then echo "Database file not found at $DB_PATH" else echo "Updating migration status in database: $DB_PATH" # Get current timestamp in milliseconds TIMESTAMP=$(date +%s)000 # Update the migration record sqlite3 "$DB_PATH" "UPDATE _prisma_migrations SET finished_at = $TIMESTAMP, rolled_back_at = NULL WHERE migration_name = '$MIGRATION_NAME' AND finished_at IS NULL;" 2>&1 if [ $? -eq 0 ]; then echo "Migration marked as applied in database" # Verify the update RESULT=$(sqlite3 "$DB_PATH" "SELECT migration_name, finished_at FROM _prisma_migrations WHERE migration_name = '$MIGRATION_NAME';" 2>&1) echo "Migration status: $RESULT" else echo "Failed to update database directly" fi fi else echo "sqlite3 not available, cannot resolve directly in database" echo "Install sqlite3 in Dockerfile: RUN apk add --no-cache sqlite" fi elif echo "$RESOLVE_OUTPUT" | grep -q "already recorded as applied"; then echo "Migration is already marked as applied" else echo "Failed to resolve migration: $RESOLVE_OUTPUT" fi fi # Retry migration deploy after resolution attempt echo "Retrying migration deploy..." if pnpm dlx prisma migrate deploy 2>&1; then echo "Migrations deployed successfully after resolution" return 0 else echo "Migration deploy still failed after resolution, but continuing..." return 0 fi } # Deploy migrations (don't fail if it errors - app might still work) deploy_migrations || { echo "Migration deployment had issues, but continuing to start app..." } # Start the application exec pnpm start