From f24d999dff0cf8873dc6dfc254f68e8c2a44d8d3 Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Thu, 30 Oct 2025 21:24:28 +0000 Subject: [PATCH] chore(ci/lint/config): update golangci-lint configuration and workflows Refactor the golangci-lint configuration to use the latest version and update GitHub Actions workflows. Key changes include: - Update golangci-lint to v2.6 - Update GitHub Actions to use latest checkout and setup-go actions - Update Go versions in test matrix - Remove deprecated cache steps - Update Makefile golangci-lint tool version - Minor documentation formatting improvements --- .github/workflows/ci.yml | 92 +++++++++++++--------------- .golangci.yml | 126 ++++++++++++++++++++------------------- Makefile | 2 +- validate.go | 98 +++++++++++++++--------------- 4 files changed, 157 insertions(+), 161 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3ad5eb2..47c0edb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,28 +7,23 @@ jobs: name: Lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: golangci-lint - uses: golangci/golangci-lint-action@v2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: - version: v1.42 - env: - VERBOSE: "true" + go-version-file: go.mod + - name: golangci-lint + uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0 + with: + version: v2.6 tidy: name: Tidy runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-go@v2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: - go-version: 1.15 - - uses: actions/cache@v2 - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- + go-version-file: go.mod - name: Check if mods are tidy run: make check-tidy @@ -63,31 +58,31 @@ jobs: # github-token: ${{ secrets.GITHUB_TOKEN }} # auto-push: false - cov: - name: Coverage - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-go@v2 - with: - go-version: 1.15 - - uses: actions/cache@v2 - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- - - name: Publish coverage - uses: paambaati/codeclimate-action@v2.7.4 - env: - VERBOSE: "true" - GOMAXPROCS: 4 - CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }} - with: - coverageCommand: make cov - prefix: github.com/${{ github.repository }} - coverageLocations: | - ${{ github.workspace }}/coverage.out:gocov + # cov: + # name: Coverage + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v2 + # - uses: actions/setup-go@v2 + # with: + # go-version: 1.15 + # - uses: actions/cache@v2 + # with: + # path: ~/go/pkg/mod + # key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + # restore-keys: | + # ${{ runner.os }}-go- + # - name: Publish coverage + # uses: paambaati/codeclimate-action@v2.7.4 + # env: + # VERBOSE: "true" + # GOMAXPROCS: 4 + # CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }} + # with: + # coverageCommand: make cov + # prefix: github.com/${{ github.repository }} + # coverageLocations: | + # ${{ github.workspace }}/coverage.out:gocov test: name: Test @@ -98,22 +93,19 @@ jobs: go_version: - "1.15" - "1.16" - - "1.17" + - "1.18" + - "1.20" + - "1.25" steps: - - uses: actions/checkout@v2 - - uses: actions/setup-go@v2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: - go-version: ${{ matrix.terraform_version }} - - uses: actions/cache@v2 - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- + go-version-file: go.mod - name: Run tests run: make test env: VERBOSE: "true" + # benchmark-store: # name: Store benchmarks # runs-on: ubuntu-latest diff --git a/.golangci.yml b/.golangci.yml index 53035e6..460e352 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,50 +1,25 @@ -linters-settings: - funlen: - lines: 100 - statements: 150 - goconst: - min-occurrences: 5 - gocyclo: - min-complexity: 20 - golint: - min-confidence: 0 - govet: - check-shadowing: true - enable-all: true - disable: - - fieldalignment - lll: - line-length: 80 - tab-width: 4 - maligned: - suggest-new: true - misspell: - locale: US - +version: "2" +run: + modules-download-mode: readonly + allow-parallel-runners: true linters: - disable-all: true + default: none enable: - asciicheck - bodyclose - - deadcode - - depguard - dupl - durationcheck - errcheck - errorlint - exhaustive - - exportloopref - funlen - gochecknoinits - goconst - gocritic - gocyclo - godot - - gofumpt - - goimports - goprintffuncname - gosec - - gosimple - govet - importas - ineffassign @@ -60,40 +35,69 @@ linters: - rowserrcheck - sqlclosecheck - staticcheck - - structcheck - tparallel - - typecheck - unconvert - unparam - unused - - varcheck - wastedassign - whitespace - -issues: - exclude: - - Using the variable on range scope `tt` in function literal - - Using the variable on range scope `tc` in function literal - exclude-rules: - - path: "_test\\.go" - linters: - - funlen - - dupl - - goconst - - source: "^//go:generate " - linters: - - lll - - source: "`json:" - linters: - - lll - - source: "`yaml:" - linters: - - lll - - source: "`form:" - linters: - - lll - -run: - timeout: 2m - allow-parallel-runners: true - modules-download-mode: readonly + settings: + funlen: + lines: 100 + statements: 150 + goconst: + min-occurrences: 5 + gocyclo: + min-complexity: 20 + govet: + disable: + - fieldalignment + enable-all: true + lll: + line-length: 80 + tab-width: 4 + misspell: + locale: US + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + rules: + - linters: + - dupl + - funlen + - goconst + path: _test\.go + - linters: + - lll + source: "^//go:generate " + - linters: + - lll + source: "`json:" + - linters: + - lll + source: "`yaml:" + - linters: + - lll + source: "`form:" + - path: (.+)\.go$ + text: Using the variable on range scope `tt` in function literal + - path: (.+)\.go$ + text: Using the variable on range scope `tc` in function literal + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gofumpt + - goimports + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/Makefile b/Makefile index 13e2870..52c1ca7 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ endef $(eval $(call tool,godoc,golang.org/x/tools/cmd/godoc)) $(eval $(call tool,gofumports,mvdan.cc/gofumpt/gofumports)) -$(eval $(call tool,golangci-lint,github.com/golangci/golangci-lint/cmd/golangci-lint@v1.42)) +$(eval $(call tool,golangci-lint,github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.6)) $(eval $(call tool,gomod,github.com/Helcaraxan/gomod)) .PHONY: tools diff --git a/validate.go b/validate.go index 45f65ea..82e7e1f 100644 --- a/validate.go +++ b/validate.go @@ -1,13 +1,13 @@ // Package validate is yet another Go struct/object validation package, with a // focus on simplicity, flexibility, and full control over validation logic. // -// Interface +// # Interface // // To add validation to any type, simply implement the Validatable interface: // -// type Validatable interface { -// Validate() error -// } +// type Validatable interface { +// Validate() error +// } // // To mark a object as failing validation, the Validate method simply needs to // return a error. @@ -17,7 +17,7 @@ // can be fully validated, and the nested path to each object is tracked and // reported back any validation errors. // -// Multiple Errors +// # Multiple Errors // // Multiple errors can be reported from the Validate method using one of the // available Append helper functions which append errors together. Under the @@ -25,53 +25,53 @@ // a single error return type, and you can in fact just directly use multierr in // the a type's Validate method. // -// Structs and Field-specific Errors +// # Structs and Field-specific Errors // // When validating a struct, you are likely to have multiple errors for multiple // fields. To specify which field on the struct the error relates to, you have // to return a *validate.Error instead of a normal Go error type. For example: // -// type Book struct { -// Title string -// Author string -// } +// type Book struct { +// Title string +// Author string +// } // -// func (s *Book) Validate() error { -// var errs error +// func (s *Book) Validate() error { +// var errs error // -// if s.Title == "" { -// errs = validate.Append(errs, &validate.Error{ -// Field: "Title", Msg: "is required", -// }) -// } +// if s.Title == "" { +// errs = validate.Append(errs, &validate.Error{ +// Field: "Title", Msg: "is required", +// }) +// } // -// if s.Author == "" { -// // Yields the same result as the Title field check above. -// errs = validate.AppendFieldError(errs, "Author", "is required") -// } +// if s.Author == "" { +// // Yields the same result as the Title field check above. +// errs = validate.AppendFieldError(errs, "Author", "is required") +// } // -// return errs -// } +// return errs +// } // // With the above example, if you validate a empty *Book: // -// err := validate.Validate(&Book{}) -// for _, e := range validate.Errors(err) { -// fmt.Println(e.Error()) -// } +// err := validate.Validate(&Book{}) +// for _, e := range validate.Errors(err) { +// fmt.Println(e.Error()) +// } // // The following errors would be printed: // -// Title: is required -// Kind: is required +// Title: is required +// Kind: is required // -// Error type +// # Error type // // All errors will be wrapped in a *Error before being returned, which is used // to keep track of the path and field the error relates to. There are various // helpers available to create Error instances. // -// Handling Validation Errors +// # Handling Validation Errors // // As mentioned above, multiple errors are wrapped up into a single error return // value using go.uber.org/multierr. You can access all errors individually with @@ -79,7 +79,7 @@ // function is just wrapper around multierr.Errors(), so you could use that // instead if you prefer. // -// Struct Field Tags +// # Struct Field Tags // // Fields on a struct which customize the name via a json, yaml, or form field // tag, will automatically have the field name converted to the name in the tag @@ -88,7 +88,7 @@ // You can customize the field name conversion logic by creating a custom // Validator instance, and calling FieldNameFunc() on it. // -// Nested Validatable Objects +// # Nested Validatable Objects // // All items/fields on any structs, maps, slices or arrays which are encountered // will be validated if they implement the Validatable interface. While @@ -103,30 +103,30 @@ // As an example, if our Book struct from above is nested within the following // structs: // -// type Order struct { -// Items []*Item `json:"items"` -// } +// type Order struct { +// Items []*Item `json:"items"` +// } // -// type Item struct { -// Book *Book `json:"book"` -// } +// type Item struct { +// Book *Book `json:"book"` +// } // // And we have a Order where the book in the second Item has a empty Author // field: // -// err := validate.Validate(&Order{ -// Items: []*Item{ -// {Book: &Book{Title: "The Traveler", Author: "John Twelve Hawks"}}, -// {Book: &Book{Title: "The Firm"}}, -// }, -// }) -// for _, e := range validate.Errors(err) { -// fmt.Println(e.Error()) -// } +// err := validate.Validate(&Order{ +// Items: []*Item{ +// {Book: &Book{Title: "The Traveler", Author: "John Twelve Hawks"}}, +// {Book: &Book{Title: "The Firm"}}, +// }, +// }) +// for _, e := range validate.Errors(err) { +// fmt.Println(e.Error()) +// } // // Then we would get the following error: // -// items.1.book.Author: is required +// items.1.book.Author: is required // // Note how both "items" and "book" are lower cased thanks to the json tags on // the struct fields, while our Book struct does not have a json tag for the