Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f1bfab969c |
@@ -1,5 +1,21 @@
|
||||
# Changelog
|
||||
|
||||
## [0.9.13] – 2026-05-20
|
||||
|
||||
### Fixes
|
||||
- **Self-Update war in 0.9.12 kaputt (wichtig):** Der In-App-Updater ersetzte
|
||||
nur `kobrax_moonraker_bridge.py`, aber seit 0.9.12 importiert diese Datei das
|
||||
ausgelagerte `_web_assets.py` (gebündeltes Frontend). Ein Update auf 0.9.12
|
||||
crashte daher mit `ModuleNotFoundError: No module named '_web_assets'` und die
|
||||
Bridge kam nicht wieder hoch. Der Updater lädt jetzt **alle** Bridge-Module
|
||||
(Hauptdatei + `_web_assets.py` + Client + Loader) erst vollständig herunter
|
||||
und ersetzt sie dann atomar — und verweigert das Self-Update im Binary-Modus
|
||||
(stattdessen neue Binary/neues Docker-Image laden).
|
||||
|
||||
> Falls du nach dem Update auf 0.9.12 hängengeblieben bist: einmalig das
|
||||
> Docker-Image neu bauen/deployen oder die 0.9.13-Binary holen, danach
|
||||
> funktioniert das Self-Update wieder.
|
||||
|
||||
## [0.9.12] – 2026-05-20
|
||||
|
||||
### Fixes
|
||||
|
||||
15
CHANGELOG.md
15
CHANGELOG.md
@@ -1,5 +1,20 @@
|
||||
# Changelog
|
||||
|
||||
## [0.9.13] – 2026-05-20
|
||||
|
||||
### Fixes
|
||||
- **Self-update was broken for 0.9.12 (important):** the in-app updater only
|
||||
replaced `kobrax_moonraker_bridge.py`, but since 0.9.12 that file imports the
|
||||
extracted `_web_assets.py` (bundled frontend). Updating to 0.9.12 therefore
|
||||
crashed with `ModuleNotFoundError: No module named '_web_assets'` and the
|
||||
bridge wouldn't come back up. The updater now downloads **all** bridge modules
|
||||
(main file + `_web_assets.py` + client + loaders), fully, then swaps them
|
||||
atomically — and refuses to self-update in binary mode (use the new
|
||||
binary/Docker image instead).
|
||||
|
||||
> If you got stuck on 0.9.12 after pressing update: rebuild/redeploy the Docker
|
||||
> image or grab the 0.9.13 binary once, then self-update works again.
|
||||
|
||||
## [0.9.12] – 2026-05-20
|
||||
|
||||
### Fixes
|
||||
|
||||
@@ -2877,26 +2877,51 @@ class KobraXBridge:
|
||||
except Exception as e:
|
||||
return web.json_response({"error": str(e)}, status=502)
|
||||
|
||||
# Bridge-Python-Module, die das Self-Update mitziehen muss. Die Hauptdatei
|
||||
# importiert _web_assets (gebündeltes Frontend) etc. – wird nur die Hauptdatei
|
||||
# ersetzt, crasht die neue Version mit ModuleNotFoundError. Daher alle laden.
|
||||
_UPDATE_FILES = [
|
||||
"kobrax_moonraker_bridge.py",
|
||||
"_web_assets.py",
|
||||
"kobrax_client.py",
|
||||
"config_loader.py",
|
||||
"env_loader.py",
|
||||
]
|
||||
|
||||
async def handle_api_update_apply(self, request):
|
||||
data = await request.json()
|
||||
download_url = data.get("download_url", "")
|
||||
new_tag = data.get("tag", "")
|
||||
if not download_url:
|
||||
return web.json_response({"error": "download_url fehlt"}, status=400)
|
||||
script_path = pathlib.Path(sys.executable if getattr(sys, "frozen", False) else __file__).resolve()
|
||||
if getattr(sys, "frozen", False):
|
||||
return web.json_response(
|
||||
{"error": "Self-Update wird im Binary-Modus nicht unterstützt – "
|
||||
"bitte neue Binary/Docker-Image laden."}, status=400)
|
||||
if not new_tag:
|
||||
return web.json_response({"error": "tag fehlt"}, status=400)
|
||||
|
||||
app_dir = pathlib.Path(__file__).resolve().parent
|
||||
try:
|
||||
# Phase 1: ALLE Dateien herunterladen (in .new), nichts ersetzen.
|
||||
downloaded: list[tuple[pathlib.Path, bytes]] = []
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(download_url, timeout=aiohttp.ClientTimeout(total=30)) as resp:
|
||||
for fname in self._UPDATE_FILES:
|
||||
url = f"{self.GITEA_RAW_BASE}/{new_tag}/{fname}"
|
||||
async with session.get(url, timeout=aiohttp.ClientTimeout(total=30)) as resp:
|
||||
if resp.status != 200:
|
||||
return web.json_response({"error": f"Download HTTP {resp.status}"}, status=502)
|
||||
content = await resp.read()
|
||||
# Atomisch ersetzen
|
||||
tmp = script_path.with_suffix(".py.new")
|
||||
# _web_assets.py o.ä. existiert evtl. in älteren Tags nicht –
|
||||
# Hauptdatei ist Pflicht, optionale dürfen fehlen.
|
||||
if fname == "kobrax_moonraker_bridge.py":
|
||||
return web.json_response(
|
||||
{"error": f"Download {fname}: HTTP {resp.status}"}, status=502)
|
||||
log.warning(f"Update: {fname} nicht im Release ({resp.status}) – übersprungen")
|
||||
continue
|
||||
downloaded.append((app_dir / fname, await resp.read()))
|
||||
# Phase 2: atomar ersetzen (erst nach komplettem, erfolgreichem Download)
|
||||
for path, content in downloaded:
|
||||
tmp = path.with_suffix(path.suffix + ".new")
|
||||
tmp.write_bytes(content)
|
||||
os.replace(tmp, script_path)
|
||||
if new_tag:
|
||||
os.replace(tmp, path)
|
||||
self._write_version(new_tag.lstrip("v"))
|
||||
log.info(f"Update auf {new_tag} installiert, starte neu …")
|
||||
log.info(f"Update auf {new_tag} installiert ({len(downloaded)} Dateien), starte neu …")
|
||||
except Exception as e:
|
||||
return web.json_response({"error": str(e)}, status=502)
|
||||
response = web.json_response({"status": "updating"})
|
||||
|
||||
Reference in New Issue
Block a user