up
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
devportal-offline / build-offline (push) Has been cancelled
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
devportal-offline / build-offline (push) Has been cancelled
This commit is contained in:
@@ -43,22 +43,39 @@ public sealed class BundleIngestionStepExecutor : IPackRunStepExecutor
|
||||
}
|
||||
|
||||
var checksum = GetString(parameters, "checksum") ?? GetString(parameters, "checksumSha256");
|
||||
if (!string.IsNullOrWhiteSpace(checksum))
|
||||
if (string.IsNullOrWhiteSpace(checksum))
|
||||
{
|
||||
var actual = ComputeSha256(sourcePath);
|
||||
if (!checksum.Equals(actual, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return Task.FromResult(PackRunStepExecutionResult.Failure($"Checksum mismatch: expected {checksum}, actual {actual}."));
|
||||
}
|
||||
return Task.FromResult(PackRunStepExecutionResult.Failure("Checksum is required for bundle ingestion."));
|
||||
}
|
||||
|
||||
var actual = ComputeSha256(sourcePath);
|
||||
if (!checksum.Equals(actual, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return Task.FromResult(PackRunStepExecutionResult.Failure($"Checksum mismatch: expected {checksum}, actual {actual}."));
|
||||
}
|
||||
|
||||
var deterministicDir = Path.Combine(stagingRoot, checksum.ToLowerInvariant());
|
||||
var destination = GetString(parameters, "destinationPath")
|
||||
?? Path.Combine(stagingRoot, Path.GetFileName(sourcePath));
|
||||
?? Path.Combine(deterministicDir, Path.GetFileName(sourcePath));
|
||||
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(destination)!);
|
||||
File.Copy(sourcePath, destination, overwrite: true);
|
||||
|
||||
// Persist deterministic metadata for downstream evidence
|
||||
var metadataPath = Path.Combine(deterministicDir, "metadata.json");
|
||||
var metadata = new
|
||||
{
|
||||
source = Path.GetFullPath(sourcePath),
|
||||
checksumSha256 = checksum.ToLowerInvariant(),
|
||||
stagedPath = Path.GetFullPath(destination)
|
||||
};
|
||||
var json = JsonSerializer.Serialize(metadata, new JsonSerializerOptions(JsonSerializerDefaults.Web)
|
||||
{
|
||||
WriteIndented = false
|
||||
});
|
||||
File.WriteAllText(metadataPath, json);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ public sealed class BundleIngestionStepExecutorTests
|
||||
using var temp = new TempDirectory();
|
||||
var source = Path.Combine(temp.Path, "bundle.tgz");
|
||||
await File.WriteAllTextAsync(source, "bundle-data");
|
||||
var checksum = "3e25960a79dbc69b674cd4ec67a72c62b3aa32b1d4d216177a5ffcc6f46673b5"; // sha256 of "bundle-data"
|
||||
|
||||
var options = Options.Create(new PackRunWorkerOptions { ArtifactsPath = temp.Path });
|
||||
var executor = new BundleIngestionStepExecutor(options, NullLogger<BundleIngestionStepExecutor>.Instance);
|
||||
@@ -22,15 +23,20 @@ public sealed class BundleIngestionStepExecutorTests
|
||||
var step = CreateStep("builtin:bundle.ingest", new Dictionary<string, TaskPackPlanParameterValue>
|
||||
{
|
||||
["path"] = Value(source),
|
||||
["checksum"] = Value("3e25960a79dbc69b674cd4ec67a72c62b3aa32b1d4d216177a5ffcc6f46673b5") // sha256 of "bundle-data"
|
||||
["checksum"] = Value(checksum)
|
||||
});
|
||||
|
||||
var result = await executor.ExecuteAsync(step, step.Parameters, CancellationToken.None);
|
||||
|
||||
Assert.True(result.Succeeded);
|
||||
var staged = Path.Combine(temp.Path, "bundles", "bundle.tgz");
|
||||
var staged = Path.Combine(temp.Path, "bundles", checksum, "bundle.tgz");
|
||||
Assert.True(File.Exists(staged));
|
||||
Assert.Equal(await File.ReadAllBytesAsync(source), await File.ReadAllBytesAsync(staged));
|
||||
|
||||
var metadataPath = Path.Combine(temp.Path, "bundles", checksum, "metadata.json");
|
||||
Assert.True(File.Exists(metadataPath));
|
||||
var metadata = await File.ReadAllTextAsync(metadataPath);
|
||||
Assert.Contains(checksum, metadata, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -55,6 +61,27 @@ public sealed class BundleIngestionStepExecutorTests
|
||||
Assert.Contains("Checksum mismatch", result.Error, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExecuteAsync_MissingChecksum_Fails()
|
||||
{
|
||||
using var temp = new TempDirectory();
|
||||
var source = Path.Combine(temp.Path, "bundle.tgz");
|
||||
await File.WriteAllTextAsync(source, "bundle-data");
|
||||
|
||||
var options = Options.Create(new PackRunWorkerOptions { ArtifactsPath = temp.Path });
|
||||
var executor = new BundleIngestionStepExecutor(options, NullLogger<BundleIngestionStepExecutor>.Instance);
|
||||
|
||||
var step = CreateStep("builtin:bundle.ingest", new Dictionary<string, TaskPackPlanParameterValue>
|
||||
{
|
||||
["path"] = Value(source)
|
||||
});
|
||||
|
||||
var result = await executor.ExecuteAsync(step, step.Parameters, CancellationToken.None);
|
||||
|
||||
Assert.False(result.Succeeded);
|
||||
Assert.Contains("Checksum is required", result.Error, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExecuteAsync_UnknownUses_NoOpSuccess()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user