Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
5 changes: 5 additions & 0 deletions src/HelmSharp.Action/HelmChartPackager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public static async Task<string> 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";

Expand Down Expand Up @@ -256,12 +257,16 @@ private static async Task<byte[]> 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()
Expand Down
48 changes: 28 additions & 20 deletions tests/HelmSharp.Tests/PackageMetadataValidationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -553,11 +553,12 @@ private async Task<string> CreateChartAsync(string directoryName, string? chartY

private async Task<string> 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"), """
Expand All @@ -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]);
Expand Down Expand Up @@ -688,15 +690,20 @@ private static async Task<List<PackageEntrySnapshot>> 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();
Expand Down Expand Up @@ -738,5 +745,6 @@ private sealed record PackageEntrySnapshot(
string Name,
TarEntryType EntryType,
UnixFileMode Mode,
long Size);
long Size,
string PayloadHex);
}