mirror of
https://github.com/UNITRONIX/BetterDesk.git
synced 2026-09-10 09:35:39 +00:00
83f3617f98
updateService.js: distinguish critical vs non-critical failures in SHA tracking. Server binary compile/download failures are non-critical — SHA is saved so the same update is not shown again on restart. update-cli.js: match same logic, non-critical failures don't set exit code 1. betterdesk.sh: new update_from_github() with git clone + tarball fallback, 3-method menu. betterdesk.ps1: new Update-FromGitHub with git clone + ZIP fallback, 3-method menu. betterdesk-docker.sh: new update_docker_from_github() with 2-method menu. This commit was made possible thanks to Insolve.
172 lines
6.4 KiB
JavaScript
Executable File
172 lines
6.4 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
'use strict';
|
|
|
|
const readline = require('readline');
|
|
const updateService = require('../services/updateService');
|
|
|
|
const args = new Set(process.argv.slice(2));
|
|
const yes = args.has('--yes') || args.has('-y') || args.has('--auto');
|
|
const dryRun = args.has('--check') || args.has('--dry-run');
|
|
const createBackup = !args.has('--no-backup');
|
|
|
|
function getOptionValue(name, fallback) {
|
|
const prefix = `${name}=`;
|
|
const found = process.argv.slice(2).find(arg => arg.startsWith(prefix));
|
|
return found ? found.slice(prefix.length) : fallback;
|
|
}
|
|
|
|
const serverStrategy = getOptionValue('--server-strategy', 'auto');
|
|
|
|
function step(index, total, message) {
|
|
console.log(`[${index}/${total}] ${message}`);
|
|
}
|
|
|
|
function printComponents(components) {
|
|
const entries = Object.entries(components || {}).filter(([, info]) => info.changed);
|
|
if (!entries.length) return;
|
|
console.log('Changed components:');
|
|
for (const [name, info] of entries) {
|
|
const mode = info.autoUpdate ? 'auto' : 'manual';
|
|
console.log(` - ${info.label || name}: ${info.fileCount || 0} file(s), ${mode}`);
|
|
}
|
|
}
|
|
|
|
function ask(question) {
|
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
return new Promise(resolve => {
|
|
rl.question(question, answer => {
|
|
rl.close();
|
|
resolve(answer.trim());
|
|
});
|
|
});
|
|
}
|
|
|
|
function summarizeResult(result) {
|
|
console.log('Update summary:');
|
|
console.log(` Applied: ${result.applied?.length || 0}`);
|
|
console.log(` Removed: ${result.removed?.length || 0}`);
|
|
console.log(` Skipped: ${result.skipped?.length || 0}`);
|
|
console.log(` Backup: ${result.backupPath || 'not created'}`);
|
|
if (result.serverBuild) {
|
|
console.log(` Go server build: ${result.serverBuild.success ? 'ok' : 'failed'} (${result.serverBuild.method})`);
|
|
}
|
|
if (result.serverDeploy) {
|
|
console.log(` Go server deploy: ${result.serverDeploy.success ? 'ok' : 'failed'}`);
|
|
}
|
|
if (result.serverServiceConfig?.changed) {
|
|
console.log(` Service config: ${result.serverServiceConfig.changes.join('; ')}`);
|
|
}
|
|
if (result.toolchainInstall) {
|
|
console.log(` Go toolchain: ${result.toolchainInstall.success ? 'ready' : 'failed'}`);
|
|
}
|
|
if (result.failed?.length) {
|
|
console.log('Failures:');
|
|
for (const failure of result.failed) {
|
|
console.log(` - ${failure.file}: ${failure.error}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
async function main() {
|
|
console.log('BetterDesk terminal updater');
|
|
console.log('Using the same update engine as the web console.');
|
|
console.log('');
|
|
|
|
step(1, 6, 'Checking remote update state');
|
|
const check = await updateService.checkForUpdates();
|
|
if (check.baselineEstablished) {
|
|
console.log(`Baseline established at ${check.remoteSHA.slice(0, 7)}. No update applied.`);
|
|
return;
|
|
}
|
|
if (!check.updateAvailable) {
|
|
console.log(`Already up to date (${check.remoteSHA.slice(0, 7)}).`);
|
|
return;
|
|
}
|
|
|
|
console.log(`Local SHA: ${check.localSHA || 'unknown'}`);
|
|
console.log(`Remote SHA: ${check.remoteSHA}`);
|
|
console.log(`Commits behind: ${check.commitsBehind}`);
|
|
printComponents(check.components);
|
|
|
|
step(2, 6, 'Loading changed file list');
|
|
const changedData = await updateService.getChangedFiles(check.remoteSHA);
|
|
console.log(`Changed files: ${changedData.totalFiles}`);
|
|
for (const commit of changedData.commits.slice(0, 5)) {
|
|
console.log(` - ${commit.sha} ${commit.message}`);
|
|
}
|
|
|
|
if (dryRun) {
|
|
console.log('Dry run complete. No files were changed.');
|
|
return;
|
|
}
|
|
|
|
if (!yes) {
|
|
const answer = await ask('Apply this update now? [y/N] ');
|
|
if (!/^y(es)?$/i.test(answer)) {
|
|
console.log('Update cancelled.');
|
|
return;
|
|
}
|
|
}
|
|
|
|
step(3, 6, createBackup ? 'Creating backup and applying files' : 'Applying files without backup');
|
|
const result = await updateService.applyUpdate(check.remoteSHA, changedData, {
|
|
createBackup,
|
|
serverStrategy
|
|
});
|
|
|
|
step(4, 6, 'Summarizing result');
|
|
summarizeResult(result);
|
|
|
|
// Distinguish critical failures (file download/write errors) from
|
|
// non-critical ones (server binary not available — source was still
|
|
// applied). See issue #154: server binary failures caused infinite
|
|
// update loop because SHA was never saved.
|
|
const NON_CRITICAL_FILES = new Set([
|
|
'betterdesk-server', 'betterdesk-server-deploy', 'server-source'
|
|
]);
|
|
const criticalFailures = (result.failed || []).filter(f => !NON_CRITICAL_FILES.has(f.file));
|
|
const nonCriticalFailures = (result.failed || []).filter(f => NON_CRITICAL_FILES.has(f.file));
|
|
|
|
if (criticalFailures.length) {
|
|
console.log(`\n${criticalFailures.length} critical failure(s) — update incomplete.`);
|
|
process.exitCode = 1;
|
|
return;
|
|
}
|
|
if (nonCriticalFailures.length) {
|
|
console.log(`\n${nonCriticalFailures.length} non-critical issue(s) (server binary not built/downloaded).`);
|
|
console.log('Console and script files were applied successfully. Rebuild Go server manually if needed.');
|
|
}
|
|
|
|
step(5, 6, 'Restarting affected services');
|
|
if (result.needsServerRestart) {
|
|
const serviceName = process.platform === 'win32' ? 'BetterDeskServer' : 'betterdesk-server';
|
|
const restart = updateService.restartService(serviceName);
|
|
if (restart.success) console.log(` - ${serviceName}: restarted`);
|
|
else {
|
|
console.log(` - ${serviceName}: restart failed (${restart.error})`);
|
|
process.exitCode = 1;
|
|
}
|
|
}
|
|
if (result.needsConsoleRestart) {
|
|
const serviceName = process.platform === 'win32' ? 'BetterDeskConsole' : 'betterdesk-console';
|
|
const restart = updateService.restartService(serviceName);
|
|
if (restart.success) console.log(` - ${serviceName}: restarted`);
|
|
else {
|
|
console.log(` - ${serviceName}: restart failed (${restart.error})`);
|
|
process.exitCode = 1;
|
|
}
|
|
}
|
|
if (!result.needsServerRestart && !result.needsConsoleRestart) {
|
|
console.log(' - No service restart required');
|
|
}
|
|
|
|
step(6, 6, 'Done');
|
|
if (result.shaSaved) {
|
|
console.log(`Updated baseline SHA to ${check.remoteSHA.slice(0, 7)}.`);
|
|
}
|
|
}
|
|
|
|
main().catch(err => {
|
|
console.error(`Update failed: ${err.message}`);
|
|
process.exitCode = 1;
|
|
}); |