From f324a9e7bd15df69927992f91ec4b799a837d104 Mon Sep 17 00:00:00 2001 From: Himanshu Rai Date: Mon, 12 Oct 2026 16:03:53 +0530 Subject: [PATCH] Modernize tooling --- .github/workflows/ci.yml | 4 +-- .golangci.yaml | 69 ++++++++++++++++++++-------------------- Makefile | 2 +- go.mod | 14 ++++---- go.sum | 30 ++++++----------- hyperbun.go | 11 +++---- util.go | 5 ++- 7 files changed, 61 insertions(+), 74 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c72c82f..5159a24 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,13 +23,13 @@ jobs: - uses: actions/setup-go@v5 with: - go-version: '^1.25.0' + go-version: '^1.26.0' - run: go version - name: golangci-lint uses: golangci/golangci-lint-action@v9 with: - version: v2.7.2 + version: v2.14.0 - name: Test run: make test diff --git a/.golangci.yaml b/.golangci.yaml index bc0fcfa..ae0d8ba 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -1,17 +1,14 @@ -# This file is licensed under the terms of the MIT license https://opensource.org/license/mit -# Copyright (c) 2021-2025 Marat Reimers - -## Golden config for golangci-lint v2.7.2 +# Based on Golden config for golangci-lint v2.14.0 by Marat Reymers. +# Licensed under the MIT License. +# https://github.com/maratori/golangci-lint-config # -# This is the best config for golangci-lint based on my experience and opinion. -# It is very strict, but not extremely strict. -# Feel free to adapt it to suit your needs. -# If this config helps you, please consider keeping a link to this repo (see the next comment). - -# Based on https://github.com/maratori/golangci-lint-config/blob/v2.7.2/.golangci.yml, with following changes -# 1. formatters.enable: Enabled gci, gofumpt; Disabled goimports -# 2. formatters.settings: Added gci; Removed goimports -# 3. linters.enable: Disabled gochecknoglobals, mnd, nilnil, testpackage +# To update: start from Marat Reymers' config for the new golangci-lint version and +# apply the diff between this file and his config for the version named above. Do not +# port our edits by hand. Bump the version above once done. +# +# A linter that upstream newly enables gets tried, not assumed: keep it enabled if the +# lint run comes back clean, otherwise leave it commented out in `linters.enable` like +# the others we have not adopted yet. version: "2" @@ -63,6 +60,7 @@ linters: - bidichk # checks for dangerous unicode character sequences - bodyclose # checks whether HTTP response body is closed successfully - canonicalheader # checks whether net/http.Header uses canonical header + - clickhouselint # detects common mistakes with the ClickHouse native Go driver API - copyloopvar # detects places where loop variables are copied (Go 1.22+) - cyclop # checks function and package cyclomatic complexity - depguard # checks if package imports are in a list of acceptable packages @@ -111,6 +109,7 @@ linters: - nolintlint # reports ill-formed or insufficient nolint directives - nonamedreturns # reports all named returns - nosprintfhostport # checks for misuse of Sprintf to construct a host with port in a URL + #- paralleltest # detects missing usage of t.Parallel() method in your Go test - perfsprint # checks that fmt.Sprintf can be replaced with a faster alternative - predeclared # finds code that shadows one of Go's predeclared identifiers - promlinter # checks Prometheus metrics naming via promlint @@ -139,7 +138,7 @@ linters: ## you may want to enable #- arangolint # opinionated best practices for arangodb client #- decorder # checks declaration order and count of types, constants, variables and functions - #- exhaustruct # [highly recommend to enable] checks if all structure fields are initialized + #- exhaustruct_v5 # [highly recommend to enable] checks if all structure fields are initialized #- ginkgolinter # [if you use ginkgo/gomega] enforces standards of using ginkgo and gomega #- godox # detects usage of FIXME, TODO and other keywords inside comments #- goheader # checks is file header matches to pattern @@ -160,8 +159,9 @@ linters: #- dupword # [useless without config] checks for duplicate words in the source code #- err113 # [too strict] checks the errors handling expressions #- errchkjson # [don't see profit + I'm against of omitting errors like in the first example https://github.com/breml/errchkjson] checks types passed to the json encoding functions. Reports unsupported types and optionally reports occasions, where the check for the returned error can be omitted + #- exhaustruct # [use exhaustruct_v5 instead] checks if all structure fields are initialized #- forcetypeassert # [replaced by errcheck] finds forced type assertions - #- gomodguard # [use more powerful depguard] allow and block lists linter for direct Go module dependencies + #- gomodguard_v2: [use more powerful depguard] allow and blocklist linter for direct Go module dependencies #- gosmopolitan # reports certain i18n/l10n anti-patterns in your Go codebase #- grouper # analyzes expression groups #- importas # enforces consistent import aliases @@ -169,10 +169,8 @@ linters: #- maintidx # measures the maintainability index of each function #- misspell # [useless] finds commonly misspelled English words in comments #- nlreturn # [too strict and mostly code is not more readable] checks for a new line before return and branch statements to increase code clarity - #- paralleltest # [too many false positives] detects missing usage of t.Parallel() method in your Go test #- tagliatelle # checks the struct tags #- thelper # detects golang test helpers without t.Helper() call and checks the consistency of test helpers - #- wsl # [too strict and mostly code is not more readable] whitespace linter forces you to use empty lines #- wsl_v5 # [too strict and mostly code is not more readable] add or remove empty lines # All settings can be found here https://github.com/golangci/golangci-lint/blob/HEAD/.golangci.reference.yml @@ -252,15 +250,15 @@ linters: - switch - map - exhaustruct: - # List of regular expressions to match type names that should be excluded from processing. + exhaustruct_v5: + # List of regular expressions to match type names that should be skipped from checking. # Anonymous structs can be matched by '' alias. # Has precedence over `include`. # Each regular expression must match the full type name, including package path. # For example, to match type `net/http.Cookie` regular expression should be `.*/http\.Cookie`, # but not `http\.Cookie`. # Default: [] - exclude: + ignore-patterns: # std libs - ^net/http.Client$ - ^net/http.Cookie$ @@ -287,6 +285,9 @@ linters: # Allows empty structures in return statements. # Default: false allow-empty-returns: true + # Allow empty literals the blank identifier receives. + # Default: false + allow-empty-blank-assignments: true funcorder: # Checks if the exported methods of a structure are placed before the non-exported ones. @@ -334,6 +335,9 @@ linters: # Assert no unused link in godocs. # https://github.com/godoc-lint/godoc-lint?tab=readme-ov-file#no-unused-link - no-unused-link + # Require proper doc links to standard library declarations where applicable. + # https://github.com/godoc-lint/godoc-lint?tab=readme-ov-file#require-stdlib-doclink + - require-stdlib-doclink govet: # Enable all analyzers. @@ -396,6 +400,9 @@ linters: # Optimizes into strings concatenation. # Default: true strconcat: false + # Enable/disable optimization of error formatting. + # Default: true + error-format: false # https://github.com/catenacyber/perfsprint/issues/62 reassign: # Patterns for global variable names that are checked for reassignment. @@ -411,21 +418,15 @@ linters: - github.com/jmoiron/sqlx sloglint: - # Enforce not using global loggers. - # Values: - # - "": disabled - # - "all": report all global loggers - # - "default": report only the default slog logger - # https://github.com/go-simpler/sloglint?tab=readme-ov-file#no-global - # Default: "" + # Report the use of global loggers. + # https://github.com/go-simpler/sloglint#no-global-logger + # Values: "all", "default" + # Default: "" (disabled) no-global: all - # Enforce using methods that accept a context. - # Values: - # - "": disabled - # - "all": report all contextless calls - # - "scope": report only if a context exists in the scope of the outermost function - # https://github.com/go-simpler/sloglint?tab=readme-ov-file#context-only - # Default: "" + # Report the use of functions without a context.Context. + # https://github.com/go-simpler/sloglint#context-only + # Values: "all", "scope" + # Default: "" (disabled) context: scope staticcheck: diff --git a/Makefile b/Makefile index 45eceea..fdd2e3b 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ GOCMD=go linters-install: @golangci-lint --version >/dev/null 2>&1 || { \ echo "installing linting tools..."; \ - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.7.2; \ + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.14.0; \ } lint: linters-install diff --git a/go.mod b/go.mod index 1f2a5b2..fe6492b 100644 --- a/go.mod +++ b/go.mod @@ -1,20 +1,18 @@ module github.com/hypersequent/hyperbun -go 1.25 +go 1.26.0 require ( - github.com/stretchr/testify v1.11.1 - github.com/uptrace/bun v1.2.1 + github.com/stretchr/testify v1.12.1 + github.com/uptrace/bun v1.3.0 ) require ( - github.com/davecgh/go-spew v1.1.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect - github.com/kr/text v0.2.0 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/puzpuzpuz/xsync/v3 v3.5.1 // indirect github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect - golang.org/x/sys v0.18.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect + go.yaml.in/yaml/v3 v3.0.5 // indirect + golang.org/x/sys v0.41.0 // indirect ) diff --git a/go.sum b/go.sum index 89ae709..74c917b 100644 --- a/go.sum +++ b/go.sum @@ -1,28 +1,18 @@ -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -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/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -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/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/puzpuzpuz/xsync/v3 v3.5.1 h1:GJYJZwO6IdxN/IKbneznS6yPkVC+c3zyY/j19c++5Fg= +github.com/puzpuzpuz/xsync/v3 v3.5.1/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA= +github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE= +github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs= -github.com/uptrace/bun v1.2.1 h1:2ENAcfeCfaY5+2e7z5pXrzFKy3vS8VXvkCag6N2Yzfk= -github.com/uptrace/bun v1.2.1/go.mod h1:cNg+pWBUMmJ8rHnETgf65CEvn3aIKErrwOD6IA8e+Ec= +github.com/uptrace/bun v1.3.0 h1:hUcbfRpbQk4/upFSI+uZf6jSJw5A0lkIKt0XdpvbUZo= +github.com/uptrace/bun v1.3.0/go.mod h1:wNltaKJk4JtOt4SG5I5zmA7v0/Mzjh1+/S906Rayd3Y= github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -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= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= +go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= +golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= diff --git a/hyperbun.go b/hyperbun.go index d8e4852..136e8da 100644 --- a/hyperbun.go +++ b/hyperbun.go @@ -284,7 +284,7 @@ func CountQuery(m DB, table string, query string, args ...any) (int, error) { if err != nil { return 0, annotate(err, "CountQuery", "table", table) } - return count, nil + return int(count), nil } func Insert[T any](m DB, row *T) error { @@ -441,15 +441,15 @@ func annotate(err error, op string, kvs ...any) error { numPairs := len(kvs) / 2 for i := range numPairs { builder.WriteByte(' ') - builder.WriteString(fmt.Sprint(kvs[i*2])) + fmt.Fprint(&builder, kvs[i*2]) builder.WriteString("='") - builder.WriteString(fmt.Sprint(kvs[i*2+1])) + fmt.Fprint(&builder, kvs[i*2+1]) builder.WriteByte('\'') } if len(kvs)%2 != 0 { builder.WriteByte(' ') - builder.WriteString(fmt.Sprint(kvs[len(kvs)-1])) + fmt.Fprint(&builder, kvs[len(kvs)-1]) builder.WriteString("=''") } @@ -467,8 +467,7 @@ func hyperbunTableForType[T any]() string { kind = typ.Kind() } - for i := range typ.NumField() { - f := typ.Field(i) + for f := range typ.Fields() { val, ok := f.Tag.Lookup("bun") if !ok { continue diff --git a/util.go b/util.go index 2edabee..8c79c34 100644 --- a/util.go +++ b/util.go @@ -25,8 +25,7 @@ func getColumns(typ reflect.Type) []string { var columns []string - for i := range typ.NumField() { - f := typ.Field(i) + for f := range typ.Fields() { unexported := f.PkgPath != "" if unexported && !f.Anonymous { // unexported @@ -72,7 +71,7 @@ func fieldName(f reflect.StructField) string { } func indirectType(t reflect.Type) reflect.Type { - if t.Kind() == reflect.Ptr { + if t.Kind() == reflect.Pointer { t = t.Elem() } return t