2026-04-15 15:59:46 +02:00
|
|
|
#!/usr/bin/env bash
|
2026-04-18 10:01:08 +02:00
|
|
|
# Deploy: SvelteKit-Build per FTPS nach einem der All-Inkl-Webroots.
|
|
|
|
|
# Credentials kommen aus ./.env.local (gitignored), Variablen-Prefix je Ziel.
|
|
|
|
|
#
|
|
|
|
|
# Zielauswahl via DEPLOY_TARGET-Env-Variable:
|
|
|
|
|
# - DEPLOY_TARGET=svelte (default) → svelte.joerg-lohrer.de via SVELTE_FTP_*
|
|
|
|
|
# - DEPLOY_TARGET=staging → staging.joerg-lohrer.de via STAGING_FTP_*
|
|
|
|
|
#
|
|
|
|
|
# Beispiele:
|
|
|
|
|
# ./scripts/deploy-svelte.sh # default: svelte
|
|
|
|
|
# DEPLOY_TARGET=staging ./scripts/deploy-svelte.sh # staging-probelauf
|
|
|
|
|
# DEPLOY_TARGET=svelte ./scripts/deploy-svelte.sh # explizit
|
2026-04-15 15:59:46 +02:00
|
|
|
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
|
|
|
|
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
|
|
|
cd "$ROOT"
|
|
|
|
|
|
|
|
|
|
if [ ! -f .env.local ]; then
|
|
|
|
|
echo "FEHLER: .env.local fehlt — Credentials ergänzen (siehe .env.example)." >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2026-04-18 10:01:08 +02:00
|
|
|
TARGET="${DEPLOY_TARGET:-svelte}"
|
|
|
|
|
case "$TARGET" in
|
|
|
|
|
svelte)
|
|
|
|
|
PREFIX="SVELTE_FTP_"
|
|
|
|
|
PUBLIC_URL="https://svelte.joerg-lohrer.de/"
|
|
|
|
|
SITE_URL="https://svelte.joerg-lohrer.de"
|
|
|
|
|
;;
|
|
|
|
|
staging)
|
|
|
|
|
PREFIX="STAGING_FTP_"
|
|
|
|
|
PUBLIC_URL="https://staging.joerg-lohrer.de/"
|
|
|
|
|
SITE_URL="https://staging.joerg-lohrer.de"
|
|
|
|
|
;;
|
|
|
|
|
prod)
|
|
|
|
|
# Deploy auf staging-ftp (joerglohrer26 = aktueller cutover-webroot),
|
|
|
|
|
# aber mit og:url auf der hauptdomain.
|
|
|
|
|
PREFIX="STAGING_FTP_"
|
|
|
|
|
PUBLIC_URL="https://joerg-lohrer.de/"
|
|
|
|
|
SITE_URL="https://joerg-lohrer.de"
|
|
|
|
|
;;
|
|
|
|
|
*)
|
|
|
|
|
echo "FEHLER: unbekanntes DEPLOY_TARGET='$TARGET' (erlaubt: svelte, staging, prod)." >&2
|
|
|
|
|
exit 2
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
|
|
|
|
|
# Werte direkt aus .env.local lesen (nicht via `source`, weil
|
|
|
|
|
# password-shell-metazeichen wie ( ) & kein sourcing überstehen).
|
|
|
|
|
read_env() {
|
|
|
|
|
local key="$1"
|
|
|
|
|
# nimmt die erste zeile, die exakt mit KEY= beginnt, schneidet alles nach
|
|
|
|
|
# dem ersten = ab, gibt den rest 1:1 zurück (auch mit sonderzeichen).
|
|
|
|
|
awk -F= -v k="$key" 'BEGIN{found=0} $1==k && !found { sub("^" k "=",""); print; found=1 }' .env.local
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FTP_HOST_KEY="${PREFIX}HOST"
|
|
|
|
|
FTP_USER_KEY="${PREFIX}USER"
|
|
|
|
|
FTP_PASS_KEY="${PREFIX}PASS"
|
|
|
|
|
FTP_PATH_KEY="${PREFIX}REMOTE_PATH"
|
|
|
|
|
|
|
|
|
|
FTP_HOST="$(read_env "$FTP_HOST_KEY")"
|
|
|
|
|
FTP_USER="$(read_env "$FTP_USER_KEY")"
|
|
|
|
|
FTP_PASS="$(read_env "$FTP_PASS_KEY")"
|
|
|
|
|
FTP_REMOTE_PATH="$(read_env "$FTP_PATH_KEY")"
|
|
|
|
|
|
|
|
|
|
for pair in "$FTP_HOST_KEY:$FTP_HOST" "$FTP_USER_KEY:$FTP_USER" \
|
|
|
|
|
"$FTP_PASS_KEY:$FTP_PASS" "$FTP_PATH_KEY:$FTP_REMOTE_PATH"; do
|
|
|
|
|
key="${pair%%:*}"
|
|
|
|
|
val="${pair#*:}"
|
|
|
|
|
if [ -z "$val" ]; then
|
|
|
|
|
echo "FEHLER: $key fehlt in .env.local." >&2
|
2026-04-15 15:59:46 +02:00
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
BUILD_DIR="$ROOT/app/build"
|
2026-04-18 10:01:08 +02:00
|
|
|
|
|
|
|
|
echo "Baue SvelteKit …"
|
|
|
|
|
(cd "$ROOT/app" && npm run build >/dev/null 2>&1) || {
|
|
|
|
|
echo "FEHLER: Build fehlgeschlagen. 'cd app && npm run build' manuell ausführen zum Debuggen." >&2
|
|
|
|
|
exit 1
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 15:59:46 +02:00
|
|
|
if [ ! -d "$BUILD_DIR" ]; then
|
2026-04-18 10:01:08 +02:00
|
|
|
echo "FEHLER: app/build nicht vorhanden nach build." >&2
|
2026-04-15 15:59:46 +02:00
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2026-04-18 10:01:08 +02:00
|
|
|
# __SITE_URL__-Platzhalter in allen HTML-Dateien durch die ziel-spezifische
|
|
|
|
|
# SITE_URL ersetzen (für og:url / canonical). Nicht im quellcode hart
|
|
|
|
|
# setzen, damit ein builder einmal baut und mehrere domains damit bedienen
|
|
|
|
|
# kann.
|
|
|
|
|
echo "Patche __SITE_URL__ → $SITE_URL in HTML-Dateien …"
|
|
|
|
|
find "$BUILD_DIR" -type f -name "*.html" -print0 | while IFS= read -r -d '' html_file; do
|
|
|
|
|
# sed -i '' für macOS-kompatibilität (bsd sed braucht leeres backup-arg)
|
|
|
|
|
sed -i '' "s|__SITE_URL__|$SITE_URL|g" "$html_file"
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
echo "Ziel: $TARGET ($PUBLIC_URL)"
|
|
|
|
|
echo "Lade Build von $BUILD_DIR nach ftp://$FTP_HOST$FTP_REMOTE_PATH"
|
2026-04-15 15:59:46 +02:00
|
|
|
|
|
|
|
|
# pro Datei ein curl-Upload (zuverlässig auf macOS ohne lftp)
|
|
|
|
|
find "$BUILD_DIR" -type f -print0 | while IFS= read -r -d '' local_file; do
|
|
|
|
|
rel="${local_file#$BUILD_DIR/}"
|
2026-04-18 10:01:08 +02:00
|
|
|
remote="ftp://$FTP_HOST${FTP_REMOTE_PATH%/}/$rel"
|
2026-04-15 15:59:46 +02:00
|
|
|
echo " → $rel"
|
|
|
|
|
# --tls-max 1.2: All-Inkl/Kasserver FTPS schließt bei TLS 1.3 die Data-
|
|
|
|
|
# Connection mit "426 Transfer aborted" — mit 1.2 läuft es sauber durch.
|
|
|
|
|
curl -sSf --ssl-reqd --tls-max 1.2 --ftp-create-dirs \
|
|
|
|
|
--retry 3 --retry-delay 2 --retry-all-errors \
|
|
|
|
|
--connect-timeout 15 \
|
2026-04-18 10:01:08 +02:00
|
|
|
--user "$FTP_USER:$FTP_PASS" \
|
2026-04-15 15:59:46 +02:00
|
|
|
-T "$local_file" "$remote"
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
echo "Upload fertig. Live-Check:"
|
2026-04-18 10:01:08 +02:00
|
|
|
curl -sIL "$PUBLIC_URL" | head -5
|