#795: Updates aus der WebUI ueber den Instanzmanager

Das Update-Angebot gab es nur im Desktop-Fenster. Der Manager prueft jetzt
selbst und spielt ein: erst alle Instanzen geordnet anhalten, dann
- ohne systemd: update-agent mit --wait-for-pid und --restart,
- unter systemd: clawddotnet-update.service anstossen (Vorlage unter
  deploy/systemd), damit der agent keinen zweiten Manager neben dem
  Dienst startet (DC SETUP_INTEGRATION_GUIDE 4A).
Fehlt die Unit, wird nichts angehalten; scheitert die Uebergabe, kommen
die Instanzen wieder hoch. Anleitung in InstanceSetupGuide Abschnitt 8.

Nebenbei: Sprachpaket wird vor dem Kopf geladen (rohe Schluessel im Kopf).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-10-02 20:15:18 +02:00
co-authored by Claude Opus 5.5
parent 4e41fc12d7
commit d4b7f34200
12 changed files with 630 additions and 12 deletions
+11 -3
View File
@@ -102,7 +102,13 @@ internal static class Program
backups.Start();
await using var web = ManagerWebHost.TryStart(manager, backups, loggerFactory);
// #795: Updates from the web interface. After a hand-over to the update agent the
// manager ends like on SIGTERM - the agent waits for exactly that.
// Three parts, as releases are named ("0.1.18", not the assembly's "0.1.18.0").
var updates = new ManagerUpdates(
manager, string.Join('.', Version().Split('.').Take(3)), loggerFactory.CreateLogger("ClawdDotNet.Manager.Update"));
await using var web = ManagerWebHost.TryStart(manager, backups, loggerFactory, updates);
if (web is null)
{
@@ -143,7 +149,7 @@ internal static class Program
// gestartet hat; die Datei liest hinterher irgendwer.
logger.LogInformation("Instanzmanager bereit. Weboberfläche: {Url}", web.Url);
await WaitForShutdownAsync(logger);
await WaitForShutdownAsync(logger, updates);
logger.LogInformation(
"Instanzmanager wird beendet. Laufende Instanzen laufen weiter.");
@@ -295,7 +301,7 @@ internal static class Program
/// Protokolls geleert. Ein Ende ohne diese Zeilen ist der Zustand aus #529, nur diesmal
/// beim Aufpasser.</para>
/// </summary>
private static async Task WaitForShutdownAsync(ILogger logger)
private static async Task WaitForShutdownAsync(ILogger logger, ManagerUpdates updates)
{
var schluss = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
@@ -305,6 +311,8 @@ internal static class Program
logger.LogInformation("Beendigung angefordert ({Grund}).", grund);
}
updates.ShutdownRequested += () => Beenden("Update");
using var sigterm = PosixSignalRegistration.Create(PosixSignal.SIGTERM, context =>
{
context.Cancel = true;