Files
harheimertc/deploy-production.sh
Torsten Schulz (local) 5905dd5784
Some checks failed
Code Analysis (JS/Vue) / analyze (push) Failing after 45s
Enhance deployment script and navigation component for improved data handling and user access
This commit updates the deploy-production.sh script to remove tracked public/data CSV files from the Git index and ensures that backup files are restored correctly, with size verification for integrity. Additionally, it modifies the Navigation.vue component to allow access to the gallery for users with newsletter permissions, enhancing user experience and access control.
2026-01-17 18:34:49 +01:00

399 lines
13 KiB
Bash
Executable File

#!/bin/bash
set -euo pipefail
# Immer im Repo-Verzeichnis arbeiten (wichtig für Backup/Restore mit relativen Pfaden)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
# Deployment Script für Harheimer TC Website
# Sichert Produktivdaten vor dem Build und stellt sie danach wieder her
echo "=== Harheimer TC Deployment ==="
echo ""
echo "Working directory: $(pwd)"
echo ""
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
echo "ERROR: Dieses Script muss im Git-Repository ausgeführt werden (kein .git gefunden)."
exit 1
fi
# Optional (empfohlen): Persistente Daten außerhalb des Git-Repos halten und per Symlink einbinden.
# Das verhindert zuverlässig, dass Git jemals Produktivdaten überschreibt.
DEPLOY_HOME="${DEPLOY_HOME:-${HOME:-/tmp}}"
DATA_ROOT="${DATA_ROOT:-$DEPLOY_HOME/harheimertc-data}"
BACKUP_ROOT="${BACKUP_ROOT:-$DEPLOY_HOME/harheimertc-backups}"
mkdir -p "$DATA_ROOT" "$BACKUP_ROOT"
ensure_symlink_dir() {
local src="$1" # z.B. server/data
local target="$2" # z.B. /var/lib/harheimertc/server-data
mkdir -p "$(dirname "$src")"
mkdir -p "$target"
if [ -L "$src" ]; then
return 0
fi
if [ -d "$src" ]; then
echo " Moving $src -> $target (first-time migration)"
# Merge existing content into target
cp -a "$src/." "$target/" || true
rm -rf "$src"
fi
ln -s "$target" "$src"
echo " Linked $src -> $target"
}
has_tracked_files_under() {
local prefix="$1" # e.g. public/data
# If any file is tracked under this path, symlinking the directory will break git operations
git ls-files "$prefix" | head -n 1 | grep -q .
}
echo "0. Ensuring persistent data directories (recommended)..."
# IMPORTANT: Only symlink server/data if it's not tracked by git.
if has_tracked_files_under "server/data"; then
echo " Skipping symlink for server/data (tracked files detected in git)."
echo " Recommendation: remove server/data/** from git history and keep them only as production data."
else
ensure_symlink_dir "server/data" "$DATA_ROOT/server-data"
fi
# IMPORTANT: Only symlink public/data if it's not tracked by git.
# Otherwise git will error with "path is beyond a symbolic link".
if has_tracked_files_under "public/data"; then
echo " Skipping symlink for public/data (tracked files detected in git)."
echo " Recommendation: remove public/data/*.csv from git history and keep them only as production data."
else
ensure_symlink_dir "public/data" "$DATA_ROOT/public-data"
fi
ensure_symlink_dir "public/uploads" "$DATA_ROOT/public-uploads"
echo ""
# 1. BACKUP: Laufende Produktivdaten VOR allen Git-Operationen sichern
echo "1. Backing up current production data (pre-git)..."
# Human readable timestamp (lokal)
BACKUP_TS="$(date +"%Y-%m-%d_%H-%M-%S")"
BACKUP_DIR="$BACKUP_ROOT/backup_$BACKUP_TS"
mkdir -p "$BACKUP_DIR"
echo " Backup directory: $BACKUP_DIR"
# Backup server data (JSON) und CSVs immer vom Dateisystem, nicht aus 'stash'
if [ -d server/data ]; then
cp -a server/data "$BACKUP_DIR/server-data"
echo " Backed up server/data -> $BACKUP_DIR/server-data"
else
echo "ERROR: server/data existiert nicht. Abbruch, damit wir keine Repo-Defaults ausrollen."
exit 1
fi
if ls public/data/*.csv >/dev/null 2>&1; then
mkdir -p "$BACKUP_DIR/public-data"
cp -a public/data/*.csv "$BACKUP_DIR/public-data/"
echo " Backed up public/data/*.csv -> $BACKUP_DIR/public-data/"
else
echo " No public CSVs to backup (public/data/*.csv not found)"
fi
# 2. Handle local changes and Git Pull
echo "2. Handling local changes and pulling latest from git..."
# Check if there are merge conflicts first
if [ -n "$(git status --porcelain | grep '^UU\|^AA\|^DD')" ]; then
echo " Resolving existing merge conflicts..."
git reset --hard HEAD
fi
# Ensure git operations can run even if we have untracked local artifacts (e.g. backups/)
# We avoid `git stash` (breaks with symlinked tracked paths). Instead, hard-reset and clean safely.
echo " Resetting working tree to HEAD (production data will be restored from backup)..."
git reset --hard HEAD
echo " Cleaning untracked files (excluding data dirs/backups/.env)..."
git clean -fd \
-e server/data \
-e public/data \
-e public/uploads \
-e backups \
-e .env || true
# Pull latest changes
echo " Pulling latest changes..."
git pull
# Reset any accidental changes from stash restore (should be none now)
git reset --hard HEAD >/dev/null 2>&1
# WICHTIG: Entferne public/data Dateien aus Git-Index, falls sie getrackt sind
# (Sie sollten in .gitignore sein, aber falls sie historisch getrackt wurden)
if git ls-files --error-unmatch public/data/*.csv >/dev/null 2>&1; then
echo " WARNING: public/data/*.csv Dateien sind im Git getrackt!"
echo " Entferne sie aus dem Git-Index (Dateien bleiben erhalten)..."
git rm --cached public/data/*.csv 2>/dev/null || true
fi
# 3. Install dependencies
echo ""
echo "3. Installing dependencies..."
npm install
# 4. Remove old build (but keep data!)
echo ""
echo "4. Cleaning build artifacts..."
# Sicherstellen, dass .output vollständig gelöscht wird
if [ -d ".output" ]; then
echo " Removing .output directory..."
rm -rf .output
# Prüfen, ob wirklich gelöscht wurde
if [ -d ".output" ]; then
echo "WARNING: .output konnte nicht vollständig gelöscht werden. Versuche erneut..."
sleep 2
rm -rf .output
if [ -d ".output" ]; then
echo "ERROR: .output konnte auch nach erneutem Versuch nicht gelöscht werden!"
echo "Bitte manuell prüfen und löschen: rm -rf .output"
exit 1
fi
fi
echo " ✓ .output gelöscht"
fi
# Auch .nuxt Cache löschen für sauberen Build
if [ -d ".nuxt" ]; then
echo " Removing .nuxt cache..."
rm -rf .nuxt
echo " ✓ .nuxt gelöscht"
fi
# Prüfe, ob node_modules vorhanden ist (für npm run build)
if [ ! -d "node_modules" ]; then
echo ""
echo "WARNING: node_modules fehlt. Installiere Dependencies..."
npm install
fi
# 5. Build
echo ""
echo "5. Building application..."
echo " Running: npm run build"
echo " (This may take a few minutes...)"
# Clean-Build: Stelle sicher, dass node_modules aktuell ist
echo " Checking dependencies..."
if [ ! -f "node_modules/.package-lock.json" ] && [ ! -f "package-lock.json" ]; then
echo " WARNING: package-lock.json fehlt. Führe npm install aus..."
npm install
fi
# Build mit expliziter Fehlerbehandlung und Output-Capture
BUILD_OUTPUT=$(npm run build 2>&1)
BUILD_EXIT_CODE=$?
# Zeige Build-Output
echo "$BUILD_OUTPUT"
if [ "$BUILD_EXIT_CODE" -ne 0 ]; then
echo ""
echo "ERROR: Build fehlgeschlagen mit Exit-Code $BUILD_EXIT_CODE"
echo "Bitte prüfen Sie die Build-Ausgabe oben auf Fehler."
exit 1
fi
# Prüfe auf Warnungen im Build-Output, die auf Probleme hinweisen
if echo "$BUILD_OUTPUT" | grep -qi "error\|failed\|missing"; then
echo ""
echo "WARNING: Build-Output enthält möglicherweise Fehler oder Warnungen."
echo "Bitte prüfen Sie die Ausgabe oben."
fi
# Prüfe, ob der Build erfolgreich war - mehrere Checks
echo ""
echo " Verifying build output..."
BUILD_FAILED=0
# Check 1: _nuxt Verzeichnis
if [ ! -d ".output/public/_nuxt" ]; then
echo "ERROR: .output/public/_nuxt Verzeichnis fehlt!"
BUILD_FAILED=1
else
NUXT_FILES=$(find .output/public/_nuxt -type f 2>/dev/null | wc -l)
echo " ✓ .output/public/_nuxt vorhanden ($NUXT_FILES Dateien)"
if [ "$NUXT_FILES" -eq 0 ]; then
echo "ERROR: .output/public/_nuxt ist leer!"
BUILD_FAILED=1
else
# Prüfe, ob wichtige Dateien vorhanden sind
JS_FILES=$(find .output/public/_nuxt -name "*.js" 2>/dev/null | wc -l)
CSS_FILES=$(find .output/public/_nuxt -name "*.css" 2>/dev/null | wc -l)
echo " ✓ JS-Dateien: $JS_FILES, CSS-Dateien: $CSS_FILES"
if [ "$JS_FILES" -eq 0 ]; then
echo "ERROR: Keine JS-Dateien in .output/public/_nuxt gefunden!"
BUILD_FAILED=1
fi
fi
fi
# Check 1b: _nuxt/builds Verzeichnis (für Meta-Dateien)
if [ -d ".output/public/_nuxt/builds" ]; then
BUILD_META_FILES=$(find .output/public/_nuxt/builds -type f 2>/dev/null | wc -l)
echo " ✓ .output/public/_nuxt/builds vorhanden ($BUILD_META_FILES Meta-Dateien)"
else
echo "WARNING: .output/public/_nuxt/builds fehlt (kann in manchen Nuxt-Versionen normal sein)"
fi
# Check 2: Server index.mjs
if [ ! -f ".output/server/index.mjs" ]; then
echo "ERROR: .output/server/index.mjs fehlt!"
BUILD_FAILED=1
else
echo " ✓ .output/server/index.mjs vorhanden"
fi
# Check 3: Public Verzeichnis
if [ ! -d ".output/public" ]; then
echo "ERROR: .output/public Verzeichnis fehlt!"
BUILD_FAILED=1
else
echo " ✓ .output/public vorhanden"
fi
# Check 4: Server Verzeichnis
if [ ! -d ".output/server" ]; then
echo "ERROR: .output/server Verzeichnis fehlt!"
BUILD_FAILED=1
else
echo " ✓ .output/server vorhanden"
fi
if [ "$BUILD_FAILED" -eq 1 ]; then
echo ""
echo "ERROR: Build-Verifikation fehlgeschlagen!"
echo "Bitte führen Sie manuell aus:"
echo " rm -rf .output .nuxt"
echo " npm run build"
exit 1
fi
echo " ✓ Build erfolgreich verifiziert"
# 6. Restore Production Data (überschreibe Repo-Defaults mit Backup)
echo ""
echo "6. Restoring production data..."
# Stelle server/data vollständig wieder her (inkl. config.json, users.json, news.json, sessions.json, members.json, membership-applications)
if [ ! -d "$BACKUP_DIR/server-data" ]; then
echo "ERROR: Backup-Verzeichnis $BACKUP_DIR/server-data fehlt. Abbruch."
exit 1
fi
mkdir -p server/data
cp -a "$BACKUP_DIR/server-data/." server/data/
echo " Restored server/data from backup ($BACKUP_DIR/server-data)."
# Stelle alle CSVs wieder her
if ls "$BACKUP_DIR/public-data"/*.csv >/dev/null 2>&1; then
mkdir -p public/data
# WICHTIG: Überschreibe auch Dateien, die aus dem Git-Repository kommen
# Verwende cp mit -f (force) um sicherzustellen, dass Backup-Dateien Vorrang haben
for csv_file in "$BACKUP_DIR/public-data"/*.csv; do
filename=$(basename "$csv_file")
# Überschreibe explizit, auch wenn Datei bereits existiert
cp -f "$csv_file" "public/data/$filename"
# Stelle sicher, dass die Datei wirklich überschrieben wurde
if [ -f "public/data/$filename" ]; then
# Prüfe, ob die Datei wirklich vom Backup kommt (Größenvergleich)
backup_size=$(stat -f%z "$csv_file" 2>/dev/null || stat -c%s "$csv_file" 2>/dev/null || echo "0")
restored_size=$(stat -f%z "public/data/$filename" 2>/dev/null || stat -c%s "public/data/$filename" 2>/dev/null || echo "0")
if [ "$backup_size" = "$restored_size" ] && [ "$backup_size" != "0" ]; then
echo " ✓ Restored public/data/$filename from backup ($backup_size bytes)"
else
echo " ⚠ WARNING: public/data/$filename Größe stimmt nicht überein (Backup: $backup_size, Restored: $restored_size)"
fi
else
echo " ❌ ERROR: Konnte public/data/$filename nicht wiederherstellen!"
fi
done
echo " ✓ All public/data/*.csv files restored from backup ($BACKUP_DIR/public-data)."
# Zusätzliche Sicherheit: Entferne public/data Dateien aus Git-Index, falls sie getrackt sind
# (nach dem Restore, damit sie nicht beim nächsten git reset überschrieben werden)
if git ls-files --error-unmatch public/data/*.csv >/dev/null 2>&1; then
echo " WARNING: public/data/*.csv Dateien sind noch im Git getrackt!"
echo " Entferne sie aus dem Git-Index (Dateien bleiben erhalten)..."
git rm --cached public/data/*.csv 2>/dev/null || true
echo " ✓ public/data/*.csv aus Git-Index entfernt"
fi
else
echo " No public CSVs to restore"
fi
# Sanity Check: users.json muss existieren und darf nicht leer sein
if [ ! -s server/data/users.json ]; then
echo "ERROR: server/data/users.json fehlt oder ist leer nach Restore. Abbruch."
exit 1
fi
# 7. Cleanup (Backups werden bewusst behalten)
echo ""
echo "7. Keeping backups in $BACKUP_ROOT (no git stash used)."
# 8. Restart PM2
echo ""
echo "8. Restarting PM2..."
# Prüfe, ob PM2 installiert ist
if ! command -v pm2 &> /dev/null; then
echo "ERROR: PM2 ist nicht installiert oder nicht im PATH!"
echo "Bitte installieren Sie PM2: npm install -g pm2"
exit 1
fi
# Prüfe, ob der Prozess existiert
if ! pm2 describe harheimertc &> /dev/null; then
echo "WARNING: PM2-Prozess 'harheimertc' existiert nicht."
echo "Versuche, den Prozess zu starten..."
pm2 start harheimertc.config.cjs --update-env || pm2 start harheimertc.simple.cjs --update-env || {
echo "ERROR: Konnte PM2-Prozess nicht starten."
echo "Bitte manuell starten: pm2 start harheimertc.config.cjs"
exit 1
}
echo " ✓ PM2-Prozess gestartet"
else
# Restart mit --update-env, um Umgebungsvariablen zu aktualisieren
echo " Restarting harheimertc with --update-env..."
if pm2 restart harheimertc --update-env; then
echo " ✓ PM2-Prozess neu gestartet"
else
echo "ERROR: PM2-Restart fehlgeschlagen!"
echo "Bitte manuell prüfen: pm2 logs harheimertc"
exit 1
fi
fi
# Prüfe, ob der Prozess läuft
sleep 2
if pm2 describe harheimertc | grep -q "online"; then
echo " ✓ PM2-Prozess läuft (online)"
else
echo "WARNING: PM2-Prozess ist nicht online. Prüfe Logs: pm2 logs harheimertc"
fi
echo ""
echo "=== Deployment completed successfully! ==="
echo "The application is now running with the latest code and your production data preserved."
echo ""
echo "Useful commands:"
echo " pm2 logs harheimertc # View logs"
echo " pm2 status # View status"
echo " pm2 restart harheimertc # Restart manually"