@ -22,6 +22,8 @@ import (
"fmt"
"io"
"log/slog"
"os"
"path/filepath"
"strings"
"testing"
"time"
@ -2292,3 +2294,153 @@ func TestInteractWithServer(t *testing.T) {
assert . False ( t , interactWithServer ( DryRunClient ) )
assert . True ( t , interactWithServer ( DryRunServer ) )
}
func TestTrimLeadingDocumentSeparator ( t * testing . T ) {
for _ , tc := range [ ] struct {
name string
data string
expected string
} {
{
name : "leading separator is removed" ,
data : "---\napiVersion: v1\n" ,
expected : "apiVersion: v1\n" ,
} ,
{
name : "content without a separator is left alone" ,
data : "apiVersion: v1\n" ,
expected : "apiVersion: v1\n" ,
} ,
{
name : "only the leading separator is removed" ,
data : "---\napiVersion: v1\n---\napiVersion: v2\n" ,
expected : "apiVersion: v1\n---\napiVersion: v2\n" ,
} ,
{
name : "separator following content is left alone" ,
data : "apiVersion: v1\n---\napiVersion: v2\n" ,
expected : "apiVersion: v1\n---\napiVersion: v2\n" ,
} ,
{
name : "comments and blank lines preceding the separator are kept" ,
data : "# a comment\n\n---\napiVersion: v1\n" ,
expected : "# a comment\n\napiVersion: v1\n" ,
} ,
{
name : "trailing whitespace on the separator is tolerated" ,
data : "--- \napiVersion: v1\n" ,
expected : "apiVersion: v1\n" ,
} ,
{
name : "carriage returns are tolerated" ,
data : "---\r\napiVersion: v1\r\n" ,
expected : "apiVersion: v1\r\n" ,
} ,
{
name : "separator without a trailing newline" ,
data : "---" ,
expected : "" ,
} ,
{
name : "indented separator is not a document separator" ,
data : " ---\napiVersion: v1\n" ,
expected : " ---\napiVersion: v1\n" ,
} ,
{
name : "four dashes are not a document separator" ,
data : "----\napiVersion: v1\n" ,
expected : "----\napiVersion: v1\n" ,
} ,
{
name : "separator terminating a YAML directive is left alone" ,
data : "%YAML 1.2\n---\napiVersion: v1\n" ,
expected : "%YAML 1.2\n---\napiVersion: v1\n" ,
} ,
{
name : "empty data" ,
data : "" ,
expected : "" ,
} ,
} {
t . Run ( tc . name , func ( t * testing . T ) {
assert . Equal ( t , tc . expected , trimLeadingDocumentSeparator ( tc . data ) )
} )
}
}
const crdManifest = ` apiVersion : apiextensions . k8s . io / v1
kind : CustomResourceDefinition
metadata :
name : testcrds . testcrdgroups . example . com
`
// Helm prefixes every rendered file with its own document separator, so a CRD
// file that already carries one must not produce a second, empty document.
// See https://github.com/helm/helm/issues/12953.
func TestRenderResources_IncludeCRDs ( t * testing . T ) {
for _ , tc := range [ ] struct {
name string
crdData string
expected string
} {
{
name : "CRD without a document separator" ,
crdData : crdManifest ,
expected : "---\n# Source: hello/crds/crd.yaml\n" + crdManifest + "\n" ,
} ,
{
name : "CRD with a leading document separator" ,
crdData : "---\n" + crdManifest ,
expected : "---\n# Source: hello/crds/crd.yaml\n" + crdManifest + "\n" ,
} ,
{
name : "CRD with a comment before the document separator" ,
crdData : "# generated by controller-gen\n---\n" + crdManifest ,
expected : "---\n# Source: hello/crds/crd.yaml\n# generated by controller-gen\n" + crdManifest + "\n" ,
} ,
{
name : "CRD holding several documents" ,
crdData : "---\n" + crdManifest + "---\n" + crdManifest ,
expected : "---\n# Source: hello/crds/crd.yaml\n" + crdManifest + "---\n" + crdManifest + "\n" ,
} ,
} {
t . Run ( tc . name , func ( t * testing . T ) {
cfg := actionConfigFixture ( t )
ch := buildChartWithTemplates ( nil , withFile ( common . File {
Name : "crds/crd.yaml" ,
ModTime : time . Now ( ) ,
Data : [ ] byte ( tc . crdData ) ,
} ) )
_ , buf , _ , err := cfg . renderResources (
t . Context ( ) , ch , map [ string ] any { } , "test-release" , "" , false , false , true ,
nil , false , false , false , PostRenderStrategyCombined ,
)
require . NoError ( t , err )
assert . Equal ( t , tc . expected , buf . String ( ) )
} )
}
}
// The --output-dir path writes CRDs through writeToFile, which prefixes each
// file with a document separator of its own.
func TestRenderResources_IncludeCRDs_OutputDir ( t * testing . T ) {
cfg := actionConfigFixture ( t )
ch := buildChartWithTemplates ( nil , withFile ( common . File {
Name : "crds/crd.yaml" ,
ModTime : time . Now ( ) ,
Data : [ ] byte ( "---\n" + crdManifest ) ,
} ) )
outputDir := t . TempDir ( )
_ , _ , _ , err := cfg . renderResources (
t . Context ( ) , ch , map [ string ] any { } , "test-release" , outputDir , false , false , true ,
nil , false , false , false , PostRenderStrategyCombined ,
)
require . NoError ( t , err )
written , err := os . ReadFile ( filepath . Join ( outputDir , "hello" , "crds" , "crd.yaml" ) )
require . NoError ( t , err )
assert . Equal ( t , "---\n# Source: hello/crds/crd.yaml\n" + crdManifest + "\n" , string ( written ) )
}