Skip to content

Commit

Permalink
fix!: hide struct binding behind a feature flag
Browse files Browse the repository at this point in the history
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
  • Loading branch information
sagikazarmark committed Dec 18, 2023
1 parent 9154b90 commit ab3a50c
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 14 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: '1.21'
go-version: "1.21"

- name: Build
run: go build .
Expand All @@ -44,8 +44,8 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
go: ['1.19', '1.20', '1.21']
tags: ['', 'finder']
go: ["1.19", "1.20", "1.21"]
tags: ["", "finder", "viper_bind_struct"]

steps:
- name: Checkout repository
Expand Down Expand Up @@ -75,7 +75,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: '1.21'
go-version: "1.21"

- name: Lint
uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc # v3.7.0
Expand Down
5 changes: 5 additions & 0 deletions internal/features/bind_struct.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//go:build viper_bind_struct

package features

const BindStruct = true
5 changes: 5 additions & 0 deletions internal/features/bind_struct_default.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//go:build !viper_bind_struct

package features

const BindStruct = false
33 changes: 23 additions & 10 deletions viper.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import (
"github.com/spf13/viper/internal/encoding/json"
"github.com/spf13/viper/internal/encoding/toml"
"github.com/spf13/viper/internal/encoding/yaml"
"github.com/spf13/viper/internal/features"
)

// ConfigMarshalError happens when failing to marshal the configuration.
Expand Down Expand Up @@ -1114,14 +1115,20 @@ func Unmarshal(rawVal any, opts ...DecoderConfigOption) error {
}

func (v *Viper) Unmarshal(rawVal any, opts ...DecoderConfigOption) error {
// TODO: make this optional?
structKeys, err := v.decodeStructKeys(rawVal, opts...)
if err != nil {
return err
keys := v.AllKeys()

if features.BindStruct {
// TODO: make this optional?
structKeys, err := v.decodeStructKeys(rawVal, opts...)
if err != nil {
return err
}

keys = append(keys, structKeys...)
}

// TODO: struct keys should be enough?
return decode(v.getSettings(append(v.AllKeys(), structKeys...)), defaultDecoderConfig(rawVal, opts...))
return decode(v.getSettings(keys), defaultDecoderConfig(rawVal, opts...))
}

func (v *Viper) decodeStructKeys(input any, opts ...DecoderConfigOption) ([]string, error) {
Expand Down Expand Up @@ -1179,14 +1186,20 @@ func (v *Viper) UnmarshalExact(rawVal any, opts ...DecoderConfigOption) error {
config := defaultDecoderConfig(rawVal, opts...)
config.ErrorUnused = true

// TODO: make this optional?
structKeys, err := v.decodeStructKeys(rawVal, opts...)
if err != nil {
return err
keys := v.AllKeys()

if features.BindStruct {
// TODO: make this optional?
structKeys, err := v.decodeStructKeys(rawVal, opts...)
if err != nil {
return err
}

keys = append(keys, structKeys...)
}

// TODO: struct keys should be enough?
return decode(v.getSettings(append(v.AllKeys(), structKeys...)), config)
return decode(v.getSettings(keys), config)
}

// BindPFlags binds a full flag set to the configuration, using each flag's long
Expand Down
5 changes: 5 additions & 0 deletions viper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/spf13/viper/internal/features"
"github.com/spf13/viper/internal/testutil"
)

Expand Down Expand Up @@ -956,6 +957,10 @@ func TestUnmarshalWithDecoderOptions(t *testing.T) {
}

func TestUnmarshalWithAutomaticEnv(t *testing.T) {
if !features.BindStruct {
t.Skip("binding struct is not enabled")
}

t.Setenv("PORT", "1313")
t.Setenv("NAME", "Steve")
t.Setenv("DURATION", "1s1ms")
Expand Down

0 comments on commit ab3a50c

Please sign in to comment.