Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ public static string ToCamelCase(this string text)
: null;
}

public static bool HasTrailingNewLine(this string? input)
{
return input != null && (input.EndsWith("\n") || input.EndsWith("\r"));
}

public static string EnsureDoubleQuoteIfContainsSpaces(this string text) => EnsureDoubleQuote(text, t => t.Contains(" "));
public static string EnsureDoubleQuote(this string text) => EnsureDoubleQuote(text, t => !t.EndsWith("\"") && !t.StartsWith("\""));
public static string EnsureDoubleQuote(this string text, Predicate<string> shouldQuote) => shouldQuote(text) ? $"\"{text}\"" : text;
Expand Down
45 changes: 25 additions & 20 deletions source/Calamari.Tests/ArgoCD/Helm/HelmValuesEditorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,29 +98,34 @@ public void GenerateVariableDictionary_ReturnsDictionaryOfNodeValuesWithValues()
result.Should().BeEquivalentTo(expected);
}

[Test]
public void UpdateNodeValue_ReturnsModifiedYaml()
[TestCase("\n")]
[TestCase("\r\n")]
public void UpdateNodeValue_ReturnsModifiedYaml(string newLine)
{
const string yamlContent = @"root:
node1: ""node1value""
node2:
node2Nest:
node2nestedValue: ""banana""
node2Child1: ""node2child1value""
node2Child2: 42
";
var yamlContent = """
root:
node1: "node1value"
node2:
node2Nest:
node2nestedValue: "banana"
node2Child1: "node2child1value"
node2Child2: 42

""".ReplaceLineEndings(newLine);

var result = HelmValuesEditor.UpdateNodeValue(yamlContent, "root.node1", "awesome new value");

const string expected = @"root:
node1: ""awesome new value""
node2:
node2Nest:
node2nestedValue: ""banana""
node2Child1: ""node2child1value""
node2Child2: 42
";
//ensure platform-agnostic multiline comparison
result.ReplaceLineEndings().Should().Be(expected.ReplaceLineEndings());
var expected = """
root:
node1: "awesome new value"
node2:
node2Nest:
node2nestedValue: "banana"
node2Child1: "node2child1value"
node2Child2: 42

""".ReplaceLineEndings(newLine);
result.Should().Be(expected);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using Calamari.ArgoCD;
using Calamari.ArgoCD.Conventions;
using Calamari.ArgoCD.Models;
Expand Down Expand Up @@ -122,13 +121,15 @@ public void StructuredValue_ImageOnNonDefaultRegistry_UpdatesFullRefAndTracksWit
[Test]
public void TwoImagesWithSameTag_OnlyUpdatesConfiguredPath()
{
const string yaml = @"
nginx:
tag: 1.0
redis:
tag: 1.0
";

const string yaml = """

nginx:
tag: 1.0
redis:
tag: 1.0

""";

var replacer = new HelmValuesImageReplaceStepVariables(yaml, DefaultRegistry, log);
var images = new List<ContainerImageReferenceAndHelmReference>
{
Expand All @@ -137,10 +138,86 @@ public void TwoImagesWithSameTag_OnlyUpdatesConfiguredPath()

var result = replacer.UpdateImages(images);

const string expectedYaml = """

nginx:
tag: 1.27.1
redis:
tag: 1.0

""";

using var scope = new AssertionScope();
result.UpdatedImageReferences.Should().BeEquivalentTo(["nginx:1.27.1"]);
result.UpdatedContents.Should().Contain($"nginx:{Environment.NewLine} tag: 1.27.1");
result.UpdatedContents.Should().Contain($"redis:{Environment.NewLine} tag: 1.0");
result.UpdatedContents.ReplaceLineEndings("\n").Should().Be(expectedYaml.ReplaceLineEndings("\n"));
}

// The endings are forced with ReplaceLineEndings rather than inherited from the literal:
// .gitattributes checks .cs files out with native endings, so an inherited ending always matches
// Environment.NewLine and the assertion cannot distinguish "preserved the input's endings" from
// "used the agent's". The customer's case was an LF file on a Windows agent.
[TestCase("\n")]
[TestCase("\r\n")]
public void UpdatedYaml_PreservesTheInputLineEndings(string newLine)
{
var yaml = """

nginx:
tag: 1.0
redis:
tag: 1.0

""".ReplaceLineEndings(newLine);

var replacer = new HelmValuesImageReplaceStepVariables(yaml, DefaultRegistry, log);
var images = new List<ContainerImageReferenceAndHelmReference>
{
new(ContainerImageReference.FromReferenceString("nginx:1.27.1", DefaultRegistry), "nginx.tag")
};

var result = replacer.UpdateImages(images);

var expectedYaml = """

nginx:
tag: 1.27.1
redis:
tag: 1.0

""".ReplaceLineEndings(newLine);

result.UpdatedContents.Should().Be(expectedYaml);
}

[TestCase("\n")]
[TestCase("\r\n")]
public void UpdatedYaml_WithoutATrailingNewline_DoesNotAddOne(string newLine)
{
var yaml = """

nginx:
tag: 1.0
redis:
tag: 1.0
""".ReplaceLineEndings(newLine);

var replacer = new HelmValuesImageReplaceStepVariables(yaml, DefaultRegistry, log);
var images = new List<ContainerImageReferenceAndHelmReference>
{
new(ContainerImageReference.FromReferenceString("nginx:1.27.1", DefaultRegistry), "nginx.tag")
};

var result = replacer.UpdateImages(images);

var expectedYaml = """

nginx:
tag: 1.27.1
redis:
tag: 1.0
""".ReplaceLineEndings(newLine);

result.UpdatedContents.Should().Be(expectedYaml);
}

[Test]
Expand Down
Loading