mirror of
https://github.com/romdo/go-validate.git
synced 2026-02-18 23:56:41 +00:00
Merge pull request #7 from romdo/upgrade-ci-and-linter
This commit is contained in:
92
.github/workflows/ci.yml
vendored
92
.github/workflows/ci.yml
vendored
@@ -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
|
||||
|
||||
126
.golangci.yml
126
.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$
|
||||
|
||||
2
Makefile
2
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
|
||||
|
||||
98
validate.go
98
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
|
||||
|
||||
Reference in New Issue
Block a user