Files
Server-MsHossa/SCRIPTS/deploy.sh
T
2026-10-22 21:59:45 +02:00

337 lines
8.8 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# ./deploy.sh public
# ./deploy.sh backend
# ./deploy.sh server
# ./deploy.sh all
# ./deploy.sh fetch
# ./deploy.sh list-backups public
# ./deploy.sh rollback public
# ./deploy.sh rollback public PUBLIC-20260216-143015-server01
# ./deploy.sh rollback server
# ./deploy.sh rollback server SERVER-20260216-143015-server01.commit
set -Eeuo pipefail
########################################
# Farben
########################################
RED="\e[31m"
GREEN="\e[32m"
YELLOW="\e[33m"
BLUE="\e[34m"
BOLD="\e[1m"
RESET="\e[0m"
########################################
# Logging
########################################
log_info() { echo -e "${BLUE}[INFO]${RESET} $1"; }
log_success() { echo -e "${GREEN}[OK]${RESET} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${RESET} $1"; }
log_error() { echo -e "${RED}[ERROR]${RESET} $1"; }
trap 'log_error "Fehler in Zeile $LINENO"' ERR
########################################
# Konfiguration
########################################
BASE_DIR="/data/DEPLOYS"
BACKUP_DIR="$BASE_DIR/MSHOSSA"
SERVER_REPO="https://gitea.mrhossa.de/bruno/Server-Mshossa.git"
# Zielverzeichnisse
SERVER_TARGET="/data" # liegt direkt in /data, NICHT in BASE_DIR!
SERVER_BRANCH="main" # ggf. anpassen (z. B. "live")
SERVER_CONTAINER="dnsmasq"
TIMESTAMP=$(date +"%Y%m%d-%H%M%S")
HOSTNAME=$(hostname)
########################################
# Root-Check
########################################
if [[ "$EUID" -ne 0 ]]; then
log_error "Script muss als root laufen!"
exit 1
fi
########################################
# Lockfile
########################################
exec 9>/var/lock/webdeploy.lock
flock -n 9 || { log_error "Deploy läuft bereits!"; exit 1; }
########################################
# Helper
########################################
ensure_directory() {
[[ -d "$1" ]] || mkdir -p "$1"
}
restart_container() {
local container="$1"
if [[ -z "$container" ]]; then
log_info "Kein Container konfiguriert – überspringe Neustart."
return
fi
if docker ps -a --format '{{.Names}}' | grep -q "^${container}$"; then
docker restart "$container" >/dev/null
log_success "Container $container neu gestartet."
else
log_warn "Container $container existiert nicht."
fi
}
# Zeigt pro Datei die Anzahl geänderter Zeilen (git diff --stat) und die Commits dazwischen
show_changes() {
local target="$1"
local from="$2"
local to="$3"
local stat
stat=$(git -C "$target" diff --stat=100 "$from" "$to")
if [[ -z "$stat" ]]; then
log_info "Keine Änderungen."
return
fi
log_info "Geänderte Dateien:"
echo "$stat"
local commits
commits=$(git -C "$target" log --oneline "$from..$to")
if [[ -n "$commits" ]]; then
log_info "Neue Commits:"
echo "$commits"
fi
}
# Warnt, wenn getrackte Dateien lokal geändert wurden (gehen bei reset --hard verloren)
warn_local_changes() {
local target="$1"
# nur getrackte Dateien: untracked (SEAFILE/, MARIADB/, .pem) bleiben bei reset --hard unberührt
if [[ -n "$(git -C "$target" status --porcelain --untracked-files=no)" ]]; then
log_warn "Lokale Änderungen an getrackten Dateien gehen beim Deploy verloren:"
git -C "$target" diff --stat HEAD
fi
}
deploy() {
local name="$1"
local repo="$2"
local container="$3"
local target="$4"
log_info "Deploying $name ..."
backup_current "$name" "$target"
ensure_directory "$(dirname "$target")"
git clone "$repo" "$target"
if [[ "$name" == "BACKEND" ]]; then
git -C "$target" checkout live
fi
restart_container "$container"
log_success "$name erfolgreich deployed."
}
list_backups() {
local name="$1"
log_info "Verfügbare Backups für $name:"
ls -ldt "$BACKUP_DIR/${name}-"* 2>/dev/null || log_warn "Keine Backups gefunden."
}
rollback() {
local name="$1"
local container="$2"
local target="$3"
local specific_backup="${4:-}"
ensure_directory "$BACKUP_DIR"
local current="$target"
local backup_to_restore
if [[ -n "$specific_backup" ]]; then
backup_to_restore="$BACKUP_DIR/$specific_backup"
else
backup_to_restore=$(ls -dt "$BACKUP_DIR/${name}-"* 2>/dev/null | head -n1)
fi
if [[ -z "${backup_to_restore:-}" || ! -d "$backup_to_restore" ]]; then
log_error "Kein gültiges Backup gefunden!"
exit 1
fi
log_warn "Rollback von $name → $(basename "$backup_to_restore")"
if [[ -n "$container" ]] && docker ps --format '{{.Names}}' | grep -q "^${container}$"; then
log_info "Stoppe Container $container ..."
docker stop "$container" >/dev/null
fi
if [[ -d "$current" ]]; then
log_info "Entferne aktuelles Verzeichnis ..."
rm -rf "$current"
fi
mv "$backup_to_restore" "$current"
if [[ -n "$container" ]]; then
docker start "$container" >/dev/null
fi
log_success "Rollback abgeschlossen."
}
########################################
# SERVER (Git-basiertes Deploy, liegt direkt in /data)
########################################
deploy_server() {
local target="$SERVER_TARGET"
if [[ -d "$target/.git" ]]; then
# Aktuellen Commit als "Backup" protokollieren
local current_commit
current_commit=$(git -C "$target" rev-parse HEAD)
ensure_directory "$BACKUP_DIR"
echo "$current_commit" > "$BACKUP_DIR/SERVER-${TIMESTAMP}-${HOSTNAME}.commit"
log_info "Aktueller Server-Commit gesichert: $current_commit"
log_info "Aktualisiere Server-Repo ..."
git -C "$target" fetch origin
show_changes "$target" HEAD "origin/$SERVER_BRANCH"
warn_local_changes "$target"
git -C "$target" reset --hard "origin/$SERVER_BRANCH"
else
# Erstinstallation: /data ist nicht leer (WEBSERVER liegt dort), daher über Temp-Ordner
log_info "Server-Repo noch nicht vorhanden, initialisiere ..."
local tmp_clone
tmp_clone=$(mktemp -d)
git clone "$SERVER_REPO" "$tmp_clone"
shopt -s dotglob
for item in "$tmp_clone"/*; do
mv "$item" "$target/"
done
shopt -u dotglob
rmdir "$tmp_clone"
fi
restart_container "$SERVER_CONTAINER"
log_success "SERVER erfolgreich deployed."
}
rollback_server() {
local specific_backup="${1:-}"
local target="$SERVER_TARGET"
local commit_file
ensure_directory "$BACKUP_DIR"
if [[ -n "$specific_backup" ]]; then
commit_file="$BACKUP_DIR/$specific_backup"
else
commit_file=$(ls -t "$BACKUP_DIR/SERVER-"*.commit 2>/dev/null | head -n1)
fi
if [[ -z "${commit_file:-}" || ! -f "$commit_file" ]]; then
log_error "Kein gültiges Server-Backup (Commit) gefunden!"
exit 1
fi
local commit_hash
commit_hash=$(cat "$commit_file")
log_warn "Rollback von SERVER → Commit $commit_hash"
git -C "$target" fetch origin
show_changes "$target" HEAD "$commit_hash"
warn_local_changes "$target"
git -C "$target" reset --hard "$commit_hash"
restart_container "$SERVER_CONTAINER"
log_success "Server-Rollback abgeschlossen."
}
list_backups_server() {
log_info "Verfügbare Server-Backups (Commits):"
ls -lt "$BACKUP_DIR/SERVER-"*.commit 2>/dev/null || log_warn "Keine Backups gefunden."
}
########################################
# Fetch (Vorschau, ohne Deploy)
########################################
fetch_changes() {
local name="$1"
local target="$2"
if [[ -d "$target/.git" ]]; then
git -C "$target" fetch origin
show_changes "$target" HEAD "origin/$SERVER_BRANCH"
warn_local_changes "$target"
else
log_warn "$name ist nicht installiert."
fi
}
########################################
# CLI
########################################
ACTION="${1:-}"
TARGET_ARG="${2:-}"
OPTIONAL="${3:-}"
case "$ACTION" in
all)
deploy_server
;;
server)
deploy_server
;;
rollback)
case "$TARGET_ARG" in
server)
rollback_server "$OPTIONAL"
;;
*)
echo "Usage: $0 rollback {public|backend|server} [backup-name]"
exit 1
;;
esac
;;
list-backups)
case "$TARGET_ARG" in
server)
list_backups_server
;;
*)
echo "Usage: $0 list-backups {public|backend|server}"
exit 1
;;
esac
;;
fetch)
fetch_changes "SERVER" "$SERVER_TARGET"
;;
*)
echo "Usage:"
echo " $0 {all|server}"
echo " $0 rollback {server} [backup-name]"
echo " $0 list-backups {server}"
echo " $0 fetch"
exit 1
;;
esac