From a7bbac38ce9347061e0b716ee8195ff9c84b31f2 Mon Sep 17 00:00:00 2001 From: "Daniel G. Taylor" Date: Sat, 17 Aug 2024 12:42:17 -0700 Subject: [PATCH] feat: Update minimum Go version to 1.21 --- .github/workflows/ci.yaml | 11 +++++++---- README.md | 2 +- README_CN.md | 2 +- adapters/humaflow/flow/flow.go | 21 +++------------------ casing/casing.go | 2 +- docs/docs/tutorial/installation.md | 2 +- examples/go.mod | 4 ++-- examples/go.sum | 8 ++++---- go.mod | 2 +- huma.go | 21 +++------------------ registry.go | 2 +- schema_test.go | 6 +++--- validate_test.go | 2 +- 13 files changed, 29 insertions(+), 56 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index d8cc3454..0683a740 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -6,15 +6,18 @@ on: jobs: build: runs-on: ubuntu-latest + strategy: + matrix: + go: [1.21, 1.22, 1.23] name: Build & Test steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup go - uses: actions/setup-go@v1 + uses: actions/setup-go@v5 with: - go-version: "1.22" + go-version: ${{ matrix.go }} - name: golangci-lint - uses: golangci/golangci-lint-action@v3 + uses: golangci/golangci-lint-action@v6 with: version: v1.57.2 - run: go test -coverprofile=coverage.txt -covermode=atomic ./... diff --git a/README.md b/README.md index 2fadd999..35ae5e85 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ A big thank you to our current & former sponsors! # Install -Install via `go get`. Note that Go 1.20 or newer is required. +Install via `go get`. Note that Go 1.21 or newer is required. ```sh # After: go mod init ... diff --git a/README_CN.md b/README_CN.md index ed0910fd..fcbc7602 100644 --- a/README_CN.md +++ b/README_CN.md @@ -83,7 +83,7 @@ # 安装 -通过安装`go get`。请注意,需要 Go 1.20 或更高版本。 +通过安装`go get`。请注意,需要 Go 1.21 或更高版本。 ```sh # After: go mod init ... diff --git a/adapters/humaflow/flow/flow.go b/adapters/humaflow/flow/flow.go index c03dc64e..22b9083e 100644 --- a/adapters/humaflow/flow/flow.go +++ b/adapters/humaflow/flow/flow.go @@ -64,25 +64,10 @@ import ( "net/http" "net/url" "regexp" + "slices" "strings" ) -// slicesIndex returns the index of the first occurrence of v in s, -// or -1 if not present. -func slicesIndex[E comparable](s []E, v E) int { - for i := range s { - if v == s[i] { - return i - } - } - return -1 -} - -// slicesContains reports whether v is present in s. -func slicesContains[E comparable](s []E, v E) bool { - return slicesIndex(s, v) >= 0 -} - // AllMethods is a slice containing all HTTP request methods. var AllMethods = []string{http.MethodGet, http.MethodHead, http.MethodPost, http.MethodPut, http.MethodPatch, http.MethodDelete, http.MethodConnect, http.MethodOptions, http.MethodTrace} @@ -128,7 +113,7 @@ func New() *Mux { // Handle registers a new handler for the given request path pattern and HTTP // methods. func (m *Mux) Handle(pattern string, handler http.Handler, methods ...string) { - if slicesContains(methods, http.MethodGet) && !slicesContains(methods, http.MethodHead) { + if slices.Contains(methods, http.MethodGet) && !slices.Contains(methods, http.MethodHead) { methods = append(methods, http.MethodHead) } @@ -191,7 +176,7 @@ func (m *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request) { route.handler.ServeHTTP(w, r.WithContext(ctx)) return } - if !slicesContains(allowedMethods, route.method) { + if !slices.Contains(allowedMethods, route.method) { allowedMethods = append(allowedMethods, route.method) } } diff --git a/casing/casing.go b/casing/casing.go index d9795a42..4414f789 100644 --- a/casing/casing.go +++ b/casing/casing.go @@ -292,7 +292,7 @@ func Camel(value string, transform ...TransformFunc) string { if transform == nil { transform = []TransformFunc{strings.ToLower} } - t := append(transform, strings.Title) //nolint:staticcheck + t := append(transform, strings.Title) return Join(Split(value), "", t...) } diff --git a/docs/docs/tutorial/installation.md b/docs/docs/tutorial/installation.md index dd89f0d5..07e408e0 100644 --- a/docs/docs/tutorial/installation.md +++ b/docs/docs/tutorial/installation.md @@ -6,7 +6,7 @@ description: Learn how to install Huma and create your first API. ## Prerequisites -Huma requires [Go 1.20 or newer](https://go.dev/dl/), so install that first. You'll also want some kind of [text editor or IDE](https://code.visualstudio.com/) to write code and a terminal to run commands. +Huma requires [Go 1.21 or newer](https://go.dev/dl/), so install that first. You'll also want some kind of [text editor or IDE](https://code.visualstudio.com/) to write code and a terminal to run commands. ## Project Setup diff --git a/examples/go.mod b/examples/go.mod index 8fea114d..123666f8 100644 --- a/examples/go.mod +++ b/examples/go.mod @@ -1,6 +1,6 @@ module github.com/danielgtaylor/huma/v2/examples -go 1.20 +go 1.21 replace github.com/danielgtaylor/huma/v2 => ../ @@ -51,7 +51,7 @@ require ( go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.8.0 // indirect go.uber.org/zap v1.21.0 // indirect - golang.org/x/sys v0.17.0 // indirect + golang.org/x/sys v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/examples/go.sum b/examples/go.sum index 3b742856..da3b7fbe 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -470,7 +470,7 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.20.0 h1:jmAMJJZXr5KiCw05dfYK9QnqaqKLYXijU23lsEdcQqg= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -549,7 +549,7 @@ golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -648,8 +648,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/go.mod b/go.mod index 69988ba0..50afc903 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/danielgtaylor/huma/v2 -go 1.20 +go 1.21 require ( github.com/danielgtaylor/shorthand/v2 v2.2.0 diff --git a/huma.go b/huma.go index 1dc7a195..45d2e6ca 100644 --- a/huma.go +++ b/huma.go @@ -18,6 +18,7 @@ import ( "net/http" "reflect" "regexp" + "slices" "strconv" "strings" "sync" @@ -33,22 +34,6 @@ var cookieType = reflect.TypeOf((*http.Cookie)(nil)).Elem() var fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() var stringType = reflect.TypeOf("") -// slicesIndex returns the index of the first occurrence of v in s, -// or -1 if not present. -func slicesIndex[E comparable](s []E, v E) int { - for i := range s { - if v == s[i] { - return i - } - } - return -1 -} - -// slicesContains reports whether v is present in s. -func slicesContains[E comparable](s []E, v E) bool { - return slicesIndex(s, v) >= 0 -} - // SetReadDeadline is a utility to set the read deadline on a response writer, // if possible. If not, it will not incur any allocations (unlike the stdlib // `http.ResponseController`). This is mostly a convenience function for @@ -141,7 +126,7 @@ func findParams(registry Registry, op *Operation, t reflect.Type) *findResult[*p name = split[0] // If `in` is `query` then `explode` defaults to true. Parsing is *much* // easier if we use comma-separated values, so we disable explode by default. - if slicesContains(split[1:], "explode") { + if slices.Contains(split[1:], "explode") { pfi.Explode = true } explode = &pfi.Explode @@ -417,7 +402,7 @@ func _findInType[T comparable](t reflect.Type, path []int, result *findResult[T] if !f.IsExported() { continue } - if slicesContains(ignore, f.Name) { + if slices.Contains(ignore, f.Name) { continue } if ignoreAnonymous && f.Anonymous { diff --git a/registry.go b/registry.go index 5b034d97..222927c5 100644 --- a/registry.go +++ b/registry.go @@ -142,7 +142,7 @@ func (r *mapRegistry) Map() map[string]*Schema { } func (r *mapRegistry) MarshalJSON() ([]byte, error) { - return json.Marshal(r.schemas) //nolint:musttag + return json.Marshal(r.schemas) } func (r *mapRegistry) MarshalYAML() (interface{}, error) { diff --git a/schema_test.go b/schema_test.go index 21ae26f0..6f8a44ff 100644 --- a/schema_test.go +++ b/schema_test.go @@ -1212,21 +1212,21 @@ func TestCustomUnmarshalType(t *testing.T) { // Confirm the field works as expected when loading JSON. o = O{} - err := json.Unmarshal([]byte(`{"field": 123}`), &o) //nolint:musttag + err := json.Unmarshal([]byte(`{"field": 123}`), &o) require.NoError(t, err) assert.True(t, o.Field.Sent) assert.False(t, o.Field.Null) assert.Equal(t, 123, o.Field.Value) o = O{} - err = json.Unmarshal([]byte(`{"field": null}`), &o) //nolint:musttag + err = json.Unmarshal([]byte(`{"field": null}`), &o) require.NoError(t, err) assert.True(t, o.Field.Sent) assert.True(t, o.Field.Null) assert.Equal(t, 0, o.Field.Value) o = O{} - err = json.Unmarshal([]byte(`{}`), &o) //nolint:musttag + err = json.Unmarshal([]byte(`{}`), &o) require.NoError(t, err) assert.False(t, o.Field.Sent) assert.False(t, o.Field.Null) diff --git a/validate_test.go b/validate_test.go index bf4e66b6..27916b89 100644 --- a/validate_test.go +++ b/validate_test.go @@ -1373,7 +1373,7 @@ func TestValidate(t *testing.T) { errs := mapTo(res.Errors, func(e error) string { return e.(*huma.ErrorDetail).Message }) - schemaJSON, _ := json.MarshalIndent(registry.Map(), "", " ") //nolint: musttag + schemaJSON, _ := json.MarshalIndent(registry.Map(), "", " ") for _, err := range test.errs { assert.Contains(t, errs, err, string(schemaJSON)) }