L'image prebuilt n'expose pas la commande prisma dans le PATH. Co-authored-by: Cursor <cursoragent@cursor.com>
138 lines
4.7 KiB
Bash
138 lines
4.7 KiB
Bash
#!/bin/sh
|
|
# ============================================================
|
|
# Memento Note — Docker Entrypoint
|
|
# Reliable DB migration for fresh installs and upgrades.
|
|
# ============================================================
|
|
# Strategy:
|
|
# 1. prisma migrate deploy → fresh DB, normal upgrades
|
|
# 2. prisma db push → fallback for DBs without migration history
|
|
# ============================================================
|
|
|
|
set -e
|
|
|
|
BACKUP_DIR="/app/data/backups"
|
|
MAX_BACKUPS=5
|
|
DB_WAIT_RETRIES=30
|
|
DB_WAIT_INTERVAL=2
|
|
MIGRATE_TIMEOUT=120
|
|
|
|
# --- Logging ---
|
|
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] [entrypoint] $*"; }
|
|
warn() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] [entrypoint] WARNING: $*" >&2; }
|
|
err() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] [entrypoint] ERROR: $*" >&2; }
|
|
|
|
# --- Detect database type ---
|
|
DB_TYPE="unknown"
|
|
case "$DATABASE_URL" in
|
|
postgres://*|postgresql://*) DB_TYPE="postgres" ;;
|
|
file:*) DB_TYPE="sqlite" ;;
|
|
esac
|
|
log "Database type: $DB_TYPE"
|
|
|
|
# --- Ensure data directories exist ---
|
|
mkdir -p "$BACKUP_DIR" 2>/dev/null || true
|
|
mkdir -p /app/data/uploads/notes 2>/dev/null || true
|
|
|
|
# --- Wait for database to be reachable ---
|
|
if [ "$DB_TYPE" != "sqlite" ]; then
|
|
log "Waiting for database connection..."
|
|
i=0
|
|
while [ "$i" -lt "$DB_WAIT_RETRIES" ]; do
|
|
if node -e "
|
|
const m = process.env.DATABASE_URL.match(/@([^:\/]+):(\d+)/);
|
|
if (!m) process.exit(1);
|
|
const net = require('net');
|
|
const s = net.createConnection(parseInt(m[2]), m[1], () => { s.end(); process.exit(0); });
|
|
s.setTimeout(3000, () => { s.destroy(); process.exit(1); });
|
|
s.on('error', () => process.exit(1));
|
|
" 2>/dev/null; then
|
|
log "Database is reachable."
|
|
break
|
|
fi
|
|
i=$((i + 1))
|
|
log " Attempt $i/$DB_WAIT_RETRIES — retrying in ${DB_WAIT_INTERVAL}s..."
|
|
sleep "$DB_WAIT_INTERVAL"
|
|
done
|
|
|
|
if [ "$i" -ge "$DB_WAIT_RETRIES" ]; then
|
|
err "Database unreachable after $((DB_WAIT_RETRIES * DB_WAIT_INTERVAL)) seconds."
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# --- Create backup before migration (best-effort) ---
|
|
if [ "$DB_TYPE" = "postgres" ] && command -v pg_dump >/dev/null 2>&1; then
|
|
ts=$(date '+%Y%m%d_%H%M%S')
|
|
backup_file="$BACKUP_DIR/pre_migrate_${ts}.sql.gz"
|
|
log "Creating backup: $backup_file"
|
|
if pg_dump --no-owner --no-privileges --format=plain "$DATABASE_URL" 2>/dev/null | gzip > "$backup_file" 2>/dev/null; then
|
|
size=$(du -h "$backup_file" | cut -f1)
|
|
log "Backup OK ($size)"
|
|
else
|
|
warn "pg_dump failed (DB may be empty). Continuing without backup."
|
|
rm -f "$backup_file"
|
|
fi
|
|
fi
|
|
|
|
# --- Cleanup old backups ---
|
|
count=$(ls -1 "$BACKUP_DIR"/pre_migrate_* 2>/dev/null | wc -l)
|
|
if [ "$count" -gt "$MAX_BACKUPS" ]; then
|
|
to_remove=$((count - MAX_BACKUPS))
|
|
log "Cleaning up $to_remove old backup(s)..."
|
|
ls -1t "$BACKUP_DIR"/pre_migrate_* 2>/dev/null | tail -n "$to_remove" | xargs rm -f
|
|
fi
|
|
|
|
# ============================================================
|
|
# Migration — two strategies
|
|
# ============================================================
|
|
|
|
PRISMA="node ./node_modules/prisma/build/index.js"
|
|
|
|
log "Running database migrations..."
|
|
|
|
# Strategy 1: prisma migrate deploy
|
|
# Works for: fresh DB (empty), existing DB with migration history
|
|
if timeout "$MIGRATE_TIMEOUT" $PRISMA migrate deploy 2>&1; then
|
|
log "Migrations applied successfully."
|
|
else
|
|
migrate_exit=$?
|
|
log "prisma migrate deploy failed (exit $migrate_exit)."
|
|
|
|
# Strategy 2: prisma db push
|
|
# Works for: existing DB without migration history (created with db push),
|
|
# schema drift, or any other case where migrate deploy fails.
|
|
# This syncs schema.prisma → database, preserving existing data.
|
|
log "Falling back to prisma db push..."
|
|
if timeout "$MIGRATE_TIMEOUT" $PRISMA db push --skip-generate --accept-data-loss 2>&1; then
|
|
log "db push completed successfully."
|
|
else
|
|
err "All migration strategies failed."
|
|
err "To fix manually:"
|
|
err " docker compose exec memento-note node ./node_modules/prisma/build/index.js migrate deploy"
|
|
err " docker compose exec memento-note node ./node_modules/prisma/build/index.js db push --skip-generate"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# --- Background cron scheduler ---
|
|
(
|
|
sleep 60
|
|
while true; do
|
|
node -e "
|
|
const http = require('http');
|
|
const req = http.request('http://localhost:3000/api/cron/agents', { method: 'POST' }, (res) => {
|
|
let body = '';
|
|
res.on('data', (d) => body += d);
|
|
res.on('end', () => console.log('[Scheduler] Cron response:', res.statusCode, body));
|
|
});
|
|
req.on('error', (e) => console.error('[Scheduler] Cron error:', e.message));
|
|
req.end();
|
|
" 2>&1 || true
|
|
sleep 300
|
|
done
|
|
) &
|
|
|
|
# --- Start server ---
|
|
log "Starting server..."
|
|
exec node server.js
|