Files
lincube 563f12caa1 Add install checkpoint/resume and DDSS workflows
Introduce install checkpoint support and resume logic for updates, plus related locking and validation. Adds InstallCheckpoint model, AppJsonContext serialization, and UpdatePaths helpers for deployment lock, apply-in-progress lock and install-checkpoint path. UpdateEngineService gains checkpoint load/save/delete, incoming-state validation, resume logic for PLONDS and legacy updates, apply lock handling, and safer cleanup; ApplyPendingPlondsUpdateAsync and ApplyPendingUpdate flow updated accordingly. Add DeploymentLock contract and extend UpdateState with pause/resume/cancel helpers. Tests updated to cover stale/valid checkpoint resume and legacy/PLONDS flows. CI: enhance ddss-publish to detect release channel, validate S3 assets, prepare and atomically publish channel pointer; add ddss-rollback workflow to publish rollbacks; adjust plonds-build concurrency and release events.
2026-05-12 08:35:48 +08:00

84 lines
3.4 KiB
C#

namespace LanMountainDesktop.Shared.Contracts.Update;
public static class UpdatePaths
{
private const string LauncherDirectoryName = ".Launcher";
private const string UpdateDirectoryName = "update";
private const string IncomingDirectoryName = "incoming";
private const string ObjectsDirectoryName = "objects";
private const string SnapshotsDirectoryName = "snapshots";
public static string ResolveLauncherRoot(string appBaseDirectory)
{
var trimmed = appBaseDirectory.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
var parent = Path.GetDirectoryName(trimmed);
return string.IsNullOrWhiteSpace(parent) ? appBaseDirectory : parent;
}
public static string GetLauncherDataRoot(string launcherRoot)
{
return Path.Combine(launcherRoot, LauncherDirectoryName);
}
public static string GetIncomingDirectory(string launcherRoot)
{
return Path.Combine(launcherRoot, LauncherDirectoryName, UpdateDirectoryName, IncomingDirectoryName);
}
public static string GetObjectsDirectory(string launcherRoot)
{
return Path.Combine(GetIncomingDirectory(launcherRoot), ObjectsDirectoryName);
}
public static string GetSnapshotsDirectory(string launcherRoot)
{
return Path.Combine(launcherRoot, LauncherDirectoryName, SnapshotsDirectoryName);
}
public static string GetDownloadMarkerPath(string launcherRoot)
{
return Path.Combine(GetIncomingDirectory(launcherRoot), ".download-complete");
}
public static string GetPlondsFileMapName() => "plonds-filemap.json";
public static string GetPlondsSignatureName() => "plonds-filemap.sig";
public static string GetPlondsUpdateMetadataName() => "plonds-update.json";
public static string GetLegacyFileMapName() => "files.json";
public static string GetLegacySignatureName() => "files.json.sig";
public static string GetLegacyArchiveName() => "update.zip";
public static string GetPublicKeyFileName() => "public-key.pem";
public static string GetPlondsFileMapPath(string launcherRoot)
=> Path.Combine(GetIncomingDirectory(launcherRoot), GetPlondsFileMapName());
public static string GetPlondsSignaturePath(string launcherRoot)
=> Path.Combine(GetIncomingDirectory(launcherRoot), GetPlondsSignatureName());
public static string GetDeploymentLockName() => "deployment.lock";
public static string GetDeploymentLockPath(string launcherRoot)
=> Path.Combine(GetIncomingDirectory(launcherRoot), GetDeploymentLockName());
public static string GetApplyInProgressLockName() => "apply-in-progress.lock";
public static string GetApplyInProgressLockPath(string launcherRoot)
=> Path.Combine(GetIncomingDirectory(launcherRoot), GetApplyInProgressLockName());
public static string GetInstallCheckpointName() => "install-checkpoint.json";
public static string GetInstallCheckpointPath(string launcherRoot)
=> Path.Combine(GetIncomingDirectory(launcherRoot), GetInstallCheckpointName());
public static string GetDownloadMarkerContent(string manifestSha256, string targetVersion, int objectCount)
{
return $$"""
{
"manifestSha256": "{{manifestSha256}}",
"targetVersion": "{{targetVersion}}",
"objectCount": {{objectCount}},
"completedAt": "{{DateTimeOffset.UtcNow:O}}"
}
""";
}
}