Repository: helmfile/helmfile (Go)

Issue:
helmfile fails if base contains an empty array
### Operating system

alpine:3.18

### Helmfile Version

0.158.1

### Helm Version

3.13.2

### Bug description

If a file listed under "bases:" only contains an empty element, like `values: []` validation will fail.

The reason for this is this part of the code: https://github.com/helmfile/helmfile/blob/main/pkg/policy/checker.go#L16 as the used regex only matches, if the key is followed by a `:` and space characters.

As `key: []` is valid YAML for an empty array, I think it should pass the checker.

Regards and thanks in advance,
Jan

### Example helmfile.yaml

---
bases:
  - ./bases/environments/global-values.yaml
  - ./bases/environments/{{ .Environment.Name }}.yaml


### Error message you've seen (if any)

`in ./helmfile.yaml: no top-level config keys are found in bases/environments/global-values.yaml`

### Steps to reproduce

https://github.com/helmfile/helmfile/blob/main/pkg/policy/checker.go#L16

### Working Helmfile Version

0.155.1

### Relevant discussion

_No response_


Discussion:
@gunzl1ng3r PR is welcome.



Patch:
diff --git a/pkg/policy/checker.go b/pkg/policy/checker.go
index 2023ecea9..71e09761e 100644
--- a/pkg/policy/checker.go
+++ b/pkg/policy/checker.go
@@ -13,7 +13,7 @@ import (
 
 var (
 	EnvironmentsAndReleasesWithinSameYamlPartErr = errors.New("environments and releases cannot be defined within the same YAML part. Use --- to extract the environments into a dedicated part")
-	topConfigKeysRegex                           = regexp.MustCompile(`^[a-zA-Z]+: *$`)
+	topConfigKeysRegex                           = regexp.MustCompile(`^[a-zA-Z]+:`)
 	separatorRegex                               = regexp.MustCompile(`^--- *$`)
 	topkeysPriority                              = map[string]int{
 		"bases":        0,


Test patch:
diff --git a/pkg/policy/checker_test.go b/pkg/policy/checker_test.go
index 3bdbb6a19..45d3a5587 100644
--- a/pkg/policy/checker_test.go
+++ b/pkg/policy/checker_test.go
@@ -19,7 +19,7 @@ func TestForbidEnvironmentsWithReleases(t *testing.T) {
 	}{
 		{
 			name:        "no error when only releases",
-			filePath:    "helmfile.yaml.gotmpl",
+			filePath:    "helmfile.yaml",
 			content:     []byte("releases:\n"),
 			v1mode:      false,
 			expectedErr: false,
@@ -27,7 +27,7 @@ func TestForbidEnvironmentsWithReleases(t *testing.T) {
 		},
 		{
 			name:        "no error when only environments",
-			filePath:    "helmfile.yaml.gotmpl",
+			filePath:    "helmfile.yaml",
 			content:     []byte("environments:\n"),
 			v1mode:      false,
 			expectedErr: false,
@@ -35,7 +35,7 @@ func TestForbidEnvironmentsWithReleases(t *testing.T) {
 		},
 		{
 			name:        "no error when has --- between releases and environments",
-			filePath:    "helmfile.yaml.gotmpl",
+			filePath:    "helmfile.yaml",
 			content:     []byte("environments:\n---\nreleases:\n"),
 			v1mode:      false,
 			expectedErr: false,
@@ -43,7 +43,7 @@ func TestForbidEnvironmentsWithReleases(t *testing.T) {
 		},
 		{
 			name:        "no error when has --- between releases and environments, and --- on top of helmfile.yaml.gotmpl",
-			filePath:    "helmfile.yaml.gotmpl",
+			filePath:    "helmfile.yaml",
 			content:     []byte("---\nenvironments:\n---\nreleases:\n"),
 			v1mode:      false,
 			expectedErr: false,
@@ -51,7 +51,7 @@ func TestForbidEnvironmentsWithReleases(t *testing.T) {
 		},
 		{
 			name:        "error when both releases and environments",
-			filePath:    "helmfile.yaml.gotmpl",
+			filePath:    "helmfile.yaml",
 			content:     []byte("environments:\nreleases:\n"),
 			v1mode:      false,
 			expectedErr: true,
@@ -214,6 +214,12 @@ func TestTopKeys(t *testing.T) {
 			hasSeparator:    true,
 			want:            []string{"bases", "---", "releases"},
 		},
+		{
+			name:            "get top keys with empty array",
+			helmfileContent: []byte("bases: []\n---\nreleases: []\n"),
+			hasSeparator:    true,
+			want:            []string{"bases", "---", "releases"},
+		},
 		{
 			name:            "get empty keys",
 			helmfileContent: []byte(""),