Update ohne Neustart, wenn nur Oberflaechendateien wechseln

Bisher verlangte jedes Update einen Home-Assistant-Neustart. Noetig ist er
aber nur fuer Python-Code: HA importiert die Module einmal beim Start und
haengt danach mit lebenden Objekten daran. frontend/ dagegen wird direkt von
der Platte ausgeliefert (StaticPathConfig, cache_headers=False) - eine
ersetzte .js ist sofort wirksam, es braucht nur ein Neuladen im Browser.

aktualisierung.neustart_noetig() vergleicht die alte gegen die neue Fassung
ueber sha256 je Datei und meldet "kein Neustart" nur, wenn JEDE Abweichung
unter frontend/ liegt oder die manifest.json ist. Alles andere - .py,
services.yaml, translations/, vorlage/ - gilt als neustartpflichtig, auch wo
es das im Einzelfall nicht waere. Die Schieflage ist Absicht: ein
faelschlich ausgelassener Neustart laesst neuen Python-Code nie anlaufen, und
der Fehler wird woanders gesucht.

manifest.json ist ausgenommen, weil sich seine Versionsnummer bei jeder
Veroeffentlichung aendert - sonst waere die Unterscheidung wertlos. Weil HA
das Manifest fuer die Laufzeit festhaelt (loader.py: hass.data[
DATA_INTEGRATIONS]), liest version_von_platte() die Nummer direkt von der
Platte; koordinator.version_neu_lesen() zieht sie nach einem Update ohne
Neustart nach, damit Panel und App die neue Fassung auch anzeigen.

Panel und App zeigen im Neustart-freien Fall "Seite neu laden" statt
"Installation abschliessen - Jetzt neu starten".

Neun neue Testfaelle fuer die Unterscheidung, 23 Tests in der
Aktualisierungs-Suite gruen.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-09-05 13:30:25 +02:00
co-authored by Claude Opus 5
parent 4dad3d21a8
commit 81808dbc10
10 changed files with 265 additions and 14 deletions
+24 -5
View File
@@ -344,23 +344,41 @@ def registrieren(hass: HomeAssistant, k: Koordinator) -> None:
await k.app_version_veroeffentlichen()
async def update_installieren(_aufruf: ServiceCall) -> None:
"""Lädt die neueste Fassung von Gitea und ersetzt den
Integrationsordner. Home Assistant muss danach von Hand neu
gestartet werden - kein automatischer Reload aus dem eigenen,
noch laufenden Aufruf heraus, siehe aktualisierung.py."""
"""Laedt die neueste Fassung von Gitea und ersetzt den
Integrationsordner.
Ob danach ein Neustart noetig ist, entscheidet der Updater am
Datei-Vergleich (aktualisierung.neustart_noetig): betrifft das Update
nur frontend/, reicht ein Neuladen der Seite - die Oberflaechen-Dateien
werden direkt von der Platte ausgeliefert (StaticPathConfig mit
cache_headers=False). Nur geaenderter Python-Code braucht wirklich
einen Neustart, weil Home Assistant seine Module einmal beim Start
importiert und danach mit lebenden Objekten daran haengt.
Kein automatischer Reload aus dem eigenen, noch laufenden Aufruf
heraus - siehe aktualisierung.py."""
token = k.entry.options.get(CONF_GITEA_TOKEN, "")
jetzt = datetime.datetime.now(datetime.timezone.utc).isoformat()
try:
ergebnis = await aktualisierung.update_installieren(hass, token)
neustart = bool(ergebnis.get("neustart_noetig", True))
_LOGGER.info(
"Update installiert: Version %s - Home Assistant muss neu gestartet werden.",
"Update installiert: Version %s - %s",
ergebnis["version"],
"Home Assistant muss neu gestartet werden."
if neustart
else "nur Oberflaechen-Dateien, ein Neuladen der Seite genuegt.",
)
if not neustart:
# Ohne Neustart bleibt Home Assistants zwischengespeichertes
# Manifest stehen - die neue Nummer muss von der Platte kommen.
await k.version_neu_lesen()
k.letzte_update_pruefung = {
"verfuegbar": False,
"version": ergebnis["version"],
"geprueft_am": jetzt,
"installiert": True,
"neustart_noetig": neustart,
"fehler": None,
}
except aktualisierung.AktualisierungsFehler as fehler:
@@ -370,6 +388,7 @@ def registrieren(hass: HomeAssistant, k: Koordinator) -> None:
"version": (k.letzte_update_pruefung or {}).get("version"),
"geprueft_am": jetzt,
"installiert": False,
"neustart_noetig": True,
"fehler": str(fehler),
}
await k.app_version_veroeffentlichen()