diff --git a/scripts/update.sh b/scripts/update.sh index 7c78698..d46eab3 100644 --- a/scripts/update.sh +++ b/scripts/update.sh @@ -2,10 +2,11 @@ set -euo pipefail # -------- Konfiguration -------- -APP_USER="mailwolt" -APP_DIR="/var/www/mailwolt" +APP_USER="${APP_USER:-mailwolt}" +APP_DIR="${APP_DIR:-/var/www/mailwolt}" BRANCH="${BRANCH:-main}" # nur relevant bei UPDATE_MODE=branch MODE="${UPDATE_MODE:-tags}" # tags | branch +ALLOW_DIRTY="${ALLOW_DIRTY:-0}" # 1 = Dirty-Working-Tree zulassen # -------- Helper -------- as_app(){ sudo -u "$APP_USER" -H bash -lc "$*"; } @@ -20,55 +21,88 @@ restart_php_fpm(){ done } +git_safe(){ + # Falls nötig: Repo als safe markieren (manche Root-Umgebungen meckern sonst) + as_app "git -C ${APP_DIR} config --global --add safe.directory ${APP_DIR} >/dev/null 2>&1 || true" +} + +git_dirty_check(){ + if [[ "$ALLOW_DIRTY" != "1" ]]; then + local dirty + dirty="$(as_app "git -C ${APP_DIR} status --porcelain")" + if [[ -n "$dirty" ]]; then + echo "[!] Arbeitsbaum hat uncommitted Änderungen. Abbruch (ALLOW_DIRTY=1 zum Überschreiben)." + exit 2 + fi + fi +} + +get_version(){ + as_app "cd ${APP_DIR} && (git describe --tags --always 2>/dev/null || git rev-parse --short=7 HEAD)" +} + +write_build_info(){ + local ver="$1" rev="$2" + printf "version=%s\nrev=%s\nupdated=%s\n" "$ver" "$rev" "$(date -Is)" > /etc/mailwolt/build.info || true +} + # -------- Guards -------- [[ "$(id -u)" -eq 0 ]] || { echo "[!] Bitte als root ausführen"; exit 1; } [[ -d "$APP_DIR/.git" ]] || { echo "[!] $APP_DIR scheint kein Git-Repo zu sein"; exit 1; } +git_safe +git_dirty_check + echo "[i] Prüfe Repository …" -OLD_REV="$(as_app "cd ${APP_DIR} && git rev-parse HEAD")" +OLD_REV="$(as_app "git -C ${APP_DIR} rev-parse HEAD")" +OLD_VER="$(get_version)" NEW_REV="$OLD_REV" if [[ "$MODE" = "tags" ]]; then - # Auf neuesten Release-Tag wechseln (semantisch sortiert) - LATEST_TAG="$(as_app "cd ${APP_DIR} && git fetch --tags --quiet origin && git tag --list | sort -V | tail -n1")" + # → Neueste Tags holen + as_app "git -C ${APP_DIR} fetch --quiet origin && git -C ${APP_DIR} fetch --tags --quiet origin || true" + + LATEST_TAG="$(as_app "git -C ${APP_DIR} tag --list | sort -V | tail -n1")" if [[ -z "$LATEST_TAG" ]]; then echo "[!] Keine Tags gefunden – falle auf origin/${BRANCH} zurück" - as_app "cd ${APP_DIR} && git fetch --quiet origin ${BRANCH} && git checkout -q ${BRANCH} && git pull --ff-only origin ${BRANCH}" + as_app "git -C ${APP_DIR} checkout -q ${BRANCH} && git -C ${APP_DIR} pull --ff-only origin ${BRANCH}" else - TARGET_REV="$(as_app "cd ${APP_DIR} && git rev-list -n1 ${LATEST_TAG}")" + TARGET_REV="$(as_app "git -C ${APP_DIR} rev-list -n1 ${LATEST_TAG}")" if [[ "$TARGET_REV" = "$OLD_REV" ]]; then echo "[✓] Bereits auf neuestem Release (${LATEST_TAG}) – nichts zu tun." + write_build_info "$(get_version)" "$OLD_REV" exit 0 fi echo "[i] Checkout auf Release ${LATEST_TAG} (${TARGET_REV:0:7}) …" - as_app "cd ${APP_DIR} && git checkout -q ${LATEST_TAG}" + as_app "git -C ${APP_DIR} checkout -q ${LATEST_TAG}" fi - NEW_REV="$(as_app "cd ${APP_DIR} && git rev-parse HEAD")" + NEW_REV="$(as_app "git -C ${APP_DIR} rev-parse HEAD")" else # Rolling: branch folgen - as_app "cd ${APP_DIR} && git fetch --quiet origin ${BRANCH}" - BEHIND="$(as_app "cd ${APP_DIR} && git rev-list --count HEAD..origin/${BRANCH} || echo 0")" + as_app "git -C ${APP_DIR} fetch --quiet origin ${BRANCH}" + BEHIND="$(as_app "git -C ${APP_DIR} rev-list --count HEAD..origin/${BRANCH} || echo 0")" if [[ "$BEHIND" -eq 0 ]]; then echo "[✓] Branch origin/${BRANCH} ist bereits aktuell – nichts zu tun." + write_build_info "$(get_version)" "$OLD_REV" exit 0 fi echo "[i] Es gibt ${BEHIND} neue Commit(s) – ziehe Änderungen …" - as_app "cd ${APP_DIR} && git checkout -q ${BRANCH} && git pull --ff-only origin ${BRANCH}" - NEW_REV="$(as_app "cd ${APP_DIR} && git rev-parse HEAD")" + as_app "git -C ${APP_DIR} checkout -q ${BRANCH} && git -C ${APP_DIR} pull --ff-only origin ${BRANCH}" + NEW_REV="$(as_app "git -C ${APP_DIR} rev-parse HEAD")" fi # -------- Änderungstypen ermitteln -------- -CHANGED_FILES="$(as_app "cd ${APP_DIR} && git diff --name-only ${OLD_REV}..${NEW_REV}")" +CHANGED_FILES="$(as_app "git -C ${APP_DIR} diff --name-only ${OLD_REV}..${NEW_REV}")" NEED_COMPOSER=0 NEED_MIGRATIONS=0 NEED_FRONTEND=0 NEED_PHP_RESTART=0 -echo "$CHANGED_FILES" | grep -qE '(^|/)composer\.(json|lock)$' && NEED_COMPOSER=1 -echo "$CHANGED_FILES" | grep -qE '^database/migrations/' && NEED_MIGRATIONS=1 -echo "$CHANGED_FILES" | grep -qE '^(package(-lock)?\.json|vite\.config|resources/|public/.*\.(js|css))' && NEED_FRONTEND=1 -echo "$CHANGED_FILES" | grep -qE '^(app/|routes/|config/|resources/views/)' && NEED_PHP_RESTART=1 +echo "$CHANGED_FILES" | grep -qE '(^|/)composer\.(json|lock)$' && NEED_COMPOSER=1 +echo "$CHANGED_FILES" | grep -qE '^database/migrations/' && NEED_MIGRATIONS=1 +echo "$CHANGED_FILES" | grep -qE '^(package(-lock)?\.json|vite\.config(\.ts|\.js)?|resources/|public/.*\.(js|css))' && NEED_FRONTEND=1 +echo "$CHANGED_FILES" | grep -qE '^(app/|routes/|config/|resources/views/)' && NEED_PHP_RESTART=1 echo "[i] Zusammenfassung:" echo " Composer : $([[ $NEED_COMPOSER -eq 1 ]] && echo JA || echo nein)" @@ -79,9 +113,9 @@ echo " PHP restart : $([[ $NEED_PHP_RESTART -eq 1 ]] && echo JA || echo nein # Wenn gar nichts relevantes geändert wurde → sauber beenden if [[ $NEED_COMPOSER -eq 0 && $NEED_MIGRATIONS -eq 0 && $NEED_FRONTEND -eq 0 && $NEED_PHP_RESTART -eq 0 ]]; then echo "[✓] Code-Stand aktualisiert, aber keine Build/Runtime-Änderungen – keine Neustarts nötig." - # Build-Info trotzdem aktualisieren - INST_VER="$(as_app "cd ${APP_DIR} && (cat VERSION 2>/dev/null || echo dev)")" - printf "version=%s\nrev=%s\nupdated=%s\n" "$INST_VER" "$NEW_REV" "$(date -Is)" > /etc/mailwolt/build.info || true + NEW_VER="$(get_version)" + write_build_info "$NEW_VER" "$NEW_REV" + echo "[i] Version: ${OLD_VER} → ${NEW_VER}" exit 0 fi @@ -122,10 +156,139 @@ if [[ $NEED_FRONTEND -eq 1 || $NEED_PHP_RESTART -eq 1 ]]; then fi # -------- Build-Info ablegen -------- -INST_VER="$(as_app "cd ${APP_DIR} && (cat VERSION 2>/dev/null || echo dev)")" -printf "version=%s\nrev=%s\nupdated=%s\n" "$INST_VER" "$NEW_REV" "$(date -Is)" > /etc/mailwolt/build.info || true +NEW_VER="$(get_version)" +write_build_info "$NEW_VER" "$NEW_REV" -echo "[✓] Update abgeschlossen: ${OLD_REV:0:7} → ${NEW_REV:0:7} (Version: ${INST_VER})" +echo "[✓] Update abgeschlossen: ${OLD_REV:0:7} → ${NEW_REV:0:7} (Version: ${NEW_VER})" + +##!/usr/bin/env bash +#set -euo pipefail +# +## -------- Konfiguration -------- +#APP_USER="mailwolt" +#APP_DIR="/var/www/mailwolt" +#BRANCH="${BRANCH:-main}" # nur relevant bei UPDATE_MODE=branch +#MODE="${UPDATE_MODE:-tags}" # tags | branch +# +## -------- Helper -------- +#as_app(){ sudo -u "$APP_USER" -H bash -lc "$*"; } +#restart_if_exists(){ local u="$1"; systemctl list-unit-files | grep -q "^${u}\.service" && systemctl restart "$u" || true; } +#reload_if_active(){ local u="$1"; systemctl is-active --quiet "$u" && systemctl reload "$u" || true; } +#restart_php_fpm(){ +# for u in php8.3-fpm php8.2-fpm php8.1-fpm php-fpm; do +# if systemctl list-unit-files | grep -q "^${u}\.service"; then +# systemctl restart "$u" +# return 0 +# fi +# done +#} +# +## -------- Guards -------- +#[[ "$(id -u)" -eq 0 ]] || { echo "[!] Bitte als root ausführen"; exit 1; } +#[[ -d "$APP_DIR/.git" ]] || { echo "[!] $APP_DIR scheint kein Git-Repo zu sein"; exit 1; } +# +#echo "[i] Prüfe Repository …" +#OLD_REV="$(as_app "cd ${APP_DIR} && git rev-parse HEAD")" +#NEW_REV="$OLD_REV" +# +#if [[ "$MODE" = "tags" ]]; then +# # Auf neuesten Release-Tag wechseln (semantisch sortiert) +# LATEST_TAG="$(as_app "cd ${APP_DIR} && git fetch --tags --quiet origin && git tag --list | sort -V | tail -n1")" +# if [[ -z "$LATEST_TAG" ]]; then +# echo "[!] Keine Tags gefunden – falle auf origin/${BRANCH} zurück" +# as_app "cd ${APP_DIR} && git fetch --quiet origin ${BRANCH} && git checkout -q ${BRANCH} && git pull --ff-only origin ${BRANCH}" +# else +# TARGET_REV="$(as_app "cd ${APP_DIR} && git rev-list -n1 ${LATEST_TAG}")" +# if [[ "$TARGET_REV" = "$OLD_REV" ]]; then +# echo "[✓] Bereits auf neuestem Release (${LATEST_TAG}) – nichts zu tun." +# exit 0 +# fi +# echo "[i] Checkout auf Release ${LATEST_TAG} (${TARGET_REV:0:7}) …" +# as_app "cd ${APP_DIR} && git checkout -q ${LATEST_TAG}" +# fi +# NEW_REV="$(as_app "cd ${APP_DIR} && git rev-parse HEAD")" +#else +# # Rolling: branch folgen +# as_app "cd ${APP_DIR} && git fetch --quiet origin ${BRANCH}" +# BEHIND="$(as_app "cd ${APP_DIR} && git rev-list --count HEAD..origin/${BRANCH} || echo 0")" +# if [[ "$BEHIND" -eq 0 ]]; then +# echo "[✓] Branch origin/${BRANCH} ist bereits aktuell – nichts zu tun." +# exit 0 +# fi +# echo "[i] Es gibt ${BEHIND} neue Commit(s) – ziehe Änderungen …" +# as_app "cd ${APP_DIR} && git checkout -q ${BRANCH} && git pull --ff-only origin ${BRANCH}" +# NEW_REV="$(as_app "cd ${APP_DIR} && git rev-parse HEAD")" +#fi +# +## -------- Änderungstypen ermitteln -------- +#CHANGED_FILES="$(as_app "cd ${APP_DIR} && git diff --name-only ${OLD_REV}..${NEW_REV}")" +# +#NEED_COMPOSER=0 +#NEED_MIGRATIONS=0 +#NEED_FRONTEND=0 +#NEED_PHP_RESTART=0 +# +#echo "$CHANGED_FILES" | grep -qE '(^|/)composer\.(json|lock)$' && NEED_COMPOSER=1 +#echo "$CHANGED_FILES" | grep -qE '^database/migrations/' && NEED_MIGRATIONS=1 +#echo "$CHANGED_FILES" | grep -qE '^(package(-lock)?\.json|vite\.config|resources/|public/.*\.(js|css))' && NEED_FRONTEND=1 +#echo "$CHANGED_FILES" | grep -qE '^(app/|routes/|config/|resources/views/)' && NEED_PHP_RESTART=1 +# +#echo "[i] Zusammenfassung:" +#echo " Composer : $([[ $NEED_COMPOSER -eq 1 ]] && echo JA || echo nein)" +#echo " Migrations : $([[ $NEED_MIGRATIONS -eq 1 ]] && echo JA || echo nein)" +#echo " Frontend : $([[ $NEED_FRONTEND -eq 1 ]] && echo JA || echo nein)" +#echo " PHP restart : $([[ $NEED_PHP_RESTART -eq 1 ]] && echo JA || echo nein)" +# +## Wenn gar nichts relevantes geändert wurde → sauber beenden +#if [[ $NEED_COMPOSER -eq 0 && $NEED_MIGRATIONS -eq 0 && $NEED_FRONTEND -eq 0 && $NEED_PHP_RESTART -eq 0 ]]; then +# echo "[✓] Code-Stand aktualisiert, aber keine Build/Runtime-Änderungen – keine Neustarts nötig." +# # Build-Info trotzdem aktualisieren +# INST_VER="$(as_app "cd ${APP_DIR} && (cat VERSION 2>/dev/null || echo dev)")" +# printf "version=%s\nrev=%s\nupdated=%s\n" "$INST_VER" "$NEW_REV" "$(date -Is)" > /etc/mailwolt/build.info || true +# exit 0 +#fi +# +## -------- Gezielter Build/Deploy -------- +#if [[ $NEED_COMPOSER -eq 1 ]]; then +# echo "[i] Composer …" +# as_app "cd ${APP_DIR} && composer install --no-interaction --prefer-dist --optimize-autoloader" +#fi +# +#if [[ $NEED_MIGRATIONS -eq 1 ]]; then +# echo "[i] DB-Migrationen …" +# as_app "cd ${APP_DIR} && php artisan migrate --force" +#fi +# +#if [[ $NEED_PHP_RESTART -eq 1 || $NEED_COMPOSER -eq 1 || $NEED_MIGRATIONS -eq 1 ]]; then +# echo "[i] Cache/Optimierungen …" +# as_app "cd ${APP_DIR} && php artisan config:cache && php artisan route:cache || true" +# as_app "cd ${APP_DIR} && php artisan queue:restart || true" +# as_app "cd ${APP_DIR} && php artisan optimize:clear || true" +#fi +# +#if [[ $NEED_FRONTEND -eq 1 ]]; then +# echo "[i] Frontend build …" +# as_app "cd ${APP_DIR} && (npm ci --no-audit --no-fund || npm install)" +# as_app "cd ${APP_DIR} && npm run build" +#fi +# +## -------- Dienste nur wenn nötig -------- +#echo "[i] Dienste neu laden/neustarten (gezielt) …" +#if [[ $NEED_PHP_RESTART -eq 1 || $NEED_COMPOSER -eq 1 || $NEED_MIGRATIONS -eq 1 ]]; then +# restart_php_fpm +# restart_if_exists "${APP_USER}-queue" +# restart_if_exists "${APP_USER}-schedule" +# restart_if_exists "${APP_USER}-ws" +#fi +#if [[ $NEED_FRONTEND -eq 1 || $NEED_PHP_RESTART -eq 1 ]]; then +# reload_if_active nginx +#fi +# +## -------- Build-Info ablegen -------- +#INST_VER="$(as_app "cd ${APP_DIR} && (cat VERSION 2>/dev/null || echo dev)")" +#printf "version=%s\nrev=%s\nupdated=%s\n" "$INST_VER" "$NEW_REV" "$(date -Is)" > /etc/mailwolt/build.info || true +# +#echo "[✓] Update abgeschlossen: ${OLD_REV:0:7} → ${NEW_REV:0:7} (Version: ${INST_VER})" ##!/usr/bin/env bash #set -euo pipefail