Replace rollback with manual version selection and simplify updater

This commit is contained in:
Aaron
2025-12-14 18:20:11 -05:00
parent 831a98c5a1
commit b01bfcd38e
7 changed files with 257 additions and 203 deletions

View File

@@ -53,10 +53,12 @@ export const applyRelease = () =>
api("/api/update/apply", {
method: "POST",
});
export const rollbackRelease = () =>
api("/api/update/rollback", {
export const applyReleaseVersion = (version) =>
api("/api/update/apply_version", {
method: "POST",
body: JSON.stringify({ version }),
});
export const listReleases = () => api("/api/update/releases");
export const setReleaseAutoCheck = (enable) =>
api("/api/update/auto", {
method: "POST",

View File

@@ -5,7 +5,8 @@ import {
getReleaseStatus,
checkRelease,
applyRelease,
rollbackRelease,
applyReleaseVersion,
listReleases,
setReleaseAutoCheck,
setReleaseChannel,
} from "./api.js";
@@ -24,7 +25,8 @@ export function initReleaseUI({ showToast, showBusy, hideBusy, confirmAction, lo
const releaseProgress = document.getElementById("releaseProgress");
const releaseCheckBtn = document.getElementById("releaseCheckBtn");
const releaseApplyBtn = document.getElementById("releaseApplyBtn");
const releaseRollbackBtn = document.getElementById("releaseRollbackBtn");
const releaseVersionSelect = document.getElementById("releaseVersionSelect");
const releaseApplyVersionBtn = document.getElementById("releaseApplyVersionBtn");
const releaseAutoCheck = document.getElementById("releaseAutoCheck");
const releaseLog = document.getElementById("releaseLog");
const releaseLogStatus = document.getElementById("releaseLogStatus");
@@ -46,6 +48,7 @@ export function initReleaseUI({ showToast, showBusy, hideBusy, confirmAction, lo
let changelogCache = { version: null, text: "" };
let lastChangelogUrl = null;
let releaseChannel = "dev";
let releaseOptions = [];
const logger = createReleaseLogger(logUi);
logger.attach(releaseLog);
@@ -64,6 +67,41 @@ export function initReleaseUI({ showToast, showBusy, hideBusy, confirmAction, lo
}
};
async function loadReleaseList() {
if (!releaseVersionSelect) return;
try {
const data = await listReleases();
releaseOptions = data.releases || [];
releaseVersionSelect.innerHTML = "";
if (!releaseOptions.length) {
const opt = document.createElement("option");
opt.value = "";
opt.textContent = "No releases found";
releaseVersionSelect.appendChild(opt);
releaseVersionSelect.disabled = true;
releaseApplyVersionBtn && (releaseApplyVersionBtn.disabled = true);
return;
}
releaseVersionSelect.disabled = false;
releaseOptions.forEach((r) => {
const opt = document.createElement("option");
opt.value = r.version;
const tag = r.prerelease ? " (dev)" : "";
opt.textContent = `${r.version}${tag}${r.published_at ? `${fmtDate(r.published_at)}` : ""}`;
releaseVersionSelect.appendChild(opt);
});
if (releaseApplyVersionBtn) releaseApplyVersionBtn.disabled = false;
} catch (e) {
releaseVersionSelect.innerHTML = "";
const opt = document.createElement("option");
opt.value = "";
opt.textContent = "Failed to load releases";
releaseVersionSelect.appendChild(opt);
releaseVersionSelect.disabled = true;
if (releaseApplyVersionBtn) releaseApplyVersionBtn.disabled = true;
}
}
function setReleaseChip(state) {
if (!releaseFlagTop) return;
releaseFlagTop.textContent = "Pi-Kit: n/a";
@@ -237,6 +275,7 @@ export function initReleaseUI({ showToast, showBusy, hideBusy, confirmAction, lo
releaseBtn?.addEventListener("click", () => {
releaseModal?.classList.remove("hidden");
loadReleaseStatus(true);
loadReleaseList();
});
releaseClose?.addEventListener("click", () => releaseModal?.classList.add("hidden"));
// Do not allow dismiss by clicking backdrop (consistency with other modals)
@@ -299,19 +338,24 @@ export function initReleaseUI({ showToast, showBusy, hideBusy, confirmAction, lo
}
});
releaseRollbackBtn?.addEventListener("click", async () => {
releaseApplyVersionBtn?.addEventListener("click", async () => {
if (!releaseVersionSelect || !releaseVersionSelect.value) {
showToast("Select a version first", "error");
return;
}
try {
lastReleaseToastKey = null;
logUi("Rollback requested");
const ver = releaseVersionSelect.value;
logUi(`Install version ${ver} requested`);
releaseBusyActive = true;
showBusy("Rolling back…", "Restoring previous backup.");
logRelease("Starting rollback…");
await rollbackRelease();
showBusy(`Installing ${ver}`, "Applying selected release. This can take up to a minute.");
logRelease(`Installing ${ver}`);
await applyReleaseVersion(ver);
pollReleaseStatus();
showToast("Rollback started", "success");
showToast(`Installing ${ver}`, "success");
} catch (e) {
showToast(e.error || "Rollback failed", "error");
logRelease(`Error: ${e.error || "Rollback failed"}`);
showToast(e.error || "Install failed", "error");
logRelease(`Error: ${e.error || "Install failed"}`);
} finally {
if (releaseProgress) releaseProgress.textContent = "";
}
@@ -334,6 +378,7 @@ export function initReleaseUI({ showToast, showBusy, hideBusy, confirmAction, lo
releaseChannel = chan;
logRelease(`Channel set to ${chan}`);
await loadReleaseStatus(true);
await loadReleaseList();
} catch (e) {
showToast(e.error || "Failed to save channel", "error");
releaseChannelToggle.checked = releaseChannel === "dev";