feat: implement rollback functionality with pre-update backup and recovery options | Rebase

This commit is contained in:
HueByte
2026-02-23 18:15:16 +01:00
parent 760693befe
commit 38df05df41
7 changed files with 359 additions and 13 deletions
+79 -1
View File
@@ -1,12 +1,58 @@
using EchoHub.Client;
using EchoHub.Client.Config;
using EchoHub.Client.Services;
using EchoHub.Client.Themes;
using Microsoft.Extensions.Configuration;
using Serilog;
using Terminal.Gui.App;
using Terminal.Gui.Drawing;
// == CLI rollback: works without TUI, before anything else ================
if (args.Contains("--rollback"))
{
if (UpdateBackupService.BackupExists())
{
var info = UpdateBackupService.GetBackupInfo();
Console.WriteLine($"Rolling back to version {info?.Version ?? "unknown"}...");
try
{
UpdateBackupService.RestoreBackup();
// RestoreBackup calls Environment.Exit(0)
}
catch (Exception ex)
{
Console.Error.WriteLine($"Rollback failed: {ex.Message}");
Environment.Exit(1);
}
}
else
{
Console.Error.WriteLine("No backup available to restore.");
Environment.Exit(1);
}
}
// == Unix permission self-check (defense-in-depth after auto-update) ==
if (!OperatingSystem.IsWindows())
{
var exePath = Environment.ProcessPath;
if (!string.IsNullOrEmpty(exePath))
{
try
{
var mode = File.GetUnixFileMode(exePath);
if ((mode & UnixFileMode.UserExecute) == 0)
{
File.SetUnixFileMode(exePath, mode | UnixFileMode.UserExecute);
}
}
catch
{
// Best-effort; if we're running, we already have execute permission
}
}
}
// == Normal startup ==
var appSettingsPath = Path.Combine(AppContext.BaseDirectory, "appsettings.json");
if (!File.Exists(appSettingsPath))
{
@@ -31,6 +77,38 @@ Log.Logger = new LoggerConfiguration()
Log.Information("EchoHub client starting");
// == Post-update detection: stale backup cleanup or flag for rollback menu ================
if (UpdateBackupService.BackupExists())
{
var backupInfo = UpdateBackupService.GetBackupInfo();
if (backupInfo is not null && DateTimeOffset.UtcNow - backupInfo.CreatedAt > TimeSpan.FromDays(7))
{
Log.Information("Deleting stale update backup from {Date}", backupInfo.CreatedAt);
UpdateBackupService.DeleteBackup();
}
else
{
Log.Information("Post-update: backup of v{OldVersion} available for rollback",
backupInfo?.Version ?? "unknown");
UpdateBackupService.IsPostUpdate = true;
}
}
// == Windows: clean up .old executable left by rollback restore ===========
if (OperatingSystem.IsWindows())
{
var currentExe = Environment.ProcessPath;
if (!string.IsNullOrEmpty(currentExe))
{
var oldExe = currentExe + ".old";
if (File.Exists(oldExe))
{
try { File.Delete(oldExe); }
catch { /* locked or permission issue — will be cleaned next launch */ }
}
}
}
try
{
var config = ConfigManager.Load();