From 3ea99f699b0f1e1ed136eb19c12a2dafa8ec8678 Mon Sep 17 00:00:00 2001 From: lcensies Date: Thu, 14 May 2026 14:07:48 +0300 Subject: [PATCH] fix(dotenv): encode []string as CSV instead of Go bracket notation --- internal/encoding/dotenv/codec.go | 12 +++++++++++- internal/encoding/dotenv/codec_test.go | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/internal/encoding/dotenv/codec.go b/internal/encoding/dotenv/codec.go index d4571672b..35eccd155 100644 --- a/internal/encoding/dotenv/codec.go +++ b/internal/encoding/dotenv/codec.go @@ -32,7 +32,17 @@ func (Codec) Encode(v map[string]any) ([]byte, error) { var buf bytes.Buffer for _, key := range keys { - _, err := buf.WriteString(fmt.Sprintf("%v=%v\n", strings.ToUpper(key), flattened[key])) + var valStr string + switch v := flattened[key].(type) { + case []string: + // Encode string slices as comma-separated values. + // Using fmt's %v would produce "[a b]" which gotenv reads back + // as a single string instead of a slice. + valStr = strings.Join(v, ",") + default: + valStr = fmt.Sprintf("%v", v) + } + _, err := buf.WriteString(fmt.Sprintf("%v=%v\n", strings.ToUpper(key), valStr)) if err != nil { return nil, err } diff --git a/internal/encoding/dotenv/codec_test.go b/internal/encoding/dotenv/codec_test.go index ac2257b79..417fc29ad 100644 --- a/internal/encoding/dotenv/codec_test.go +++ b/internal/encoding/dotenv/codec_test.go @@ -53,3 +53,22 @@ func TestCodec_Decode(t *testing.T) { t.Logf("decoding failed as expected: %s", err) }) } + +// TestCodec_Encode_StringSlice verifies that []string values are encoded as +// comma-separated values rather than Go's default bracket notation "[a b]". +// +// dotenv has no array type, so the de-facto convention is CSV (VAL=a,b,c). +// Viper's defaultDecoderConfig uses stringToWeakSliceHookFunc(",") which +// reconstructs []string from a comma-separated string during Unmarshal, +// completing the round-trip. +func TestCodec_Encode_StringSlice(t *testing.T) { + codec := Codec{} + + b, err := codec.Encode(map[string]any{ + "HOSTS": []string{"host1:10101", "host2:10101"}, + }) + require.NoError(t, err) + + // Must be comma-separated, not bracket notation. + assert.Equal(t, "HOSTS=host1:10101,host2:10101\n", string(b)) +}