A new plugin reads Home Assistant with a read-only token every 5 minutes and shows which Core, OS and add-on updates are waiting and how old the last backup is. Install takes a backup through a local-only webhook, confirms Home Assistant's last-backup time moved, installs, and follows the update to its end, through Home Assistant's and Steward's own restarts. One runs at a time. Each ends as one timeline entry. Steward holds nothing that can act on the house: the webhook's automation can only take a backup or install an allowed update (System 231's ruling). A refused token stops polling, as Home Assistant bans an address after a few refusals. Milestone 576 steps 1 to 5. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
35 lines
1.5 KiB
Python
35 lines
1.5 KiB
Python
# plugins/homeassistant/timeline.py
|
|
"""What Home Assistant maintenance puts on the timeline: each update once it ends."""
|
|
from __future__ import annotations
|
|
|
|
from steward.timeline import catalog
|
|
from steward.timeline.record import record_or_update
|
|
|
|
TYPES = (
|
|
("homeassistant.updated", "Home Assistant updated", "automation", "service", True,
|
|
"Steward installed a Home Assistant update after a confirmed backup."),
|
|
("homeassistant.update_failed", "Home Assistant update failed", "automation", "service", True,
|
|
"A Home Assistant update Steward was asked to install didn't finish."),
|
|
)
|
|
|
|
|
|
def register() -> None:
|
|
for t in TYPES:
|
|
catalog.register_type(*t)
|
|
from .models import HomeAssistantUpdate
|
|
catalog.register_ref("homeassistant_update", HomeAssistantUpdate)
|
|
|
|
|
|
async def update_entry(session, run) -> None:
|
|
done = run.state == "done"
|
|
versions = f"{run.from_version} to {run.to_version}" if run.to_version else "a new version"
|
|
summary = (f"{run.title} updated from {versions}" if done
|
|
else f"{run.title} update failed: {run.message}")
|
|
await record_or_update(
|
|
session, ("homeassistant_update", run.id),
|
|
type="homeassistant.updated" if done else "homeassistant.update_failed",
|
|
at=run.started_at, until=run.finished_at, summary=summary, subject=run.title,
|
|
detail={"entity_id": run.entity_id, "from": run.from_version, "to": run.to_version,
|
|
"url": "/plugins/homeassistant/"},
|
|
actor=run.started_by or "Steward")
|