Files
BetterDesk/web-nodejs/lib/updateResultStore.js
UNITRONIX 001de87a77 fix: clear stale update results and improve update handling
- Added functionality to clear stale update results when the local SHA matches the target SHA, preventing unnecessary warnings in the panel.
- Enhanced the update result persistence logic to filter out non-critical failures, ensuring only actionable errors are displayed.
- Updated the update service to handle remote SHA retrieval and integrate with the new result display logic.
- Improved tests for the update result handling to cover new behaviors and ensure reliability.
2026-06-10 04:26:18 +02:00

111 lines
3.3 KiB
JavaScript

'use strict';
const fs = require('fs');
const path = require('path');
const { splitUpdateFailures } = require('./updateFailurePolicy');
function lastUpdateResultPath(dataDir) {
return path.join(dataDir, '.last_update_result.json');
}
function shaMatches(a, b) {
if (!a || !b) return false;
const left = String(a).trim().toLowerCase();
const right = String(b).trim().toLowerCase();
if (!left || !right) return false;
return left === right
|| left.startsWith(right.slice(0, 7))
|| right.startsWith(left.slice(0, 7));
}
function persistUpdateResult(dataDir, payload) {
if (!dataDir) return null;
const target = lastUpdateResultPath(dataDir);
const record = {
savedAt: new Date().toISOString(),
...payload,
};
fs.mkdirSync(dataDir, { recursive: true });
fs.writeFileSync(target, JSON.stringify(record, null, 2));
return record;
}
function readLastUpdateResult(dataDir) {
if (!dataDir) return null;
const target = lastUpdateResultPath(dataDir);
if (!fs.existsSync(target)) return null;
try {
return JSON.parse(fs.readFileSync(target, 'utf8'));
} catch (_) {
return null;
}
}
function clearLastUpdateResult(dataDir) {
if (!dataDir) return false;
const target = lastUpdateResultPath(dataDir);
if (!fs.existsSync(target)) return false;
try {
fs.unlinkSync(target);
return true;
} catch (_) {
return false;
}
}
/**
* Drop stale or non-actionable update warnings from the persisted panel result.
* Returns null when nothing should be shown in Settings → Updates.
*
* @param {string} dataDir
* @param {{ rootDir?: string, localSHA?: string|null, remoteSHA?: string|null }} [opts]
* @returns {object|null}
*/
function resolveLastUpdateResultForDisplay(dataDir, opts = {}) {
const record = readLastUpdateResult(dataDir);
if (!record) return null;
const rootDir = opts.rootDir || null;
const localSHA = opts.localSHA || null;
const remoteSHA = opts.remoteSHA || null;
const { critical, nonCritical } = splitUpdateFailures(record.failed || [], rootDir);
const hasServiceFailures = Array.isArray(record.servicesFailed) && record.servicesFailed.length > 0;
const hasRestartBlock = !!record.consoleRestartBlocked;
// Target commit reached via script / external update — clear stale panel log (#192).
if (localSHA && record.sha && shaMatches(localSHA, record.sha)) {
clearLastUpdateResult(dataDir);
return null;
}
// Already at remote HEAD while the stored record targets an older commit.
if (localSHA && remoteSHA && shaMatches(localSHA, remoteSHA)
&& record.sha && !shaMatches(record.sha, remoteSHA)) {
clearLastUpdateResult(dataDir);
return null;
}
if (critical.length === 0 && !hasServiceFailures && !hasRestartBlock) {
if ((record.failed || []).length > 0 || nonCritical.length > 0) {
clearLastUpdateResult(dataDir);
}
return null;
}
return {
...record,
failed: critical,
nonCriticalFailures: nonCritical,
};
}
module.exports = {
lastUpdateResultPath,
persistUpdateResult,
readLastUpdateResult,
clearLastUpdateResult,
resolveLastUpdateResultForDisplay,
shaMatches,
};