diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e29b526..cee89c2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: os: [Ubuntu] - go-version: ["1.23.x"] + go-version: ["1.24.x"] runs-on: ${{ matrix.os }}-latest permissions: contents: read # for golangci-lint-action @@ -39,6 +39,7 @@ jobs: paths: "test-report.xml" if: always() - name: Lint - uses: golangci/golangci-lint-action@v7 + uses: golangci/golangci-lint-action@v8 with: - version: v2.0.1 + version: v2.1.6 + args: --timeout=5m --verbose diff --git a/.golangci.yaml b/.golangci.yaml index 31ca1c4..9fdf301 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -33,7 +33,7 @@ linters: #- exhaustruct # checks if all structure fields are initialized - exptostd # Detects functions from golang.org/x/exp/ that can be replaced by std functions. - fatcontext # finds nested context.WithValue calls in loops - # - forbidigo # forbids identifiers + #- forbidigo # forbids identifiers #- forcetypeassert # finds forced type assertions #- funlen # Tool for detection of long functions #- ginkgolinter # Enforces the Ginkgo testing package guidelines. diff --git a/config.go b/config.go index d66ab08..340aa90 100644 --- a/config.go +++ b/config.go @@ -87,7 +87,7 @@ func (r *structReflector) processField(field reflect.StructField, fieldValue ref apply = func(cmd *cli.Command) { fieldValue.SetString(cmd.String(flagName)) } - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32: + case reflect.Int: var value int64 var err error if tags.defaultValue != "" { @@ -96,17 +96,76 @@ func (r *structReflector) processField(field reflect.StructField, fieldValue ref return fmt.Errorf("failed to parse int value %s for field %s: %w", tags.defaultValue, field.Name, err) } } - flag = &cli.IntFlag{ Name: flagName, Aliases: tags.aliases, Usage: tags.help, DefaultText: tags.defaultValue, - Value: value, + Value: int(value), + Sources: sources, + } + apply = func(cmd *cli.Command) { + fieldValue.SetInt(int64(cmd.Int(flagName))) + } + case reflect.Int8: + var value int64 + var err error + if tags.defaultValue != "" { + value, err = strconv.ParseInt(tags.defaultValue, 10, 64) + if err != nil { + return fmt.Errorf("failed to parse int value %s for field %s: %w", tags.defaultValue, field.Name, err) + } + } + flag = &cli.Int8Flag{ + Name: flagName, + Aliases: tags.aliases, + Usage: tags.help, + DefaultText: tags.defaultValue, + Value: int8(value), //nolint: gosec + Sources: sources, + } + apply = func(cmd *cli.Command) { + fieldValue.SetInt(int64(cmd.Int8(flagName))) + } + case reflect.Int16: + var value int64 + var err error + if tags.defaultValue != "" { + value, err = strconv.ParseInt(tags.defaultValue, 10, 64) + if err != nil { + return fmt.Errorf("failed to parse int value %s for field %s: %w", tags.defaultValue, field.Name, err) + } + } + flag = &cli.Int16Flag{ + Name: flagName, + Aliases: tags.aliases, + Usage: tags.help, + DefaultText: tags.defaultValue, + Value: int16(value), //nolint: gosec Sources: sources, } apply = func(cmd *cli.Command) { - fieldValue.SetInt(cmd.Int(flagName)) + fieldValue.SetInt(int64(cmd.Int16(flagName))) + } + case reflect.Int32: + var value int64 + var err error + if tags.defaultValue != "" { + value, err = strconv.ParseInt(tags.defaultValue, 10, 64) + if err != nil { + return fmt.Errorf("failed to parse int value %s for field %s: %w", tags.defaultValue, field.Name, err) + } + } + flag = &cli.Int32Flag{ + Name: flagName, + Aliases: tags.aliases, + Usage: tags.help, + DefaultText: tags.defaultValue, + Value: int32(value), //nolint: gosec + Sources: sources, + } + apply = func(cmd *cli.Command) { + fieldValue.SetInt(int64(cmd.Int32(flagName))) } case reflect.Int64: if _, ok := fieldValue.Interface().(time.Duration); ok { // special handling for time.Duration, which is a int64 @@ -140,7 +199,7 @@ func (r *structReflector) processField(field reflect.StructField, fieldValue ref } } - flag = &cli.IntFlag{ + flag = &cli.Int64Flag{ Name: flagName, Aliases: tags.aliases, Usage: tags.help, @@ -149,10 +208,10 @@ func (r *structReflector) processField(field reflect.StructField, fieldValue ref Sources: sources, } apply = func(cmd *cli.Command) { - fieldValue.SetInt(cmd.Int(flagName)) + fieldValue.SetInt(cmd.Int64(flagName)) } } - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + case reflect.Uint: var value uint64 var err error if tags.defaultValue != "" { @@ -163,6 +222,90 @@ func (r *structReflector) processField(field reflect.StructField, fieldValue ref } flag = &cli.UintFlag{ + Name: flagName, + Aliases: tags.aliases, + Usage: tags.help, + DefaultText: tags.defaultValue, + Value: uint(value), + Sources: sources, + } + apply = func(cmd *cli.Command) { + fieldValue.SetUint(uint64(cmd.Uint(flagName))) + } + case reflect.Uint8: + var value uint64 + var err error + if tags.defaultValue != "" { + value, err = strconv.ParseUint(tags.defaultValue, 10, 64) + if err != nil { + return fmt.Errorf("failed to parse uint value %s for field %s: %w", tags.defaultValue, field.Name, err) + } + } + + flag = &cli.Uint8Flag{ + Name: flagName, + Aliases: tags.aliases, + Usage: tags.help, + DefaultText: tags.defaultValue, + Value: uint8(value), //nolint: gosec + Sources: sources, + } + apply = func(cmd *cli.Command) { + fieldValue.SetUint(uint64(cmd.Uint8(flagName))) + } + case reflect.Uint16: + var value uint64 + var err error + if tags.defaultValue != "" { + value, err = strconv.ParseUint(tags.defaultValue, 10, 64) + if err != nil { + return fmt.Errorf("failed to parse uint value %s for field %s: %w", tags.defaultValue, field.Name, err) + } + } + + flag = &cli.Uint16Flag{ + Name: flagName, + Aliases: tags.aliases, + Usage: tags.help, + DefaultText: tags.defaultValue, + Value: uint16(value), //nolint: gosec + Sources: sources, + } + apply = func(cmd *cli.Command) { + fieldValue.SetUint(uint64(cmd.Uint16(flagName))) + } + case reflect.Uint32: + var value uint64 + var err error + if tags.defaultValue != "" { + value, err = strconv.ParseUint(tags.defaultValue, 10, 64) + if err != nil { + return fmt.Errorf("failed to parse uint value %s for field %s: %w", tags.defaultValue, field.Name, err) + } + } + + flag = &cli.Uint32Flag{ + Name: flagName, + Aliases: tags.aliases, + Usage: tags.help, + DefaultText: tags.defaultValue, + Value: uint32(value), //nolint: gosec + Sources: sources, + } + apply = func(cmd *cli.Command) { + fieldValue.SetUint(uint64(cmd.Uint32(flagName))) + } + case reflect.Uint64: + var value uint64 + var err error + if tags.defaultValue != "" { + value, err = strconv.ParseUint(tags.defaultValue, 10, 64) + if err != nil { + return fmt.Errorf("failed to parse uint value %s for field %s: %w", tags.defaultValue, field.Name, err) + } + } + + flag = &cli.Uint64Flag{ Name: flagName, Aliases: tags.aliases, Usage: tags.help, @@ -171,9 +314,30 @@ func (r *structReflector) processField(field reflect.StructField, fieldValue ref Sources: sources, } apply = func(cmd *cli.Command) { - fieldValue.SetUint(cmd.Uint(flagName)) + fieldValue.SetUint(cmd.Uint64(flagName)) + } + case reflect.Float32: + var value float64 + var err error + if tags.defaultValue != "" { + value, err = strconv.ParseFloat(tags.defaultValue, 64) + if err != nil { + return fmt.Errorf("failed to parse float value %s for field %s: %w", tags.defaultValue, field.Name, err) + } + } + + flag = &cli.Float32Flag{ + Name: flagName, + Aliases: tags.aliases, + Usage: tags.help, + DefaultText: tags.defaultValue, + Value: float32(value), + Sources: sources, + } + apply = func(cmd *cli.Command) { + fieldValue.SetFloat(float64(cmd.Float32(flagName))) } - case reflect.Float32, reflect.Float64: + case reflect.Float64: var value float64 var err error if tags.defaultValue != "" { @@ -183,7 +347,7 @@ func (r *structReflector) processField(field reflect.StructField, fieldValue ref } } - flag = &cli.FloatFlag{ + flag = &cli.Float64Flag{ Name: flagName, Aliases: tags.aliases, Usage: tags.help, @@ -192,7 +356,7 @@ func (r *structReflector) processField(field reflect.StructField, fieldValue ref Sources: sources, } apply = func(cmd *cli.Command) { - fieldValue.SetFloat(cmd.Float(flagName)) + fieldValue.SetFloat(cmd.Float64(flagName)) } case reflect.Bool: var value bool diff --git a/go.mod b/go.mod index f7591ea..079eead 100644 --- a/go.mod +++ b/go.mod @@ -6,21 +6,21 @@ require ( github.com/BurntSushi/toml v1.5.0 github.com/go-playground/validator/v10 v10.26.0 github.com/iancoleman/strcase v0.3.0 - github.com/samber/lo v1.49.1 + github.com/samber/lo v1.50.0 github.com/stretchr/testify v1.10.0 - github.com/urfave/cli/v3 v3.1.1 + github.com/urfave/cli/v3 v3.3.3 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect - github.com/gabriel-vasile/mimetype v1.4.8 // indirect + github.com/gabriel-vasile/mimetype v1.4.9 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/crypto v0.37.0 // indirect - golang.org/x/net v0.39.0 // indirect - golang.org/x/sys v0.32.0 // indirect - golang.org/x/text v0.24.0 // indirect + golang.org/x/crypto v0.38.0 // indirect + golang.org/x/net v0.40.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/text v0.25.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 4af5fca..3edbf61 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= -github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= +github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY= +github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -22,20 +22,20 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew= -github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o= +github.com/samber/lo v1.50.0 h1:XrG0xOeHs+4FQ8gJR97zDz5uOFMW7OwFWiFVzqopKgY= +github.com/samber/lo v1.50.0/go.mod h1:RjZyNk6WSnUFRKK6EyOhsRJMqft3G+pg7dCWHQCWvsc= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/urfave/cli/v3 v3.1.1 h1:bNnl8pFI5dxPOjeONvFCDFoECLQsceDG4ejahs4Jtxk= -github.com/urfave/cli/v3 v3.1.1/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo= -golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= -golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= -golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= -golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +github.com/urfave/cli/v3 v3.3.3 h1:byCBaVdIXuLPIDm5CYZRVG6NvT7tv1ECqdU4YzlEa3I= +github.com/urfave/cli/v3 v3.3.3/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo= +golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= +golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=