fix(installer): harden DownloadAndExtractStep per review
This commit is contained in:
@@ -17,6 +17,9 @@ public sealed class DownloadAndExtractStep : IInstallStep
|
|||||||
|
|
||||||
public async Task<StepResult> ExecuteAsync(InstallContext ctx, IProgress<string> progress, CancellationToken ct)
|
public async Task<StepResult> ExecuteAsync(InstallContext ctx, IProgress<string> progress, CancellationToken ct)
|
||||||
{
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(ctx.InstallDirectory))
|
||||||
|
return StepResult.Fail("Install directory is not set.");
|
||||||
|
|
||||||
progress.Report("Fetching latest release metadata...");
|
progress.Report("Fetching latest release metadata...");
|
||||||
var release = await _releases.GetLatestReleaseAsync(ct);
|
var release = await _releases.GetLatestReleaseAsync(ct);
|
||||||
if (release is null)
|
if (release is null)
|
||||||
@@ -24,7 +27,7 @@ public sealed class DownloadAndExtractStep : IInstallStep
|
|||||||
|
|
||||||
var zipAsset = release.Assets.FirstOrDefault(a =>
|
var zipAsset = release.Assets.FirstOrDefault(a =>
|
||||||
a.Name.StartsWith("ClaudeDo-", StringComparison.OrdinalIgnoreCase) &&
|
a.Name.StartsWith("ClaudeDo-", StringComparison.OrdinalIgnoreCase) &&
|
||||||
a.Name.EndsWith(".zip", StringComparison.OrdinalIgnoreCase));
|
a.Name.EndsWith("-win-x64.zip", StringComparison.OrdinalIgnoreCase));
|
||||||
var checksumAsset = release.Assets.FirstOrDefault(a =>
|
var checksumAsset = release.Assets.FirstOrDefault(a =>
|
||||||
a.Name.Equals("checksums.txt", StringComparison.OrdinalIgnoreCase));
|
a.Name.Equals("checksums.txt", StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
@@ -51,7 +54,7 @@ public sealed class DownloadAndExtractStep : IInstallStep
|
|||||||
new Progress<long>(_ => { }), ct);
|
new Progress<long>(_ => { }), ct);
|
||||||
|
|
||||||
progress.Report("Verifying checksum...");
|
progress.Report("Verifying checksum...");
|
||||||
var map = ChecksumVerifier.ParseChecksumsFile(File.ReadAllText(checksumPath));
|
var map = ChecksumVerifier.ParseChecksumsFile(await File.ReadAllTextAsync(checksumPath, ct));
|
||||||
if (!map.TryGetValue(zipAsset.Name, out var expectedHash))
|
if (!map.TryGetValue(zipAsset.Name, out var expectedHash))
|
||||||
return StepResult.Fail($"No checksum entry for {zipAsset.Name} in checksums.txt.");
|
return StepResult.Fail($"No checksum entry for {zipAsset.Name} in checksums.txt.");
|
||||||
if (!ChecksumVerifier.Verify(zipPath, expectedHash))
|
if (!ChecksumVerifier.Verify(zipPath, expectedHash))
|
||||||
@@ -66,7 +69,16 @@ public sealed class DownloadAndExtractStep : IInstallStep
|
|||||||
|
|
||||||
progress.Report("Extracting...");
|
progress.Report("Extracting...");
|
||||||
Directory.CreateDirectory(ctx.InstallDirectory);
|
Directory.CreateDirectory(ctx.InstallDirectory);
|
||||||
|
try
|
||||||
|
{
|
||||||
ZipFile.ExtractToDirectory(zipPath, ctx.InstallDirectory, overwriteFiles: true);
|
ZipFile.ExtractToDirectory(zipPath, ctx.InstallDirectory, overwriteFiles: true);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return StepResult.Fail(
|
||||||
|
$"Extraction failed after old binaries were removed: {ex.Message}. " +
|
||||||
|
"Your install directory may be incomplete. Re-run the installer to retry.");
|
||||||
|
}
|
||||||
|
|
||||||
ctx.InstalledVersion = release.TagName.TrimStart('v', 'V');
|
ctx.InstalledVersion = release.TagName.TrimStart('v', 'V');
|
||||||
return StepResult.Ok();
|
return StepResult.Ok();
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ public sealed class DownloadAndExtractStepTests : IDisposable
|
|||||||
Assert.True(result.Success, result.ErrorMessage);
|
Assert.True(result.Success, result.ErrorMessage);
|
||||||
Assert.Equal("hello-app", File.ReadAllText(Path.Combine(_installDir, "app", "a.txt")));
|
Assert.Equal("hello-app", File.ReadAllText(Path.Combine(_installDir, "app", "a.txt")));
|
||||||
Assert.Equal("hello-worker", File.ReadAllText(Path.Combine(_installDir, "worker", "b.txt")));
|
Assert.Equal("hello-worker", File.ReadAllText(Path.Combine(_installDir, "worker", "b.txt")));
|
||||||
|
Assert.Equal("0.1.0", ctx.InstalledVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|||||||
Reference in New Issue
Block a user