feat: add support for yaml files
Some checks failed
/ linting (push) Failing after 47s
/ tests (push) Successful in 53s

This commit is contained in:
Bruno Carlin 2025-01-15 15:06:02 +01:00
parent 81dfdacb33
commit 9eccdccc5c
Signed by: bcarlin
GPG key ID: 8E254EA0FFEB9B6D
11 changed files with 51 additions and 2 deletions

View file

@ -4,6 +4,7 @@
- Add support for TOML configuration files
- Add support for HCL configuration files
- Add support for YAML configuration files
- Use stdlib for tests instead of convey
- Public functions now panic when the data to be marshaled or unmarshaled is not
a pointer to a struct. These errors should be caught during deelopment (with

View file

@ -11,6 +11,7 @@ import (
"github.com/hashicorp/hcl/v2/hclsimple"
"github.com/hashicorp/hcl/v2/hclwrite"
"github.com/pelletier/go-toml/v2"
"gopkg.in/yaml.v3"
)
type filetype int
@ -20,6 +21,7 @@ const (
typeJSON
typeTOML
typeHCL
typeYAML
)
// getType returns the type of the config file.
@ -31,6 +33,9 @@ func getType(filename string) filetype {
return typeTOML
case strings.HasSuffix(filename, ".hcl"):
return typeHCL
case strings.HasSuffix(filename, ".yml") ||
strings.HasSuffix(filename, ".yaml"):
return typeYAML
default:
return typeInvalid
}
@ -47,6 +52,8 @@ func unmarshal(filepath string, data []byte, v any) error {
return unmarshalTOML(data, v)
case typeHCL:
return unmarshalHCL(filepath, data, v)
case typeYAML:
return unmarshalYAML(data, v)
default:
return ErrUnsupportedFileType
}
@ -61,6 +68,8 @@ func marshal(ft filetype, v any) ([]byte, error) {
return marshalTOML(v)
case typeHCL:
return marshalHCL(v)
case typeYAML:
return marshalYAML(v)
default:
return nil, ErrUnsupportedFileType
}
@ -123,7 +132,7 @@ func unmarshalHCL(filepath string, data []byte, v any) error {
}
// marshalHCL marshals the given struct to bytes.
func marshalHCL(v any) (b []byte, err error) { //nolint:nonamedreturns // need named return to convert a panic to error
func marshalHCL(v any) ([]byte, error) {
f := hclwrite.NewEmptyFile()
gohcl.EncodeIntoBody(v, f.Body())
@ -145,3 +154,23 @@ func hclFilterDiagnostics(diags hcl.Diagnostics) hcl.Diagnostics {
return nil
}
// unmarshalYAML unmarshals the given data to the given struct.
func unmarshalYAML(data []byte, v any) error {
err := yaml.Unmarshal(data, v)
if err != nil {
return fmt.Errorf("cannot parse config file: %w", err)
}
return nil
}
// marshalYAML marshals the given struct to bytes.
func marshalYAML(v any) ([]byte, error) {
data, err := yaml.Marshal(v)
if err != nil {
return nil, fmt.Errorf("cannot generate config content: %w", err)
}
return data, nil
}

View file

@ -29,6 +29,12 @@ func TestHCLFiles(t *testing.T) {
runTestSuite(t, "hcl")
}
func TestYAMLFiles(t *testing.T) {
t.Parallel()
runTestSuite(t, "yaml")
}
func TestUnknownFiles(t *testing.T) {
t.Parallel()
@ -457,7 +463,7 @@ func testLoadAndUpdateFile(t *testing.T, ext string) {
newContent, err := os.ReadFile(file)
require.NoError(t, err)
assert.Contains(t, string(newContent), "Invariant")
assert.Contains(t, string(newContent), "nvariant")
assert.True(t, updated)
})

3
test_data/full.yaml Normal file
View file

@ -0,0 +1,3 @@
string: default string
invariant: should not change
int: 1

1
test_data/invalid.yaml Normal file
View file

@ -0,0 +1 @@
String = not yaml

1
test_data/part1.yaml Normal file
View file

@ -0,0 +1 @@
string: foo

1
test_data/part2.yaml Normal file
View file

@ -0,0 +1 @@
int: 42

1
test_data/same1.yaml Normal file
View file

@ -0,0 +1 @@
string: foo

1
test_data/same2.yaml Normal file
View file

@ -0,0 +1 @@
string: bar

3
test_data/unknown.yaml Normal file
View file

@ -0,0 +1,3 @@
String: config string
Int: 42
Unknown: "foo"

2
test_data/valid.yaml Normal file
View file

@ -0,0 +1,2 @@
string: config string
int: 42