fix(sync): Guard gegen Datenverlust — reset --hard nur bei sauberem Baum
sync_state.py bricht den git-Sync ab + alarmiert per Telegram, wenn der Live-Arbeitsbaum uncommittete Aenderungen oder ungepushte Commits hat, statt sie per reset --hard FETCH_HEAD zu vernichten. Watchdog laeuft unabhaengig weiter. Behebt die Ursache von Issue #123.
This commit is contained in:
parent
38b91136c2
commit
4f61172468
1 changed files with 54 additions and 19 deletions
|
|
@ -387,12 +387,45 @@ def git_sync(cfg: config.HomelabConfig):
|
||||||
["git", "-C", str(REPO), "fetch", forgejo_url, "main", "--quiet"],
|
["git", "-C", str(REPO), "fetch", forgejo_url, "main", "--quiet"],
|
||||||
capture_output=True, timeout=30,
|
capture_output=True, timeout=30,
|
||||||
)
|
)
|
||||||
|
# -- Schutz gegen Datenverlust (Ref Issue #123) --------------------
|
||||||
|
# Kein blindes 'reset --hard', wenn der Live-Arbeitsbaum nicht-committete
|
||||||
|
# Aenderungen oder lokale, noch nicht gepushte Commits hat -- sonst wuerde
|
||||||
|
# echte Arbeit vernichtet (das Beinahe-Desaster vom Juni 2026).
|
||||||
|
# Stattdessen: git-Sync ueberspringen + Telegram-Alarm; Mensch loest auf.
|
||||||
|
dirty = subprocess.run(
|
||||||
|
["git", "-C", str(REPO), "status", "--porcelain", "--untracked-files=no"],
|
||||||
|
capture_output=True, text=True, timeout=15,
|
||||||
|
).stdout.strip()
|
||||||
|
ahead = subprocess.run(
|
||||||
|
["git", "-C", str(REPO), "rev-list", "--count", "FETCH_HEAD..HEAD"],
|
||||||
|
capture_output=True, text=True, timeout=15,
|
||||||
|
).stdout.strip()
|
||||||
|
|
||||||
|
if dirty or (ahead.isdigit() and int(ahead) > 0):
|
||||||
|
n_dirty = len(dirty.splitlines()) if dirty else 0
|
||||||
|
n_ahead = ahead if ahead.isdigit() else "?"
|
||||||
|
log("GUARD: git-Sync abgebrochen -- Arbeitsbaum nicht sauber "
|
||||||
|
"(%s geaenderte Datei(en), %s ungepushte Commit(s)). "
|
||||||
|
"reset --hard uebersprungen (Schutz vor Datenverlust, Ref #123)."
|
||||||
|
% (n_dirty, n_ahead))
|
||||||
|
tg_alert(
|
||||||
|
cfg, "sync_guard",
|
||||||
|
"*Homelab git-Sync ABGEBROCHEN*%0A%0A"
|
||||||
|
"Live-Repo (CT116) ist nicht sauber:%0A"
|
||||||
|
"- " + str(n_dirty) + " uncommittete Datei(en)%0A"
|
||||||
|
"- " + str(n_ahead) + " ungepushte Commit(s)%0A%0A"
|
||||||
|
"reset --hard FETCH_HEAD wurde UEBERSPRUNGEN, um Arbeit nicht zu "
|
||||||
|
"vernichten (Ref Issue #123).%0ABitte manuell aufloesen: committen + "
|
||||||
|
"pushen oder gezielt verwerfen. Watchdog laeuft normal weiter."
|
||||||
|
)
|
||||||
|
return forgejo_url, False
|
||||||
|
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
["git", "-C", str(REPO), "reset", "--hard", "FETCH_HEAD"],
|
["git", "-C", str(REPO), "reset", "--hard", "FETCH_HEAD"],
|
||||||
capture_output=True, timeout=15,
|
capture_output=True, timeout=15,
|
||||||
)
|
)
|
||||||
|
|
||||||
return forgejo_url
|
return forgejo_url, True
|
||||||
|
|
||||||
|
|
||||||
def git_commit_and_push(cfg: config.HomelabConfig, forgejo_url: str):
|
def git_commit_and_push(cfg: config.HomelabConfig, forgejo_url: str):
|
||||||
|
|
@ -436,16 +469,16 @@ def main():
|
||||||
log("Sync startet...")
|
log("Sync startet...")
|
||||||
|
|
||||||
cfg = config.parse_config(REPO / "homelab.conf")
|
cfg = config.parse_config(REPO / "homelab.conf")
|
||||||
forgejo_url = git_sync(cfg)
|
forgejo_url, repo_clean = git_sync(cfg)
|
||||||
|
|
||||||
cfg = config.parse_config(REPO / "homelab.conf")
|
cfg = config.parse_config(REPO / "homelab.conf")
|
||||||
|
|
||||||
# Watchdog
|
# Watchdog (laeuft immer, unabhaengig vom git-Zustand)
|
||||||
log("Watchdog läuft...")
|
log("Watchdog laeuft...")
|
||||||
check_service(cfg, 109, "rss-manager", "RSS Manager")
|
check_service(cfg, 109, "rss-manager", "RSS Manager")
|
||||||
check_docker(cfg, 101, "wordpress-app", "WordPress Docker")
|
check_docker(cfg, 101, "wordpress-app", "WordPress Docker")
|
||||||
|
|
||||||
# STATE.md Dateien generieren
|
if repo_clean:
|
||||||
states = {
|
states = {
|
||||||
"arakava-news/STATE.md": generate_arakava_state(cfg),
|
"arakava-news/STATE.md": generate_arakava_state(cfg),
|
||||||
"infrastructure/STATE.md": generate_infra_state(cfg),
|
"infrastructure/STATE.md": generate_infra_state(cfg),
|
||||||
|
|
@ -457,12 +490,14 @@ def main():
|
||||||
full_path.parent.mkdir(parents=True, exist_ok=True)
|
full_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
full_path.write_text(content)
|
full_path.write_text(content)
|
||||||
CHANGED = True
|
CHANGED = True
|
||||||
log(f"{path} aktualisiert")
|
log("%s aktualisiert" % path)
|
||||||
|
|
||||||
if CHANGED:
|
if CHANGED:
|
||||||
git_commit_and_push(cfg, forgejo_url)
|
git_commit_and_push(cfg, forgejo_url)
|
||||||
else:
|
else:
|
||||||
log("Keine Änderungen")
|
log("Keine Aenderungen")
|
||||||
|
else:
|
||||||
|
log("git-Sync uebersprungen (Guard aktiv) -- STATE-Regen + Push ausgelassen")
|
||||||
|
|
||||||
log("Sync abgeschlossen")
|
log("Sync abgeschlossen")
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue