feat(ops): værtens apt-sikkerhedsopdateringer på driftssiden
CD / deploy (push) Successful in 24s
CI / check (push) Successful in 32s

Proxmox VE får 'nyeste' fra værtens apt-kandidat, ny sektion med
sikkerhedspakker/genstartsbehov, ntfy ved nye sikkerhedsopdateringer.
_norm stripper release-præfiks (qBittorrent).

Claude-Session: https://claude.ai/code/session_01AUj1LSMmrowcomkn1ciAgj
This commit is contained in:
root
2026-10-09 19:25:57 +02:00
parent 79f49bda45
commit 6e5bb5eac1
4 changed files with 37 additions and 5 deletions
+13 -3
View File
@@ -74,8 +74,8 @@ SERVICES = [
def _norm(v):
if not v:
return ""
# behold dato-versioner (fx NPMplus 2026-04-21-r2) — strip kun v-præfiks + build-metadata
return re.sub(r"^[vV]", "", str(v).strip()).split("+")[0].strip().lower()
# behold dato-versioner (fx NPMplus 2026-04-21-r2) — strip kun v-/release-præfiks + build-metadata
return re.sub(r"^(release-)?[vV]?", "", str(v).strip()).split("+")[0].strip().lower()
async def _latest(src, client, store):
@@ -229,7 +229,8 @@ async def _one(name, kind, repo, client, local, store):
cur, lat_builtin = await _current(kind, client)
if not cur:
cur = local.get(name) # vært-indsamlet snapshot for LXC-tjenester
latest = lat_builtin or await _latest(repo, client, store)
# _latest i snapshot'et = nyeste fra værten selv (fx apt-kandidat for pve-manager)
latest = lat_builtin or await _latest(repo, client, store) or local.get("_latest", {}).get(name)
eol = await _eol(name, cur, client)
level = None
if cur and latest:
@@ -263,6 +264,10 @@ async def _maybe_alert(res, client):
if e and e.get("state") in ("eol", "soon"):
sig = f"eol:{v['name']}:{e.get('date')}"
cur.add(sig); detail[sig] = f"⏳ {v['name']} EOL {e.get('date')}"
h = host_updates()
if h and h.get("security"):
sig = "sec:host:" + ",".join(sorted(f"{p['name']}={p['to']}" for p in h["security_pkgs"]))
cur.add(sig); detail[sig] = f"🔒 Proxmox-vært: {h['security']} sikkerhedsopdateringer"
try:
stored = set(json.loads(ALERT_STATE.read_text("utf-8")))
except Exception:
@@ -285,6 +290,11 @@ async def _maybe_alert(res, client):
ALERT_STATE.write_text(json.dumps(sorted(cur)), "utf-8")
def host_updates():
"""Værtens apt-status (indsamlet af portal-versions.py) eller None."""
return _load_local().get("_host")
async def all_versions():
hit = cache.get("ver:all")
if hit is not None: