From 16dc32d29cd62d288fd3efa21c119f357a4c6f70 Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Wed, 26 Aug 2026 11:27:55 +0200 Subject: [PATCH] =?UTF-8?q?F=C3=BCge=20Skript=20f=C3=BCr=20automatisches?= =?UTF-8?q?=20Produktions-Deployment=20hinzu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy-production.sh | 77 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100755 deploy-production.sh diff --git a/deploy-production.sh b/deploy-production.sh new file mode 100755 index 0000000..aa3472d --- /dev/null +++ b/deploy-production.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# Automatisches Produktions-Deployment für TimeClock. +# Dieses Script wird nach einem Push auf main im Checkout auf dem Server ausgeführt. + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$SCRIPT_DIR" + +REMOTE_NAME="${DEPLOY_REMOTE:-origin}" +BRANCH_NAME="${DEPLOY_BRANCH:-main}" +PM2_APP="${PM2_APP:-timeclock-backend}" +CACHE_DIR=".deploy-cache" + +fail() { + echo "ERROR: $*" >&2 + exit 1 +} + +install_dependencies_if_needed() { + local directory="$1" + local cache_key="$2" + local lockfile="$directory/package-lock.json" + local hash_file="$CACHE_DIR/${cache_key}-package-lock.sha256" + local current_hash="" + local previous_hash="" + + if [ ! -f "$lockfile" ]; then + echo "[$directory] package-lock.json fehlt, führe npm install aus" + (cd "$directory" && npm install --no-audit --no-fund) + return + fi + + current_hash="$(sha256sum "$lockfile" | awk '{print $1}')" + previous_hash="$(cat "$hash_file" 2>/dev/null || true)" + + if [ ! -d "$directory/node_modules" ] || [ "$current_hash" != "$previous_hash" ]; then + echo "[$directory] installiere Abhängigkeiten" + (cd "$directory" && npm ci --no-audit --no-fund) + else + echo "[$directory] Abhängigkeiten unverändert" + fi + + printf '%s\n' "$current_hash" > "$hash_file" +} + +echo "=== TimeClock Produktions-Deployment ===" +echo "Arbeitsverzeichnis: $SCRIPT_DIR" + +git rev-parse --is-inside-work-tree >/dev/null 2>&1 \ + || fail "Das Script muss im TimeClock-Git-Checkout ausgeführt werden." + +if [ -n "$(git status --porcelain --untracked-files=no)" ]; then + fail "Der Deployment-Checkout enthält lokale Änderungen. Deployment abgebrochen." +fi + +mkdir -p "$CACHE_DIR" + +echo "Aktualisiere $REMOTE_NAME/$BRANCH_NAME …" +git fetch "$REMOTE_NAME" "$BRANCH_NAME" +git merge --ff-only "$REMOTE_NAME/$BRANCH_NAME" + +install_dependencies_if_needed "backend" "backend" +install_dependencies_if_needed "frontend" "frontend" + +echo "Baue Frontend …" +(cd frontend && npm run build) + +echo "Lade PM2-Prozess neu …" +if pm2 describe "$PM2_APP" >/dev/null 2>&1; then + pm2 reload ecosystem.config.js --only "$PM2_APP" --env production --update-env +else + pm2 start ecosystem.config.js --only "$PM2_APP" --env production +fi +pm2 save + +echo "Deployment erfolgreich abgeschlossen."