From 3347e0dd6e76db198ee22d50a1deffb97857044a Mon Sep 17 00:00:00 2001 From: LandonTClipp Date: Tue, 20 Dec 2022 15:03:24 -0600 Subject: [PATCH 1/3] Add ability for mockery to search upwards for config file Mockery will iteratively search higher in the cwd tree for a config file matching `.mockery.yaml` --- cmd/mockery.go | 47 ++++++++++++++++++++++++---------- cmd/mockery_test.go | 38 ++++++++++++++++++++++++++- go.mod | 1 + go.sum | 7 +++++ mocks/pkg/fixtures/Expecter.go | 14 +++++----- 5 files changed, 85 insertions(+), 22 deletions(-) diff --git a/cmd/mockery.go b/cmd/mockery.go index c2941c11..39dac43b 100644 --- a/cmd/mockery.go +++ b/cmd/mockery.go @@ -10,6 +10,7 @@ import ( "strings" "time" + "github.com/chigopher/pathlib" "github.com/mitchellh/go-homedir" "github.com/pkg/errors" "github.com/rs/zerolog" @@ -28,7 +29,7 @@ var ( ) func init() { - cobra.OnInitialize(initConfig) + cobra.OnInitialize(func() { initConfig(nil, nil) }) } func NewRootCmd() *cobra.Command { @@ -103,16 +104,27 @@ func Execute() { } } -func initConfig() { - viper.SetEnvPrefix("mockery") - viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) - viper.AutomaticEnv() +func initConfig(baseSearchPath *pathlib.Path, viperObj *viper.Viper) { + if baseSearchPath == nil { + currentWorkingDir, err := os.Getwd() + if err != nil { + panic(err) + } + baseSearchPath = pathlib.NewPath(currentWorkingDir) + } + if viperObj == nil { + viperObj = viper.GetViper() + } + + viperObj.SetEnvPrefix("mockery") + viperObj.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) + viperObj.AutomaticEnv() if cfgFile != "" { // Use config file from the flag. - viper.SetConfigFile(cfgFile) - } else if viper.IsSet("config") { - viper.SetConfigFile(viper.GetString("config")) + viperObj.SetConfigFile(cfgFile) + } else if viperObj.IsSet("config") { + viperObj.SetConfigFile(viperObj.GetString("config")) } else { // Find home directory. home, err := homedir.Dir() @@ -120,15 +132,20 @@ func initConfig() { log.Fatal().Err(err).Msgf("Failed to find homedir") } - // Search config in home directory with name ".cobra" (without extension). - viper.AddConfigPath(".") - viper.AddConfigPath(home) - viper.SetConfigName(".mockery") + currentDir := baseSearchPath + + for len(currentDir.Parts()) != 1 { + viperObj.AddConfigPath(currentDir.String()) + currentDir = currentDir.Parent() + } + + viperObj.AddConfigPath(home) + viperObj.SetConfigName(".mockery") } // Note we purposely ignore the error. Don't care if we can't find a config file. - if err := viper.ReadInConfig(); err == nil { - fmt.Fprintf(os.Stderr, "Using config file: %s\n", viper.ConfigFileUsed()) + if err := viperObj.ReadInConfig(); err == nil { + fmt.Fprintf(os.Stderr, "Using config file: %s\n", viperObj.ConfigFileUsed()) } } @@ -143,6 +160,7 @@ func GetRootAppFromViper(v *viper.Viper) (*RootApp, error) { if err := v.UnmarshalExact(&r.Config); err != nil { return nil, errors.Wrapf(err, "failed to get config") } + r.Config.Config = v.ConfigFileUsed() return r, nil } @@ -164,6 +182,7 @@ func (r *RootApp) Run() error { } log = log.With().Bool(logging.LogKeyDryRun, r.Config.DryRun).Logger() log.Info().Msgf("Starting mockery") + log.Info().Msgf("Using config: %s", r.Config.Config) ctx := log.WithContext(context.Background()) if r.Config.Version { diff --git a/cmd/mockery_test.go b/cmd/mockery_test.go index ae93c95b..bb2c658f 100644 --- a/cmd/mockery_test.go +++ b/cmd/mockery_test.go @@ -3,8 +3,10 @@ package cmd import ( "fmt" "os" + "strings" "testing" + "github.com/chigopher/pathlib" "github.com/spf13/viper" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -76,7 +78,7 @@ func TestConfigEnvFlags(t *testing.T) { env(t, "EXPORTED", fmt.Sprint(expected.Exported)) env(t, "WITH_EXPECTER", fmt.Sprint(expected.WithExpecter)) - initConfig() + initConfig(nil, nil) app, err := GetRootAppFromViper(viper.GetViper()) require.NoError(t, err) @@ -89,3 +91,37 @@ func env(t *testing.T, key, value string) { t.Cleanup(func() { os.Unsetenv(key) }) os.Setenv(key, value) } + +func Test_initConfig(t *testing.T) { + tests := []struct { + name string + base_path string + configPath string + }{ + { + name: "test config at base directory", + base_path: "1/2/3/4", + configPath: "1/2/3/4/.mockery.yaml", + }, + { + name: "test config at upper directory", + base_path: "1/2/3/4", + configPath: "1/.mockery.yaml", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tmpDir := pathlib.NewPath(t.TempDir()) + baseDir := tmpDir.Join(strings.Split(tt.base_path, "/")...) + require.NoError(t, baseDir.MkdirAll()) + configPath := tmpDir.Join(strings.Split(tt.configPath, "/")...) + configPath.WriteFile([]byte("all: True")) + + viperObj := viper.New() + + initConfig(baseDir, viperObj) + + assert.Equal(t, configPath.String(), viperObj.ConfigFileUsed()) + }) + } +} diff --git a/go.mod b/go.mod index d55d49aa..0a89c6d5 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/vektra/mockery/v2 go 1.19 require ( + github.com/chigopher/pathlib v0.12.0 github.com/mitchellh/go-homedir v1.1.0 github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.27.0 diff --git a/go.sum b/go.sum index da710184..ec0a07f7 100644 --- a/go.sum +++ b/go.sum @@ -39,6 +39,8 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chigopher/pathlib v0.12.0 h1:1GM7fN/IwXXmOHbd1jkMqHD2wUhYqUvafgxTwmLT/q8= +github.com/chigopher/pathlib v0.12.0/go.mod h1:EJ5UtJ/sK8Nt6q3VWN+EwZLZ3g0afJiG8NegYiQQ/gQ= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -150,8 +152,10 @@ github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3v github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.2 h1:+jQXlF3scKIcSEKkdHzXhCTDLPFi5r1wnK6yPS+49Gw= github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuwRkXbG66OzopI= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -162,6 +166,7 @@ github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs= github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/afero v1.4.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= @@ -180,6 +185,7 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= @@ -198,6 +204,7 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= diff --git a/mocks/pkg/fixtures/Expecter.go b/mocks/pkg/fixtures/Expecter.go index 8f91afff..6d7ce5ee 100644 --- a/mocks/pkg/fixtures/Expecter.go +++ b/mocks/pkg/fixtures/Expecter.go @@ -46,8 +46,8 @@ type Expecter_ManyArgsReturns_Call struct { } // ManyArgsReturns is a helper method to define mock.On call -// - str string -// - i int +// - str string +// - i int func (_e *Expecter_Expecter) ManyArgsReturns(str interface{}, i interface{}) *Expecter_ManyArgsReturns_Call { return &Expecter_ManyArgsReturns_Call{Call: _e.mock.On("ManyArgsReturns", str, i)} } @@ -111,7 +111,7 @@ type Expecter_NoReturn_Call struct { } // NoReturn is a helper method to define mock.On call -// - str string +// - str string func (_e *Expecter_Expecter) NoReturn(str interface{}) *Expecter_NoReturn_Call { return &Expecter_NoReturn_Call{Call: _e.mock.On("NoReturn", str)} } @@ -154,7 +154,7 @@ type Expecter_Variadic_Call struct { } // Variadic is a helper method to define mock.On call -// - ints ...int +// - ints ...int func (_e *Expecter_Expecter) Variadic(ints ...interface{}) *Expecter_Variadic_Call { return &Expecter_Variadic_Call{Call: _e.mock.On("Variadic", append([]interface{}{}, ints...)...)} @@ -201,9 +201,9 @@ type Expecter_VariadicMany_Call struct { } // VariadicMany is a helper method to define mock.On call -// - i int -// - a string -// - intfs ...interface{} +// - i int +// - a string +// - intfs ...interface{} func (_e *Expecter_Expecter) VariadicMany(i interface{}, a interface{}, intfs ...interface{}) *Expecter_VariadicMany_Call { return &Expecter_VariadicMany_Call{Call: _e.mock.On("VariadicMany", append([]interface{}{i, a}, intfs...)...)} From 6182e9186bd8ad20c424b68925f1c56b3be6969d Mon Sep 17 00:00:00 2001 From: LandonTClipp Date: Tue, 20 Dec 2022 15:07:24 -0600 Subject: [PATCH 2/3] Add additional test for non-existent config file --- cmd/mockery.go | 2 +- cmd/mockery_test.go | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/cmd/mockery.go b/cmd/mockery.go index 39dac43b..6201e3af 100644 --- a/cmd/mockery.go +++ b/cmd/mockery.go @@ -134,7 +134,7 @@ func initConfig(baseSearchPath *pathlib.Path, viperObj *viper.Viper) { currentDir := baseSearchPath - for len(currentDir.Parts()) != 1 { + for len(currentDir.Parts()) > 1 { viperObj.AddConfigPath(currentDir.String()) currentDir = currentDir.Parent() } diff --git a/cmd/mockery_test.go b/cmd/mockery_test.go index bb2c658f..6745ef26 100644 --- a/cmd/mockery_test.go +++ b/cmd/mockery_test.go @@ -108,14 +108,22 @@ func Test_initConfig(t *testing.T) { base_path: "1/2/3/4", configPath: "1/.mockery.yaml", }, + { + name: "no config file found", + base_path: "1/2/3/4", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tmpDir := pathlib.NewPath(t.TempDir()) baseDir := tmpDir.Join(strings.Split(tt.base_path, "/")...) require.NoError(t, baseDir.MkdirAll()) - configPath := tmpDir.Join(strings.Split(tt.configPath, "/")...) - configPath.WriteFile([]byte("all: True")) + + configPath := pathlib.NewPath("") + if tt.configPath != "" { + configPath = tmpDir.Join(strings.Split(tt.configPath, "/")...) + configPath.WriteFile([]byte("all: True")) + } viperObj := viper.New() From 231d3d6cf69a819320332b3acf7380080b8b37cf Mon Sep 17 00:00:00 2001 From: LandonTClipp Date: Tue, 20 Dec 2022 15:22:21 -0600 Subject: [PATCH 3/3] Updating logs --- cmd/mockery.go | 10 ++++++---- cmd/showconfig.go | 7 +++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/cmd/mockery.go b/cmd/mockery.go index 6201e3af..76e0d77f 100644 --- a/cmd/mockery.go +++ b/cmd/mockery.go @@ -134,8 +134,11 @@ func initConfig(baseSearchPath *pathlib.Path, viperObj *viper.Viper) { currentDir := baseSearchPath - for len(currentDir.Parts()) > 1 { + for { viperObj.AddConfigPath(currentDir.String()) + if len(currentDir.Parts()) <= 1 { + break + } currentDir = currentDir.Parent() } @@ -144,9 +147,8 @@ func initConfig(baseSearchPath *pathlib.Path, viperObj *viper.Viper) { } // Note we purposely ignore the error. Don't care if we can't find a config file. - if err := viperObj.ReadInConfig(); err == nil { - fmt.Fprintf(os.Stderr, "Using config file: %s\n", viperObj.ConfigFileUsed()) - } + viperObj.ReadInConfig() + viperObj.Set("config", viperObj.ConfigFileUsed()) } const regexMetadataChars = "\\.+*?()|[]{}^$" diff --git a/cmd/showconfig.go b/cmd/showconfig.go index 14755da9..7ac7d23f 100644 --- a/cmd/showconfig.go +++ b/cmd/showconfig.go @@ -18,6 +18,7 @@ func NewShowConfigCmd() *cobra.Command { This initializes viper and prints out the merged configuration between config files, environment variables, and CLI flags.`, RunE: func(cmd *cobra.Command, args []string) error { + config := &config.Config{} if err := viper.UnmarshalExact(config); err != nil { return errors.Wrapf(err, "failed to unmarshal config") @@ -26,6 +27,12 @@ func NewShowConfigCmd() *cobra.Command { if err != nil { return errors.Wrapf(err, "Failed to marshal yaml") } + log, err := getLogger(config.LogLevel) + if err != nil { + panic(err) + } + log.Info().Msgf("Using config: %s", config.Config) + fmt.Printf("%s", string(out)) return nil },