Fix: git-Ops als root, fix_permissions immer im Exit-Trap

- git_safe: chown -R APP_DIR immer (kein bedingter Check)
- git_dirty_check + alle git fetch/checkout: als root → kein
  "permission denied" / "dubious ownership" mehr
- _cleanup: fix_permissions() immer aufrufen (auch bei Fehler-Abbruch)
  → kein 404/500 nach fehlgeschlagenem Update mehr

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
main v1.1.313
boban 2026-04-26 19:30:57 +02:00
parent a119686bfa
commit 190b627fd4
1 changed files with 35 additions and 31 deletions

View File

@ -66,35 +66,30 @@ artisan_up(){
}
git_safe(){
# System-Level safe.directory (root schreibt /etc/gitconfig → gilt für alle User)
# safe.directory system-weit (root → /etc/gitconfig → gilt für alle User)
git config --system --add safe.directory "${APP_DIR}" >/dev/null 2>&1 || true
# Wenn APP_DIR einem anderen User gehört (z.B. nach User-Wechsel mailwolt→www-data),
# kompletten Baum neu besitzen — nur wenn nötig (einmalig teuer, danach billig)
local dir_owner
dir_owner="$(stat -c '%U' "${APP_DIR}" 2>/dev/null || echo '')"
if [[ -n "${dir_owner}" && "${dir_owner}" != "${APP_USER}" ]]; then
echo "[i] Eigentümer-Korrektur: ${APP_DIR}${APP_USER} (war: ${dir_owner})"
# Gesamte App dem APP_USER zuweisen — root kann immer schreiben,
# aber PHP-FPM (www-data) braucht Lese-/Schreibrecht auf bootstrap/cache + storage
chown -R "${APP_USER}":"${APP_GROUP}" "${APP_DIR}" 2>/dev/null || true
else
# Nur .git sicherstellen (schnell)
chown -R "${APP_USER}":"${APP_GROUP}" "${APP_DIR}/.git" 2>/dev/null || true
fi
as_app "git config --global --add safe.directory ${APP_DIR} >/dev/null 2>&1 || true"
}
git_dirty_check(){
# Als root ausführen: kein Permission-Problem unabhängig vom Dateieigentümer
local dirty
dirty="$(as_app "git -C ${APP_DIR} status --porcelain" 2>/dev/null || true)"
dirty="$(git -C "${APP_DIR}" status --porcelain 2>/dev/null || true)"
if [[ -n "$dirty" ]]; then
echo "[!] Uncommitted Änderungen gefunden — tracked Dateien werden zurückgesetzt:"
echo "[!] Uncommitted Änderungen — tracked Dateien werden zurückgesetzt:"
echo "$dirty"
as_app "git -C ${APP_DIR} reset --hard HEAD" 2>/dev/null || true
as_app "git -C ${APP_DIR} clean -fd --exclude='.env' --exclude='storage/' --exclude='node_modules/'" 2>/dev/null || true
git -C "${APP_DIR}" reset --hard HEAD 2>/dev/null || true
git -C "${APP_DIR}" clean -fd \
--exclude='.env' --exclude='storage/' --exclude='node_modules/' 2>/dev/null || true
fi
}
get_version(){
as_app "cd ${APP_DIR} && (git describe --tags --always 2>/dev/null || git rev-parse --short=7 HEAD)"
git -C "${APP_DIR}" describe --tags --always 2>/dev/null \
|| git -C "${APP_DIR}" rev-parse --short=7 HEAD 2>/dev/null \
|| echo "unknown"
}
write_version_files(){
@ -261,6 +256,8 @@ MAINTENANCE_ACTIVE=0
_cleanup() {
local rc=$?
[[ "$MAINTENANCE_ACTIVE" -eq 1 ]] && artisan_up
# Rechte + Cache IMMER korrigieren — auch bei Fehler-Abbruch
fix_permissions
mkdir -p "$STATE_DIR"
echo "done" > "$STATE_DIR/state"
echo "$rc" > "$STATE_DIR/rc"
@ -280,21 +277,24 @@ git_dirty_check
# -------- Git: neuen Stand holen ---------------------------------------------
echo "[i] Prüfe Repository …"
OLD_REV="$(as_app "git -C ${APP_DIR} rev-parse HEAD")"
OLD_REV="$(git -C "${APP_DIR}" rev-parse HEAD)"
OLD_VER="$(get_version)"
NEW_REV="$OLD_REV"
if [[ "$MODE" = "tags" ]]; then
# → 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} describe --tags --abbrev=0 \$(git -C ${APP_DIR} rev-list --tags --max-count=1 2>/dev/null) 2>/dev/null || echo ''")"
# Neuesten Remote-Tag cachen für CheckUpdates (läuft als www-data ohne git-Credentials)
# Tags vom Remote holen (als root — hat Zugriff auf gespeicherte Credentials)
git -C "${APP_DIR}" fetch --quiet origin 2>/dev/null || true
git -C "${APP_DIR}" fetch --tags --quiet origin 2>/dev/null || true
LATEST_TAG="$(git -C "${APP_DIR}" describe --tags --abbrev=0 \
"$(git -C "${APP_DIR}" rev-list --tags --max-count=1 2>/dev/null)" 2>/dev/null || echo '')"
# Neuesten Remote-Tag cachen
[[ -n "$LATEST_TAG" ]] && { mkdir -p /var/lib/mailwolt; printf '%s\n' "$LATEST_TAG" > /var/lib/mailwolt/version_remote; } || true
if [[ -z "$LATEST_TAG" ]]; then
echo "[!] Keine Tags gefunden falle auf origin/${BRANCH} zurück"
as_app "git -C ${APP_DIR} checkout -q ${BRANCH} && git -C ${APP_DIR} pull --ff-only origin ${BRANCH}"
git -C "${APP_DIR}" checkout -q "${BRANCH}"
git -C "${APP_DIR}" pull --ff-only origin "${BRANCH}"
else
TARGET_REV="$(as_app "git -C ${APP_DIR} rev-list -n1 ${LATEST_TAG}")"
TARGET_REV="$(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"
@ -302,13 +302,15 @@ if [[ "$MODE" = "tags" ]]; then
exit 0
fi
echo "[i] Checkout auf Release ${LATEST_TAG} (${TARGET_REV:0:7}) …"
as_app "git -C ${APP_DIR} checkout -q ${LATEST_TAG}"
git -C "${APP_DIR}" checkout -q "${LATEST_TAG}"
fi
NEW_REV="$(as_app "git -C ${APP_DIR} rev-parse HEAD")"
NEW_REV="$(git -C "${APP_DIR}" rev-parse HEAD)"
# Nach Checkout Eigentümer korrigieren
chown -R "${APP_USER}":"${APP_GROUP}" "${APP_DIR}" 2>/dev/null || true
else
# Rolling: branch folgen
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")"
git -C "${APP_DIR}" fetch --quiet origin "${BRANCH}" 2>/dev/null || true
BEHIND="$(git -C "${APP_DIR}" rev-list --count "HEAD..origin/${BRANCH}" 2>/dev/null || echo 0)"
if [[ "$BEHIND" -eq 0 ]]; then
echo "[✓] Branch origin/${BRANCH} ist bereits aktuell nichts zu tun."
write_build_info "$(get_version)" "$OLD_REV"
@ -316,8 +318,10 @@ else
exit 0
fi
echo "[i] Es gibt ${BEHIND} neue Commit(s) ziehe Änderungen …"
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")"
git -C "${APP_DIR}" checkout -q "${BRANCH}"
git -C "${APP_DIR}" pull --ff-only origin "${BRANCH}"
NEW_REV="$(git -C "${APP_DIR}" rev-parse HEAD)"
chown -R "${APP_USER}":"${APP_GROUP}" "${APP_DIR}" 2>/dev/null || true
fi
# -------- Änderungstypen ermitteln -------------------------------------------