diff --git a/CHANGELOG.md b/CHANGELOG.md index c29f1a0..509022b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ This project follows semantic versioning once stable releases begin. ### Changed +- Normalized packaged root and nested `Chart.yaml` metadata to Helm-compatible LF payloads on every platform while preserving source chart files (#180). - Documented complete packaging, repository, pull, and dependency workflows in English and Simplified Chinese, with compile-checked examples and explicit OCI/provenance boundaries (#141). - Added dependency repository aliases, local `file://` packaging, and alias-aware update/build handling while preserving Helm-compatible lock identities (#139). - Made dependency builds reproduce exact `Chart.lock` versions, reject missing or stale locks, restore archives, and validate dependency digests without rewriting the lock (#138). diff --git a/src/HelmSharp.Action/HelmChartPackager.cs b/src/HelmSharp.Action/HelmChartPackager.cs index eb27dfa..a179fd5 100644 --- a/src/HelmSharp.Action/HelmChartPackager.cs +++ b/src/HelmSharp.Action/HelmChartPackager.cs @@ -77,6 +77,7 @@ public static async Task PackageAsync( if (version is not null || appVersion is not null) chartYamlContent = HelmYaml.Serialize(metadata); + chartYamlContent = NormalizeChartYamlLineEndings(chartYamlContent); if (!chartYamlContent.EndsWith("\n", StringComparison.Ordinal)) chartYamlContent += "\n"; @@ -256,12 +257,16 @@ private static async Task ReadPackagedFileBytesAsync( return await File.ReadAllBytesAsync(fullPath, cancellationToken); var chartYaml = await File.ReadAllTextAsync(fullPath, Encoding.UTF8, cancellationToken); + chartYaml = NormalizeChartYamlLineEndings(chartYaml); if (!chartYaml.EndsWith("\n", StringComparison.Ordinal)) chartYaml += "\n"; return Encoding.UTF8.GetBytes(chartYaml); } + private static string NormalizeChartYamlLineEndings(string content) + => content.Replace("\r\n", "\n", StringComparison.Ordinal).Replace('\r', '\n'); + private static bool PathsEqual(string left, string right) { var comparison = OperatingSystem.IsWindows() diff --git a/tests/HelmSharp.Tests/PackageMetadataValidationTests.cs b/tests/HelmSharp.Tests/PackageMetadataValidationTests.cs index c98859f..49eff73 100644 --- a/tests/HelmSharp.Tests/PackageMetadataValidationTests.cs +++ b/tests/HelmSharp.Tests/PackageMetadataValidationTests.cs @@ -460,12 +460,12 @@ public async Task PackageAsync_HelmIgnoreEntriesMatchHelmPackage() [HelmCliFact] public async Task PackageAsync_VersionAndAppVersionOverrideMatchesHelmPackagedChartYaml() { - var sourceChartYaml = """ - apiVersion: v2 - name: appver-test - version: 1.2.3 - appVersion: 1.16 - """; + var sourceChartYaml = string.Join("\r\n", [ + "apiVersion: v2", + "name: appver-test", + "version: 1.2.3", + "appVersion: 1.16" + ]); var sharpChartDir = await CreateChartAsync("sharp-appver-test", sourceChartYaml); var helmChartDir = await CreateChartAsync("helm-appver-test", sourceChartYaml); var sharpDestination = Path.Combine(_tempDir, "sharp-appver-output"); @@ -553,11 +553,12 @@ private async Task CreateChartAsync(string directoryName, string? chartY private async Task CreateArchiveLayoutChartAsync(string directoryName) { - var chartDir = await CreateChartAsync(directoryName, """ - apiVersion: v2 - name: archive-layout - version: 1.2.3 - """); + var chartYaml = string.Join("\r\n", [ + "apiVersion: v2", + "name: archive-layout", + "version: 1.2.3" + ]); + var chartDir = await CreateChartAsync(directoryName, chartYaml); await WriteTextAsync(Path.Combine(chartDir, "values.yaml"), "replicaCount: 1\n"); await WriteTextAsync(Path.Combine(chartDir, "templates", "deployment.yaml"), "kind: Deployment\n"); await WriteTextAsync(Path.Combine(chartDir, "crds", "widgets.yaml"), """ @@ -566,11 +567,12 @@ await WriteTextAsync(Path.Combine(chartDir, "crds", "widgets.yaml"), """ metadata: name: widgets.example.com """); - await WriteTextAsync(Path.Combine(chartDir, "charts", "child", "Chart.yaml"), """ - apiVersion: v2 - name: child - version: 0.1.0 - """); + var childChartYaml = string.Join("\r\n", [ + "apiVersion: v2", + "name: child", + "version: 0.1.0" + ]); + await WriteTextAsync(Path.Combine(chartDir, "charts", "child", "Chart.yaml"), childChartYaml); await WriteTextAsync(Path.Combine(chartDir, "charts", "child", "values.yaml"), "enabled: true\n"); await WriteTextAsync(Path.Combine(chartDir, "README.md"), "# Archive layout\n"); await WriteBytesAsync(Path.Combine(chartDir, "files", "payload.bin"), [0, 1, 2, 127, 128, 255]); @@ -688,15 +690,20 @@ private static async Task> ReadPackageEntriesAsync(st TarEntry? entry; while ((entry = reader.GetNextEntry()) is not null) { - var size = 0L; + byte[] payload = []; if (entry.DataStream is not null) { using var memory = new MemoryStream(); await entry.DataStream.CopyToAsync(memory); - size = memory.Length; + payload = memory.ToArray(); } - entries.Add(new PackageEntrySnapshot(entry.Name, entry.EntryType, entry.Mode, size)); + entries.Add(new PackageEntrySnapshot( + entry.Name, + entry.EntryType, + entry.Mode, + payload.LongLength, + Convert.ToHexString(payload))); } return entries.OrderBy(entry => entry.Name, StringComparer.Ordinal).ToList(); @@ -738,5 +745,6 @@ private sealed record PackageEntrySnapshot( string Name, TarEntryType EntryType, UnixFileMode Mode, - long Size); + long Size, + string PayloadHex); }