Improve updater version selection and surface release dates
This commit is contained in:
@@ -18,6 +18,8 @@ export function initReleaseUI({ showToast, showBusy, hideBusy, confirmAction, lo
|
|||||||
const releaseClose = document.getElementById("releaseClose");
|
const releaseClose = document.getElementById("releaseClose");
|
||||||
const releaseCurrent = document.getElementById("releaseCurrent");
|
const releaseCurrent = document.getElementById("releaseCurrent");
|
||||||
const releaseLatest = document.getElementById("releaseLatest");
|
const releaseLatest = document.getElementById("releaseLatest");
|
||||||
|
const releaseCurrentDate = document.getElementById("releaseCurrentDate");
|
||||||
|
const releaseLatestDate = document.getElementById("releaseLatestDate");
|
||||||
const releaseStatusMsg = document.getElementById("releaseStatusMsg");
|
const releaseStatusMsg = document.getElementById("releaseStatusMsg");
|
||||||
const releaseProgress = document.getElementById("releaseProgress");
|
const releaseProgress = document.getElementById("releaseProgress");
|
||||||
const releaseCheckBtn = document.getElementById("releaseCheckBtn");
|
const releaseCheckBtn = document.getElementById("releaseCheckBtn");
|
||||||
@@ -47,6 +49,21 @@ export function initReleaseUI({ showToast, showBusy, hideBusy, confirmAction, lo
|
|||||||
const logger = createReleaseLogger(logUi);
|
const logger = createReleaseLogger(logUi);
|
||||||
logger.attach(releaseLog);
|
logger.attach(releaseLog);
|
||||||
|
|
||||||
|
const fmtDate = (iso) => {
|
||||||
|
if (!iso) return "—";
|
||||||
|
try {
|
||||||
|
const d = new Date(iso);
|
||||||
|
if (Number.isNaN(d.getTime())) return "—";
|
||||||
|
return d.toLocaleDateString(undefined, {
|
||||||
|
year: "numeric",
|
||||||
|
month: "short",
|
||||||
|
day: "numeric",
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
return "—";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
function setReleaseChip(state) {
|
function setReleaseChip(state) {
|
||||||
if (!releaseFlagTop) return;
|
if (!releaseFlagTop) return;
|
||||||
releaseFlagTop.textContent = "Pi-Kit: n/a";
|
releaseFlagTop.textContent = "Pi-Kit: n/a";
|
||||||
@@ -69,7 +86,9 @@ export function initReleaseUI({ showToast, showBusy, hideBusy, confirmAction, lo
|
|||||||
const msg = shorten(message, 80) || "";
|
const msg = shorten(message, 80) || "";
|
||||||
releaseFlagTop.title = msg || "Pi-Kit release status";
|
releaseFlagTop.title = msg || "Pi-Kit release status";
|
||||||
if (releaseStatusMsg) {
|
if (releaseStatusMsg) {
|
||||||
releaseStatusMsg.textContent = status === "update_available" ? msg || "Update available" : "";
|
const isUrlMsg = msg && /^https?:/i.test(msg);
|
||||||
|
const safeMsg = isUrlMsg ? "Update available" : msg;
|
||||||
|
releaseStatusMsg.textContent = status === "update_available" ? safeMsg || "Update available" : "";
|
||||||
releaseStatusMsg.classList.remove("error");
|
releaseStatusMsg.classList.remove("error");
|
||||||
}
|
}
|
||||||
if (releaseLogStatus) {
|
if (releaseLogStatus) {
|
||||||
@@ -133,6 +152,9 @@ export function initReleaseUI({ showToast, showBusy, hideBusy, confirmAction, lo
|
|||||||
auto_check = false,
|
auto_check = false,
|
||||||
progress = null,
|
progress = null,
|
||||||
channel = "dev",
|
channel = "dev",
|
||||||
|
current_release_date = null,
|
||||||
|
latest_release_date = null,
|
||||||
|
changelog_url = null,
|
||||||
} = data || {};
|
} = data || {};
|
||||||
releaseChannel = channel || "dev";
|
releaseChannel = channel || "dev";
|
||||||
if (releaseChannelToggle) releaseChannelToggle.checked = releaseChannel === "dev";
|
if (releaseChannelToggle) releaseChannelToggle.checked = releaseChannel === "dev";
|
||||||
@@ -143,14 +165,17 @@ export function initReleaseUI({ showToast, showBusy, hideBusy, confirmAction, lo
|
|||||||
lastReleaseLogKey = key;
|
lastReleaseLogKey = key;
|
||||||
}
|
}
|
||||||
releaseLastFetched = now;
|
releaseLastFetched = now;
|
||||||
if (status === "update_available" && message && message.startsWith("http")) {
|
lastChangelogUrl = changelog_url || null;
|
||||||
|
if (!lastChangelogUrl && status === "update_available" && message && message.startsWith("http")) {
|
||||||
lastChangelogUrl = message;
|
lastChangelogUrl = message;
|
||||||
} else if (latest_version) {
|
} else if (!lastChangelogUrl && latest_version) {
|
||||||
lastChangelogUrl = `https://git.44r0n.cc/44r0n7/pi-kit/releases/download/v${latest_version}/CHANGELOG-${latest_version}.txt`;
|
lastChangelogUrl = `https://git.44r0n.cc/44r0n7/pi-kit/releases/download/v${latest_version}/CHANGELOG-${latest_version}.txt`;
|
||||||
}
|
}
|
||||||
setReleaseChip(data);
|
setReleaseChip(data);
|
||||||
if (releaseCurrent) releaseCurrent.textContent = current_version;
|
if (releaseCurrent) releaseCurrent.textContent = current_version;
|
||||||
if (releaseLatest) releaseLatest.textContent = latest_version;
|
if (releaseLatest) releaseLatest.textContent = latest_version;
|
||||||
|
if (releaseCurrentDate) releaseCurrentDate.textContent = fmtDate(current_release_date);
|
||||||
|
if (releaseLatestDate) releaseLatestDate.textContent = fmtDate(latest_release_date);
|
||||||
if (releaseAutoCheck) releaseAutoCheck.checked = !!auto_check;
|
if (releaseAutoCheck) releaseAutoCheck.checked = !!auto_check;
|
||||||
if (releaseProgress) releaseProgress.textContent = "";
|
if (releaseProgress) releaseProgress.textContent = "";
|
||||||
if (status === "in_progress" && progress) {
|
if (status === "in_progress" && progress) {
|
||||||
@@ -317,8 +342,11 @@ export function initReleaseUI({ showToast, showBusy, hideBusy, confirmAction, lo
|
|||||||
|
|
||||||
releaseChangelogBtn?.addEventListener("click", async () => {
|
releaseChangelogBtn?.addEventListener("click", async () => {
|
||||||
const state = window.__lastReleaseState || {};
|
const state = window.__lastReleaseState || {};
|
||||||
const { latest_version, message } = state;
|
const { latest_version, message, changelog_url } = state;
|
||||||
const url = (message && message.startsWith("http") ? message : null) || lastChangelogUrl;
|
const url =
|
||||||
|
changelog_url ||
|
||||||
|
(message && message.startsWith("http") ? message : null) ||
|
||||||
|
lastChangelogUrl;
|
||||||
if (!url) {
|
if (!url) {
|
||||||
showToast("No changelog URL available", "error");
|
showToast("No changelog URL available", "error");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
"last_check": "2025-12-10T22:00:00Z",
|
"last_check": "2025-12-10T22:00:00Z",
|
||||||
"status": "update_available",
|
"status": "update_available",
|
||||||
"message": "New UI polish and bug fixes.",
|
"message": "New UI polish and bug fixes.",
|
||||||
|
"changelog_url": "https://git.44r0n.cc/44r0n7/pi-kit/releases/download/v0.1.1-mock/CHANGELOG-0.1.1-mock.txt",
|
||||||
|
"latest_release_date": "2025-12-09T18:00:00Z",
|
||||||
|
"current_release_date": "2025-12-01T17:00:00Z",
|
||||||
"auto_check": true,
|
"auto_check": true,
|
||||||
"in_progress": false,
|
"in_progress": false,
|
||||||
"progress": null
|
"progress": null
|
||||||
|
|||||||
@@ -148,10 +148,12 @@
|
|||||||
<div>
|
<div>
|
||||||
<p class="hint quiet">Current version</p>
|
<p class="hint quiet">Current version</p>
|
||||||
<h3 id="releaseCurrent">n/a</h3>
|
<h3 id="releaseCurrent">n/a</h3>
|
||||||
|
<p class="hint quiet" id="releaseCurrentDate">—</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="align-right">
|
<div class="align-right">
|
||||||
<p class="hint quiet">Latest available</p>
|
<p class="hint quiet">Latest available</p>
|
||||||
<h3 id="releaseLatest">—</h3>
|
<h3 id="releaseLatest">—</h3>
|
||||||
|
<p class="hint quiet" id="releaseLatestDate">—</p>
|
||||||
<p id="releaseStatusMsg" class="hint status-msg"></p>
|
<p id="releaseStatusMsg" class="hint status-msg"></p>
|
||||||
<button id="releaseChangelogBtn" class="ghost small" title="View changelog">Changelog</button>
|
<button id="releaseChangelogBtn" class="ghost small" title="View changelog">Changelog</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -45,7 +45,11 @@ def load_update_state() -> Dict[str, Any]:
|
|||||||
UPDATE_STATE_DIR.mkdir(parents=True, exist_ok=True)
|
UPDATE_STATE_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
if UPDATE_STATE.exists():
|
if UPDATE_STATE.exists():
|
||||||
try:
|
try:
|
||||||
return json.loads(UPDATE_STATE.read_text())
|
state = json.loads(UPDATE_STATE.read_text())
|
||||||
|
state.setdefault("changelog_url", None)
|
||||||
|
state.setdefault("latest_release_date", None)
|
||||||
|
state.setdefault("current_release_date", None)
|
||||||
|
return state
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
return {
|
return {
|
||||||
@@ -58,6 +62,9 @@ def load_update_state() -> Dict[str, Any]:
|
|||||||
"in_progress": False,
|
"in_progress": False,
|
||||||
"progress": None,
|
"progress": None,
|
||||||
"channel": os.environ.get("PIKIT_CHANNEL", "dev"),
|
"channel": os.environ.get("PIKIT_CHANNEL", "dev"),
|
||||||
|
"changelog_url": None,
|
||||||
|
"latest_release_date": None,
|
||||||
|
"current_release_date": None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -119,32 +126,78 @@ def fetch_manifest(url: str | None = None):
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
def fetch_manifest_for_channel(channel: str):
|
def _try_fetch(url: Optional[str]):
|
||||||
|
if not url:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
return fetch_manifest(url)
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_manifest_for_channel(channel: str, with_meta: bool = False):
|
||||||
"""
|
"""
|
||||||
For stable: use normal manifest (latest non-prerelease).
|
For stable: use normal manifest (latest non-prerelease).
|
||||||
For dev: try normal manifest; if it points to stable, fetch latest prerelease manifest via Gitea API.
|
For dev: try normal manifest; if it points to stable, fetch latest prerelease manifest via Gitea API.
|
||||||
|
If a stable build is newer than the latest dev build, prefer the newer stable even on dev channel.
|
||||||
"""
|
"""
|
||||||
channel = channel or "dev"
|
channel = channel or "dev"
|
||||||
base_manifest_url = os.environ.get("PIKIT_MANIFEST_URL") or DEFAULT_MANIFEST_URL
|
base_manifest_url = os.environ.get("PIKIT_MANIFEST_URL") or DEFAULT_MANIFEST_URL
|
||||||
|
dev_manifest_url = os.environ.get("PIKIT_DEV_MANIFEST_URL")
|
||||||
|
stable_manifest_url = os.environ.get("PIKIT_STABLE_MANIFEST_URL") or base_manifest_url
|
||||||
manifest = None
|
manifest = None
|
||||||
|
version_dates: Dict[str, Optional[str]] = {}
|
||||||
try:
|
try:
|
||||||
manifest = fetch_manifest(base_manifest_url)
|
manifest = fetch_manifest(stable_manifest_url)
|
||||||
except Exception:
|
except Exception:
|
||||||
manifest = None
|
manifest = None
|
||||||
|
|
||||||
if manifest and channel == "stable":
|
def _norm_ver(ver):
|
||||||
return manifest
|
if ver is None:
|
||||||
if manifest:
|
return None
|
||||||
version = manifest.get("version") or manifest.get("latest_version")
|
s = str(ver).strip()
|
||||||
if channel == "dev" and version and "dev" in str(version):
|
if s.lower().startswith("v"):
|
||||||
return manifest
|
s = s[1:]
|
||||||
|
return s
|
||||||
|
|
||||||
|
def _newer(a, b):
|
||||||
|
try:
|
||||||
|
from distutils.version import LooseVersion
|
||||||
|
|
||||||
|
return LooseVersion(a) > LooseVersion(b)
|
||||||
|
except Exception:
|
||||||
|
return a > b
|
||||||
|
|
||||||
|
def _release_version(rel: Dict[str, Any]):
|
||||||
|
for key in ("tag_name", "name"):
|
||||||
|
val = rel.get(key)
|
||||||
|
if val:
|
||||||
|
v = _norm_ver(val)
|
||||||
|
if v:
|
||||||
|
return v
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _manifest_from_release(rel: Dict[str, Any]):
|
||||||
|
asset = next((a for a in rel.get("assets", []) if a.get("name") == "manifest.json"), None)
|
||||||
|
if not asset or not asset.get("browser_download_url"):
|
||||||
|
return None
|
||||||
|
mf = fetch_manifest(asset["browser_download_url"])
|
||||||
|
if mf:
|
||||||
|
dt = rel.get("published_at") or rel.get("created_at")
|
||||||
|
if dt:
|
||||||
|
mf["_release_date"] = dt
|
||||||
|
tag = rel.get("tag_name")
|
||||||
|
if tag:
|
||||||
|
mf["_release_tag"] = tag
|
||||||
|
return mf
|
||||||
|
|
||||||
try:
|
try:
|
||||||
parts = base_manifest_url.split("/")
|
parts = base_manifest_url.split("/")
|
||||||
if "releases" not in parts:
|
if "releases" not in parts:
|
||||||
if manifest:
|
if manifest:
|
||||||
return manifest
|
return (manifest, {"version_dates": version_dates}) if with_meta else manifest
|
||||||
return fetch_manifest(base_manifest_url)
|
mf = fetch_manifest(base_manifest_url)
|
||||||
|
return (mf, {"version_dates": version_dates}) if with_meta else mf
|
||||||
idx = parts.index("releases")
|
idx = parts.index("releases")
|
||||||
owner = parts[idx - 2]
|
owner = parts[idx - 2]
|
||||||
repo = parts[idx - 1]
|
repo = parts[idx - 1]
|
||||||
@@ -157,25 +210,78 @@ def fetch_manifest_for_channel(channel: str):
|
|||||||
resp = urllib.request.urlopen(req, timeout=10)
|
resp = urllib.request.urlopen(req, timeout=10)
|
||||||
releases = json.loads(resp.read().decode())
|
releases = json.loads(resp.read().decode())
|
||||||
|
|
||||||
def pick(predicate):
|
# Map release versions to published dates so we can surface them later
|
||||||
for r in releases:
|
for rel in releases:
|
||||||
if predicate(r):
|
v = _release_version(rel)
|
||||||
asset = next((a for a in r.get("assets", []) if a.get("name") == "manifest.json"), None)
|
if v and v not in version_dates:
|
||||||
if asset and asset.get("browser_download_url"):
|
version_dates[v] = rel.get("published_at") or rel.get("created_at")
|
||||||
return fetch_manifest(asset["browser_download_url"])
|
|
||||||
return None
|
dev_rel = None
|
||||||
|
stable_rel = None
|
||||||
|
dev_ver = None
|
||||||
|
stable_ver = None
|
||||||
|
for rel in releases:
|
||||||
|
ver_str = _release_version(rel)
|
||||||
|
parsed = _norm_ver(ver_str) if ver_str else None
|
||||||
|
if parsed is None:
|
||||||
|
continue
|
||||||
|
if rel.get("prerelease") is True:
|
||||||
|
if dev_ver is None or _newer(parsed.replace("-", "."), dev_ver):
|
||||||
|
dev_rel = rel
|
||||||
|
dev_ver = parsed.replace("-", ".")
|
||||||
|
elif rel.get("prerelease") is False:
|
||||||
|
if stable_ver is None or _newer(parsed.replace("-", "."), stable_ver):
|
||||||
|
stable_rel = rel
|
||||||
|
stable_ver = parsed.replace("-", ".")
|
||||||
|
|
||||||
|
latest_dev = _manifest_from_release(dev_rel) if dev_rel else None
|
||||||
|
latest_stable = _manifest_from_release(stable_rel) if stable_rel else None
|
||||||
|
|
||||||
|
# If API didn't give us a dev manifest, try explicitly configured dev URL
|
||||||
|
if dev_manifest_url and latest_dev is None:
|
||||||
|
latest_dev = _try_fetch(dev_manifest_url)
|
||||||
|
if latest_dev and "_release_date" not in latest_dev:
|
||||||
|
latest_dev["_release_date"] = version_dates.get(
|
||||||
|
_norm_ver(latest_dev.get("version") or latest_dev.get("latest_version")), None
|
||||||
|
)
|
||||||
|
|
||||||
|
# Attach publish date to the base manifest when possible
|
||||||
|
if manifest:
|
||||||
|
mver = _norm_ver(manifest.get("version") or manifest.get("latest_version"))
|
||||||
|
if mver and mver in version_dates and "_release_date" not in manifest:
|
||||||
|
manifest["_release_date"] = version_dates[mver]
|
||||||
|
|
||||||
if channel == "dev":
|
if channel == "dev":
|
||||||
m = pick(lambda r: r.get("prerelease") is True)
|
# Choose the newest by version comparison across stable/dev/base candidates
|
||||||
if m:
|
candidates = [c for c in (latest_dev, latest_stable, manifest) if c]
|
||||||
return m
|
best = None
|
||||||
m = pick(lambda r: r.get("prerelease") is False)
|
best_ver = None
|
||||||
if m:
|
for c in candidates:
|
||||||
return m
|
ver = _norm_ver(c.get("version") or c.get("latest_version"))
|
||||||
|
if not ver:
|
||||||
|
continue
|
||||||
|
ver_cmp = ver.replace("-", ".")
|
||||||
|
if best_ver is None or _newer(ver_cmp, best_ver):
|
||||||
|
best = c
|
||||||
|
best_ver = ver_cmp
|
||||||
|
manifest = best
|
||||||
|
else:
|
||||||
|
# stable channel
|
||||||
|
manifest = latest_stable or manifest
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# As a last resort for dev channel, consider explicitly configured dev manifest even without API data
|
||||||
|
if channel == "dev" and manifest is None and dev_manifest_url:
|
||||||
|
manifest = _try_fetch(dev_manifest_url)
|
||||||
|
|
||||||
|
# If still nothing and stable manifest URL is set, try that once more
|
||||||
|
if manifest is None and stable_manifest_url and stable_manifest_url != base_manifest_url:
|
||||||
|
manifest = _try_fetch(stable_manifest_url)
|
||||||
|
|
||||||
if manifest:
|
if manifest:
|
||||||
|
if with_meta:
|
||||||
|
return manifest, {"version_dates": version_dates}
|
||||||
return manifest
|
return manifest
|
||||||
raise RuntimeError("No manifest found for channel")
|
raise RuntimeError("No manifest found for channel")
|
||||||
|
|
||||||
@@ -303,10 +409,25 @@ def check_for_update():
|
|||||||
state["progress"] = "Checking for updates…"
|
state["progress"] = "Checking for updates…"
|
||||||
save_update_state(state)
|
save_update_state(state)
|
||||||
try:
|
try:
|
||||||
manifest = fetch_manifest_for_channel(state.get("channel") or "dev")
|
manifest, meta = fetch_manifest_for_channel(state.get("channel") or "dev", with_meta=True)
|
||||||
latest = manifest.get("version") or manifest.get("latest_version")
|
latest = manifest.get("version") or manifest.get("latest_version")
|
||||||
state["latest_version"] = latest
|
state["latest_version"] = latest
|
||||||
|
state["changelog_url"] = manifest.get("changelog")
|
||||||
state["last_check"] = datetime.datetime.utcnow().isoformat() + "Z"
|
state["last_check"] = datetime.datetime.utcnow().isoformat() + "Z"
|
||||||
|
version_dates = (meta or {}).get("version_dates") or {}
|
||||||
|
if manifest.get("_release_date"):
|
||||||
|
state["latest_release_date"] = manifest.get("_release_date")
|
||||||
|
elif latest and latest in version_dates:
|
||||||
|
state["latest_release_date"] = version_dates.get(str(latest))
|
||||||
|
else:
|
||||||
|
state["latest_release_date"] = None
|
||||||
|
state["current_release_date"] = None
|
||||||
|
current_ver = state.get("current_version")
|
||||||
|
if current_ver and current_ver in version_dates:
|
||||||
|
state["current_release_date"] = version_dates.get(str(current_ver))
|
||||||
|
elif current_ver and current_ver == latest and state["latest_release_date"]:
|
||||||
|
# If current matches latest and we have a date for latest, reuse it
|
||||||
|
state["current_release_date"] = state["latest_release_date"]
|
||||||
channel = state.get("channel") or "dev"
|
channel = state.get("channel") or "dev"
|
||||||
if channel == "stable" and latest and "dev" in str(latest):
|
if channel == "stable" and latest and "dev" in str(latest):
|
||||||
state["status"] = "up_to_date"
|
state["status"] = "up_to_date"
|
||||||
@@ -314,7 +435,7 @@ def check_for_update():
|
|||||||
else:
|
else:
|
||||||
if latest and latest != state.get("current_version"):
|
if latest and latest != state.get("current_version"):
|
||||||
state["status"] = "update_available"
|
state["status"] = "update_available"
|
||||||
state["message"] = manifest.get("changelog", "Update available")
|
state["message"] = manifest.get("notes") or manifest.get("message") or "Update available"
|
||||||
else:
|
else:
|
||||||
state["status"] = "up_to_date"
|
state["status"] = "up_to_date"
|
||||||
state["message"] = "Up to date"
|
state["message"] = "Up to date"
|
||||||
@@ -323,6 +444,7 @@ def check_for_update():
|
|||||||
state["status"] = "up_to_date"
|
state["status"] = "up_to_date"
|
||||||
state["message"] = f"Could not reach update server: {e}"
|
state["message"] = f"Could not reach update server: {e}"
|
||||||
state["last_check"] = datetime.datetime.utcnow().isoformat() + "Z"
|
state["last_check"] = datetime.datetime.utcnow().isoformat() + "Z"
|
||||||
|
state["latest_release_date"] = None
|
||||||
diag_log("error", "Update check failed", {"error": str(e)})
|
diag_log("error", "Update check failed", {"error": str(e)})
|
||||||
finally:
|
finally:
|
||||||
state["in_progress"] = False
|
state["in_progress"] = False
|
||||||
@@ -371,7 +493,7 @@ def apply_update():
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
channel = state.get("channel") or os.environ.get("PIKIT_CHANNEL", "dev")
|
channel = state.get("channel") or os.environ.get("PIKIT_CHANNEL", "dev")
|
||||||
manifest = fetch_manifest_for_channel(channel)
|
manifest, meta = fetch_manifest_for_channel(channel, with_meta=True)
|
||||||
latest = manifest.get("version") or manifest.get("latest_version")
|
latest = manifest.get("version") or manifest.get("latest_version")
|
||||||
if not latest:
|
if not latest:
|
||||||
raise RuntimeError("Manifest missing version")
|
raise RuntimeError("Manifest missing version")
|
||||||
@@ -428,6 +550,9 @@ def apply_update():
|
|||||||
|
|
||||||
state["current_version"] = str(latest)
|
state["current_version"] = str(latest)
|
||||||
state["latest_version"] = str(latest)
|
state["latest_version"] = str(latest)
|
||||||
|
state["changelog_url"] = manifest.get("changelog")
|
||||||
|
state["latest_release_date"] = manifest.get("_release_date") or (meta or {}).get("version_dates", {}).get(str(latest))
|
||||||
|
state["current_release_date"] = state.get("latest_release_date")
|
||||||
state["status"] = "up_to_date"
|
state["status"] = "up_to_date"
|
||||||
state["message"] = "Update installed"
|
state["message"] = "Update installed"
|
||||||
state["progress"] = None
|
state["progress"] = None
|
||||||
@@ -436,11 +561,13 @@ def apply_update():
|
|||||||
except urllib.error.HTTPError as e:
|
except urllib.error.HTTPError as e:
|
||||||
state["status"] = "error"
|
state["status"] = "error"
|
||||||
state["message"] = f"No release available ({e.code})"
|
state["message"] = f"No release available ({e.code})"
|
||||||
|
state["latest_release_date"] = None
|
||||||
diag_log("error", "Update apply HTTP error", {"code": e.code})
|
diag_log("error", "Update apply HTTP error", {"code": e.code})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
state["status"] = "error"
|
state["status"] = "error"
|
||||||
state["message"] = f"Update failed: {e}"
|
state["message"] = f"Update failed: {e}"
|
||||||
state["progress"] = None
|
state["progress"] = None
|
||||||
|
state["latest_release_date"] = None
|
||||||
save_update_state(state)
|
save_update_state(state)
|
||||||
diag_log("error", "Update apply failed", {"error": str(e)})
|
diag_log("error", "Update apply failed", {"error": str(e)})
|
||||||
backup = choose_rollback_backup()
|
backup = choose_rollback_backup()
|
||||||
|
|||||||
Reference in New Issue
Block a user