HomeCore Controller v0.1.13 staged from HomeCore Admin
This commit is contained in:
parent
f80139c3e4
commit
45e73f118e
@ -1,5 +1,14 @@
|
||||
# HomeCore Controller Changelog
|
||||
|
||||
## 0.1.13
|
||||
|
||||
- Fixes HomeCore self-update architecture for Home Assistant OS.
|
||||
- Home Assistant Supervisor intentionally blocks an app from updating itself directly.
|
||||
- HomeCore now asks Home Assistant Core to run the supported `update.install` action for the HomeCore Controller update entity.
|
||||
- Keeps repository validation, backup-before-update, restart recovery and completion reporting.
|
||||
- Automatic rollout remains disabled; deployment is still manual and per-controller from HomeCore Admin.
|
||||
- No functional home-control changes from 0.1.12.
|
||||
|
||||
## 0.1.12
|
||||
|
||||
- End-to-end validation release for HomeCore Admin manual per-controller updating using the Supervisor `admin` API role.
|
||||
|
||||
@ -16,7 +16,7 @@ from cryptography.hazmat.primitives import serialization
|
||||
import uvicorn
|
||||
from updater import start_update_manager
|
||||
|
||||
VERSION = "0.1.12"
|
||||
VERSION = "0.1.13"
|
||||
|
||||
print(
|
||||
"HOMECORE SUPERVISOR: token "
|
||||
|
||||
@ -62,6 +62,74 @@ def supervisor_request(method, path, payload=None, timeout=90):
|
||||
return body
|
||||
|
||||
|
||||
HOME_ASSISTANT_API = "http://supervisor/core/api"
|
||||
|
||||
|
||||
def homeassistant_request(method, path, payload=None, timeout=90):
|
||||
r = httpx.request(
|
||||
method,
|
||||
HOME_ASSISTANT_API + path,
|
||||
headers=supervisor_headers(),
|
||||
json=payload,
|
||||
timeout=timeout,
|
||||
)
|
||||
r.raise_for_status()
|
||||
|
||||
try:
|
||||
return r.json()
|
||||
except Exception:
|
||||
return {}
|
||||
|
||||
|
||||
def find_homecore_update_entity(current_version, target_version):
|
||||
states = homeassistant_request("GET", "/states", timeout=30)
|
||||
if not isinstance(states, list):
|
||||
raise RuntimeError("Home Assistant did not return entity states")
|
||||
|
||||
candidates = []
|
||||
|
||||
for state in states:
|
||||
entity_id = str(state.get("entity_id", ""))
|
||||
if not entity_id.startswith("update."):
|
||||
continue
|
||||
|
||||
attrs = state.get("attributes") or {}
|
||||
title = str(attrs.get("title") or "")
|
||||
friendly = str(attrs.get("friendly_name") or "")
|
||||
installed = str(attrs.get("installed_version") or "")
|
||||
latest = str(attrs.get("latest_version") or "")
|
||||
|
||||
name_match = (
|
||||
"homecore controller" in title.lower()
|
||||
or "homecore controller" in friendly.lower()
|
||||
)
|
||||
|
||||
version_match = (
|
||||
installed == current_version
|
||||
and latest == target_version
|
||||
)
|
||||
|
||||
if name_match:
|
||||
candidates.append((state, version_match))
|
||||
|
||||
exact = [state for state, version_match in candidates if version_match]
|
||||
if exact:
|
||||
return exact[0]
|
||||
|
||||
if len(candidates) == 1:
|
||||
return candidates[0][0]
|
||||
|
||||
if not candidates:
|
||||
raise RuntimeError(
|
||||
"HomeCore Controller update entity was not found in Home Assistant"
|
||||
)
|
||||
|
||||
raise RuntimeError(
|
||||
"Multiple HomeCore Controller update entities were found; "
|
||||
"cannot choose safely"
|
||||
)
|
||||
|
||||
|
||||
def find_homecore_app():
|
||||
data = supervisor_request("GET", "/store/addons")
|
||||
|
||||
@ -321,17 +389,44 @@ class HomeCoreUpdateManager:
|
||||
"Backup requested; Supervisor update starting",
|
||||
)
|
||||
|
||||
supervisor_request(
|
||||
"POST",
|
||||
f"/store/addons/{slug}/update",
|
||||
{
|
||||
"backup": True,
|
||||
"background": True,
|
||||
},
|
||||
update_entity = find_homecore_update_entity(
|
||||
self.current_version,
|
||||
target,
|
||||
)
|
||||
update_entity_id = str(update_entity.get("entity_id", "")).strip()
|
||||
|
||||
if not update_entity_id:
|
||||
raise RuntimeError(
|
||||
"HomeCore Controller update entity ID is missing"
|
||||
)
|
||||
|
||||
print(
|
||||
"HOMECORE UPDATE: Supervisor accepted manual update job",
|
||||
"HOMECORE UPDATE: Home Assistant update action "
|
||||
f"entity={update_entity_id} target={target}",
|
||||
flush=True,
|
||||
)
|
||||
|
||||
# Home Assistant Supervisor deliberately blocks an app from calling
|
||||
# its own /store/addons/<slug>/update endpoint. Ask Home Assistant Core
|
||||
# to execute the normal update.install action instead. Core performs
|
||||
# the Supervisor update, exactly as if an administrator installed the
|
||||
# app update from the Home Assistant UI.
|
||||
#
|
||||
# The state above is written before this call because updating this
|
||||
# app stops the current container. On restart, mark_completed_if_required
|
||||
# reports completion back to HomeCore Admin.
|
||||
homeassistant_request(
|
||||
"POST",
|
||||
"/services/update/install",
|
||||
{
|
||||
"entity_id": update_entity_id,
|
||||
"backup": True,
|
||||
},
|
||||
timeout=300,
|
||||
)
|
||||
|
||||
print(
|
||||
"HOMECORE UPDATE: Home Assistant accepted manual update action",
|
||||
flush=True,
|
||||
)
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
name: HomeCore Controller
|
||||
version: "0.1.12"
|
||||
version: "0.1.13"
|
||||
slug: homecore_controller
|
||||
description: HomeCore local controller agent for Home Assistant Green.
|
||||
url: https://homecore.home-core.co.uk
|
||||
|
||||
Loading…
Reference in New Issue
Block a user