From 4098c97539d1d18848a7742907834a0c6171f6ea Mon Sep 17 00:00:00 2001 From: Kevin Franklin Kim Date: Thu, 6 Mar 2025 16:07:42 +0100 Subject: [PATCH 1/6] docs: add community templates --- .github/CONTRIBUTING.md | 21 +++++++++++++ .github/ISSUE_TEMPLATE/bug-report.md | 17 ++++++++++ .github/ISSUE_TEMPLATE/enhancement.md | 8 +++++ .github/PULL_REQUEST_TEMPLATE.md | 19 +++++++++++ .github/SECURITY.md | 45 +++++++++++++++++++++++++++ 5 files changed, 110 insertions(+) create mode 100644 .github/CONTRIBUTING.md create mode 100644 .github/ISSUE_TEMPLATE/bug-report.md create mode 100644 .github/ISSUE_TEMPLATE/enhancement.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/SECURITY.md diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..65bdbe0 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,21 @@ +# Contributing + +If you want to submit a pull request to fix a bug or enhance an existing +feature, please first open an issue and link to that issue when you +submit your pull request. + +If you have any questions about a possible submission, feel free to open +an issue too. + +### Pull request process + +1. Fork this repository +2. Create a branch in your fork to implement the changes. We recommend using + the issue number as part of your branch name, e.g. `1234-fixes` +3. Ensure that any documentation is updated with the changes that are required + by your fix. +4. Ensure that any samples are updated if the base image has been changed. +5. Submit the pull request. *Do not leave the pull request blank*. Explain exactly + what your changes are meant to do and provide simple steps on how to validate + your changes. Ensure that you reference the issue you created as well. + The pull request will be review before it is merged. diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md new file mode 100644 index 0000000..e415a86 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -0,0 +1,17 @@ +--- +name: Bug Report +about: Report a bug you encountered +labels: bug +--- +**What happened**: + +**What you expected to happen**: + +**How to reproduce it (as minimally and precisely as possible)**: + +**Anything else we need to know?**: + +**Environment**: +- Affected Version: +- OS (e.g: `cat /etc/os-release`): +- Others: diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md new file mode 100644 index 0000000..bfa7836 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/enhancement.md @@ -0,0 +1,8 @@ +--- +name: Enhancement Request +about: Suggest an enhancement +labels: enhancement +--- +**What would you like to be added**: + +**Why is this needed**: diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..1b9b846 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,19 @@ +### Type of Change +- [ ] New feature +- [ ] Bug fix +- [ ] Documentation update +- [ ] Refactoring +- [ ] Hotfix +- [ ] Security patch + +### Description +_[Provide a detailed explanation of the changes you have made. Include the reasons behind these changes and any relevant context. Link any related issues.]_ + +### Related Issue +_[If this pull request addresses an issue, please link to it here (e.g., Fixes #123).]_ + +### Checklist +- [ ] My code adheres to the coding and style guidelines of the project. +- [ ] I have performed a self-review of my own code. +- [ ] I have commented my code, particularly in hard-to-understand areas. +- [ ] I have made corresponding changes to the documentation. diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 0000000..9de3268 --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,45 @@ +# Security Guidelines + +## How security is managed on this project + +The foomo team and community take security seriously and wants to ensure that +we maintain a secure environment and provide secure solutions for the open +source community. To help us achieve these goals, please note the +following before using this software: + +- Review the software license to understand the contributor's obligations in + terms of warranties and suitability for purpose +- For any questions or concerns about security, you can + [create an issue][new-issue] or [report a vulnerability][new-sec-issue] +- We request that you work with our security team and opt for + responsible disclosure using the guidelines below +- All security related issues and pull requests you make should be tagged with + "security" for easy identification +- Please monitor this repository and update your environment in a timely manner + as we release patches and updates + +## Responsibly Disclosing Security Bugs + +If you find a security bug in this repository, please work with contributors +following responsible disclosure principles and these guidelines: + +- Do not submit a normal issue or pull request in our public repository, instead + [report it directly][new-sec-issue]. +- We will review your submission and may follow up for additional details +- If you have a patch, we will review it and approve it privately; once approved + for release you can submit it as a pull request publicly in the repository (we + give credit where credit is due) +- We will keep you informed during our investigation, feel free to check in for + a status update +- We will release the fix and publicly disclose the issue as soon as possible, + but want to ensure we due properly due diligence before releasing +- Please do not publicly blog or post about the security issue until after we + have updated the public repo so that other downstream users have an opportunity + to patch + +## Contact / Misc + +If you have any questions, please reach out directly by [creating an issue][new-issue]. + +[new-issue]: https://github.com/foomo/gotsrpc/issues/new/choose +[new-sec-issue]: https://github.com/foomo/gotsrpc/security/advisories/new From a8f572ab269f4d3b1d414026754676c58049e425 Mon Sep 17 00:00:00 2001 From: Kevin Franklin Kim Date: Thu, 6 Mar 2025 16:07:58 +0100 Subject: [PATCH 2/6] chore: update golangci lint --- .golangci.yaml | 163 ++++++++++++++++++++++++++++--------------------- 1 file changed, 92 insertions(+), 71 deletions(-) diff --git a/.golangci.yaml b/.golangci.yaml index c2e7ab7..4ab8930 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -1,6 +1,10 @@ -# Minimum golangci-lint version required: v1.42.0 +# yaml-language-server: $schema=https://golangci-lint.run/jsonschema/golangci.jsonschema.json +# https://golangci-lint.run/usage/configuration/ + run: - timeout: 5m + go: 1.23.0 + build-tags: [safe] + modules-download-mode: readonly linters-settings: revive: @@ -43,103 +47,120 @@ linters-settings: bson: camel linters: + disable-all: true enable: - # Enabled by default linters: - - errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases [fast: false, auto-fix: false] - - gosimple # (megacheck): Linter for Go source code that specializes in simplifying code [fast: false, auto-fix: false] - - govet # (vet, vetshadow): Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string [fast: false, auto-fix: false] + ## Default linters + - errcheck # errcheck is a program for checking for unchecked errors in Go code. These unchecked errors can be critical bugs in some cases [fast: false, auto-fix: false] + - gosimple # (megacheck) Linter for Go source code that specializes in simplifying code [fast: false, auto-fix: false] + - govet # (vet, vetshadow) Vet examines Go source code and reports suspicious constructs. It is roughly the same as 'go vet' and uses its passes. [fast: false, auto-fix: false] - ineffassign # Detects when assignments to existing variables are not used [fast: true, auto-fix: false] - - staticcheck # (megacheck): It's a set of rules from staticcheck. It's not the same thing as the staticcheck binary. The author of staticcheck doesn't support or approve the use of staticcheck as a library inside golangci-lint. [fast: false, auto-fix: false] - - typecheck # Like the front-end of a Go compiler, parses and type-checks Go code [fast: false, auto-fix: false] - - unused # (megacheck): Checks Go code for unused constants, variables, functions and types [fast: false, auto-fix: false] - - # Disabled by default linters: - #- canonicalheader # canonicalheader checks whether net/http.Header uses canonical header [fast: false, auto-fix: false] - #- dupword # checks for duplicate words in the source code [fast: true, auto-fix: false] - #- fatcontext # detects nested contexts in loops and function literals [fast: false, auto-fix: false] - #- iface # Detect the incorrect use of interfaces, helping developers avoid interface pollution. [fast: false, auto-fix: false] - #- interfacebloat # A linter that checks the number of methods inside an interface. [fast: true, auto-fix: false] - #- perfsprint # Checks that fmt.Sprintf can be replaced with a faster alternative. [fast: false, auto-fix: false] - #- reassign # Checks that package variables are not reassigned [fast: false, auto-fix: false] - #- recvcheck # checks for receiver type consistency [fast: false, auto-fix: false] - #- sloglint # ensure consistent code style when using log/slog [fast: false, auto-fix: false] - #- tagalign # check that struct tags are well aligned [fast: true, auto-fix: true] - #- zerologlint # Detects the wrong usage of `zerolog` that a user forgets to dispatch with `Send` or `Msg` [fast: false, auto-fix: false] - + - staticcheck # (megacheck) It's a set of rules from staticcheck. It's not the same thing as the staticcheck binary. The author of staticcheck doesn't support or approve the use of staticcheck as a library inside golangci-lint. [fast: false, auto-fix: false] + - unused # (megacheck) Checks Go code for unused constants, variables, functions and types [fast: false, auto-fix: false] + ## Recommended linters - asasalint # check for pass []any as any in variadic func(...any) [fast: false, auto-fix: false] - - asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers [fast: true, auto-fix: false] + - asciicheck # checks that all code identifiers does not have non-ASCII symbols in the name [fast: true, auto-fix: false] - bidichk # Checks for dangerous unicode character sequences [fast: true, auto-fix: false] - bodyclose # checks whether HTTP response body is closed successfully [fast: false, auto-fix: false] + - canonicalheader # checks whether net/http.Header uses canonical header [fast: false, auto-fix: false] #- containedctx # containedctx is a linter that detects struct contained context.Context field [fast: true, auto-fix: false] - #- contextcheck # check the function whether to use a non-inherited context [fast: false, auto-fix: false] - #- cyclop # checks function and package cyclomatic complexity [fast: false, auto-fix: false] + #- contextcheck # check whether the function uses a non-inherited context [fast: false, auto-fix: false] + - copyloopvar # (go >= 1.22) copyloopvar is a linter detects places where loop variables are copied [fast: true, auto-fix: false] - decorder # check declaration order and count of types, constants, variables and functions [fast: true, auto-fix: false] - #- depguard # Go linter that checks if package imports are in a list of acceptable packages [fast: true, auto-fix: false] - - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) [fast: true, auto-fix: false] - #- dupl # Tool for code clone detection [fast: true, auto-fix: false] - durationcheck # check for two durations multiplied together [fast: false, auto-fix: false] - - 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. [fast: false, auto-fix: false] + - errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and reports occations, where the check for the returned error can be omitted. [fast: false, auto-fix: false] - errname # Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`. [fast: false, auto-fix: false] - errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. [fast: false, auto-fix: false] - exhaustive # check exhaustiveness of enum switch statements [fast: false, auto-fix: false] - #- exhaustruct # Checks if all structure fields are initialized [fast: false, auto-fix: false] + - exptostd # Detects functions from golang.org/x/exp/ that can be replaced by std functions. [auto-fix] + - fatcontext # detects nested contexts in loops and function literals [fast: false, auto-fix: false] #- forbidigo # Forbids identifiers [fast: true, auto-fix: false] - forcetypeassert # finds forced type assertions [fast: true, auto-fix: false] - #- funlen # Tool for detection of long functions [fast: true, auto-fix: false] - #- gci # Gci controls golang package import order and makes it always deterministic. [fast: true, auto-fix: false] - #- gochecknoglobals # check that no global variables exist [fast: true, auto-fix: false] - #- gochecknoinits # Checks that no init functions are present in Go code [fast: true, auto-fix: false] - #- gocognit # Computes and checks the cognitive complexity of functions [fast: true, auto-fix: false] + - gocheckcompilerdirectives # Checks that go compiler directive comments (//go:) are valid. [fast: true, auto-fix: false] + - gochecksumtype # Run exhaustiveness checks on Go "sum types" [fast: false, auto-fix: false] #- goconst # Finds repeated strings that could be replaced by a constant [fast: true, auto-fix: false] - - gocritic # Provides diagnostics that check for bugs, performance and style issues. [fast: false, auto-fix: false] - #- gocyclo # Computes and checks the cyclomatic complexity of functions [fast: true, auto-fix: false] - #- godot # Check if comments end in a period [fast: true, auto-fix: true] - #- godox # Tool for detection of FIXME, TODO and other comment keywords [fast: true, auto-fix: false] - #- err113: Go linter to check the errors handling expressions [fast: false, auto-fix: false] + - gocritic # Provides diagnostics that check for bugs, performance and style issues. [fast: false, auto-fix: true] - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification [fast: true, auto-fix: true] - #- gofumpt # Gofumpt checks whether code was gofumpt-ed. [fast: true, auto-fix: true] - - goheader # Checks is file header matches to pattern [fast: true, auto-fix: false] - - goimports # In addition to fixing imports, goimports also formats your code in the same style as gofmt. [fast: true, auto-fix: true] - #- mnd: An analyzer to detect magic numbers. [fast: true, auto-fix: false] - #- gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. [fast: true, auto-fix: false] + - goheader # Checks is file header matches to pattern [fast: true, auto-fix: true] + - goimports # Check import statements are formatted according to the 'goimport' command. Reformat imports in autofix mode. [fast: true, auto-fix: true] + - gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. [fast: true, auto-fix: false] - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. [fast: true, auto-fix: false] - - goprintffuncname # Checks that printf-like functions are named with `f` at the end [fast: true, auto-fix: false] - - gosec # (gas): Inspects source code for security problems [fast: false, auto-fix: false] - - grouper # An analyzer to analyze expression groups. [fast: true, auto-fix: false] + - goprintffuncname # Checks that printf-like functions are named with `f` at the end. [fast: true, auto-fix: false] + - gosec # (gas) Inspects source code for security problems [fast: false, auto-fix: false] + #- gosmopolitan # Report certain i18n/l10n anti-patterns in your Go codebase [fast: false, auto-fix: false] + - grouper # Analyze expression groups. [fast: true, auto-fix: false] + - iface # Detect the incorrect use of interfaces, helping developers avoid interface pollution. [fast: false, auto-fix: false] - importas # Enforces consistent import aliases [fast: false, auto-fix: false] - #- ireturn # Accept Interfaces, Return Concrete Types [fast: false, auto-fix: false] - #- lll # Reports long lines [fast: true, auto-fix: false] - - maintidx # maintidx measures the maintainability index of each function. [fast: true, auto-fix: false] + - inamedparam # reports interfaces with unnamed method parameters [fast: true, auto-fix: false] + - loggercheck # (logrlint) Checks key value pairs for common logger libraries (kitlog,klog,logr,zap). [fast: false, auto-fix: false] - makezero # Finds slice declarations with non-zero initial length [fast: false, auto-fix: false] - - misspell # Finds commonly misspelled English words in comments [fast: true, auto-fix: true] - #- nakedret # Finds naked returns in functions greater than a specified function length [fast: true, auto-fix: false] - #- nestif # Reports deeply nested if statements [fast: true, auto-fix: false] + - mirror # reports wrong mirror patterns of bytes/strings usage [fast: false, auto-fix: true] + - misspell # Finds commonly misspelled English words [fast: true, auto-fix: true] + - musttag # enforce field tags in (un)marshaled structs [fast: false, auto-fix: false] + #- nakedret # Checks that functions with naked returns are not longer than a maximum size (can be zero). [fast: true, auto-fix: false] - nilerr # Finds the code that returns nil even if it checks that the error is not nil. [fast: false, auto-fix: false] + - nilnesserr # Reports constructs that checks for err != nil, but returns a different nil value error. - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. [fast: false, auto-fix: false] - #- nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity [fast: true, auto-fix: false] - - noctx # noctx finds sending http request without context.Context [fast: false, auto-fix: false] - - nolintlint # Reports ill-formed or insufficient nolint directives [fast: true, auto-fix: false] + - noctx # Finds sending http request without context.Context [fast: false, auto-fix: false] + - nolintlint # Reports ill-formed or insufficient nolint directives [fast: true, auto-fix: true] #- nonamedreturns # Reports all named returns [fast: false, auto-fix: false] - nosprintfhostport # Checks for misuse of Sprintf to construct a host with port in a URL. [fast: true, auto-fix: false] - #- paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test [fast: false, auto-fix: false] - #- prealloc # Finds slice declarations that could potentially be pre-allocated [fast: true, auto-fix: false] + #- paralleltest # Detects missing usage of t.Parallel() method in your Go test [fast: false, auto-fix: false] - predeclared # find code that shadows one of Go's predeclared identifiers [fast: true, auto-fix: false] - promlinter # Check Prometheus metrics naming via promlint [fast: true, auto-fix: false] + - reassign # Checks that package variables are not reassigned [fast: false, auto-fix: false] + - recvcheck # checks for receiver type consistency [fast: false, auto-fix: false] - revive # Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint. [fast: false, auto-fix: false] - - rowserrcheck # checks whether Err of rows is checked successfully [fast: false, auto-fix: false] - - sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. [fast: false, auto-fix: false] + - rowserrcheck # checks whether Rows.Err of rows is checked successfully [fast: false, auto-fix: false] + - spancheck # Checks for mistakes with OpenTelemetry/Census spans. [fast: false, auto-fix: false] + - sqlclosecheck # Checks that sql.Rows, sql.Stmt, sqlx.NamedStmt, pgx.Query are closed. [fast: false, auto-fix: false] - stylecheck # Stylecheck is a replacement for golint [fast: false, auto-fix: false] - #- tagliatelle # Checks the struct tags. [fast: true, auto-fix: false] + - testableexamples # linter checks if examples are testable (have an expected output) [fast: true, auto-fix: false] + - testifylint # Checks usage of github.com/stretchr/testify. [fast: false, auto-fix: false] #- testpackage # linter that makes you use a separate _test package [fast: true, auto-fix: false] - - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers [fast: false, auto-fix: false] - - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes [fast: false, auto-fix: false] + - thelper # thelper detects tests helpers which is not start with t.Helper() method. [fast: false, auto-fix: false] + - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes. [fast: false, auto-fix: false] - unconvert # Remove unnecessary type conversions [fast: false, auto-fix: false] - #- unparam # Reports unused function parameters [fast: false, auto-fix: false] - usestdlibvars # A linter that detect the possibility to use variables/constants from the Go standard library. [fast: true, auto-fix: false] - #- varnamelen # checks that the length of a variable's name matches its scope [fast: false, auto-fix: false] - - wastedassign # wastedassign finds wasted assignment statements. [fast: false, auto-fix: false] - - whitespace # Tool for detection of leading and trailing whitespace [fast: true, auto-fix: true] - #- wrapcheck # Checks that errors returned from external packages are wrapped [fast: false, auto-fix: false] - #- wsl # Whitespace Linter - Forces you to use empty lines! [fast: true, auto-fix: false] + - usetesting # Reports uses of functions with replacement inside the testing package. [auto-fix] + - wastedassign # Finds wasted assignment statements [fast: false, auto-fix: false] + - whitespace # Whitespace is a linter that checks for unnecessary newlines at the start and end of functions, if, for, etc. [fast: true, auto-fix: true] + ## Discouraged linters + #- cyclop # checks function and package cyclomatic complexity [fast: false, auto-fix: false] + #- depguard # Go linter that checks if package imports are in a list of acceptable packages [fast: true, auto-fix: false] + #- dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) [fast: true, auto-fix: false] + #- dupl # Tool for code clone detection [fast: true, auto-fix: false] + #- dupword # checks for duplicate words in the source code [fast: true, auto-fix: false] + #- dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) [fast: true, auto-fix: false] + #- err113 # Go linter to check the errors handling expressions [fast: false, auto-fix: false] + #- exhaustruct # Checks if all structure fields are initialized [fast: false, auto-fix: false] + #- funlen # Tool for detection of long functions [fast: true, auto-fix: false] + #- gci # Gci controls Go package import order and makes it always deterministic. [fast: true, auto-fix: true] + #- ginkgolinter # enforces standards of using ginkgo and gomega [fast: false, auto-fix: false] + #- gochecknoglobals # Check that no global variables exist. [fast: false, auto-fix: false] + #- gochecknoinits # Checks that no init functions are present in Go code [fast: true, auto-fix: false] + #- gocognit # Computes and checks the cognitive complexity of functions [fast: true, auto-fix: false] + #- gocyclo # Computes and checks the cyclomatic complexity of functions [fast: true, auto-fix: false] + #- godot # Check if comments end in a period [fast: true, auto-fix: true] + #- godox # Tool for detection of comment keywords [fast: true, auto-fix: false] + #- gofumpt # Gofumpt checks whether code was gofumpt-ed. [fast: true, auto-fix: true] + #- interfacebloat # A linter that checks the number of methods inside an interface. [fast: true, auto-fix: false] + #- intrange # (go >= 1.22) intrange is a linter to find places where for loops could make use of an integer range. [fast: true, auto-fix: false] + #- ireturn # Accept Interfaces, Return Concrete Types [fast: false, auto-fix: false] + #- lll # Reports long lines [fast: true, auto-fix: false] + #- maintidx # maintidx measures the maintainability index of each function. [fast: true, auto-fix: false] + #- nestif # Reports deeply nested if statements [fast: true, auto-fix: false] + #- nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity [fast: true, auto-fix: false] + #- mnd # An analyzer to detect magic numbers. [fast: true, auto-fix: false] + #- perfsprint # Checks that fmt.Sprintf can be replaced with a faster alternative. [fast: false, auto-fix: false] + #- prealloc # Finds slice declarations that could potentially be pre-allocated [fast: true, auto-fix: false] + #- protogetter # Reports direct reads from proto message fields when getters should be used [fast: false, auto-fix: true] + #- sloglint # ensure consistent code style when using log/slog [fast: false, auto-fix: false] + #- tagalign # check that struct tags are well aligned [fast: true, auto-fix: true] + #- tagliatelle # Checks the struct tags. [fast: true, auto-fix: false] + #- unparam # Reports unused function parameters [fast: false, auto-fix: false] + #- varnamelen # checks that the length of a variable's name matches its scope [fast: false, auto-fix: false] + #- wrapcheck # Checks that errors returned from external packages are wrapped [fast: false, auto-fix: false] + #- wsl # add or remove empty lines [fast: true, auto-fix: false] + #- zerologlint # Detects the wrong usage of `zerolog` that a user forgets to dispatch with `Send` or `Msg` [fast: false, auto-fix: false] From 6f0cb501fa88a9d65e48306bb9186b2d16b59283 Mon Sep 17 00:00:00 2001 From: Kevin Franklin Kim Date: Thu, 6 Mar 2025 16:08:04 +0100 Subject: [PATCH 3/6] chore: update go releaser --- .goreleaser.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 328dcce..1ff4252 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,5 +1,5 @@ -# .goreleaser.yml -# Build customization +version: 2 + builds: - binary: gotsrpc main: ./cmd/gotsrpc/gotsrpc.go @@ -32,7 +32,6 @@ changelog: use: github-native brews: - # Reporitory to push the tap to. - repository: owner: foomo name: homebrew-tap From 0a3551cb98500de7f40d97104e3340c5f29d1910 Mon Sep 17 00:00:00 2001 From: Kevin Franklin Kim Date: Thu, 6 Mar 2025 16:08:43 +0100 Subject: [PATCH 4/6] fix: struct error --- error.go | 16 +++++++++--- example/errors/handler/backend/handler.go | 25 +++++++++++++++++++ example/errors/main.go | 22 ++++++++++++++++ example/errors/service/backend/gotsrpc_gen.go | 19 ++++++++++++++ .../service/backend/gotsrpcclient_gen.go | 11 ++++++++ example/errors/service/backend/service.go | 1 + gotsrpc.go | 2 +- transport.go | 8 ++++-- 8 files changed, 97 insertions(+), 7 deletions(-) diff --git a/error.go b/error.go index 6a5bfe3..3e7b33a 100644 --- a/error.go +++ b/error.go @@ -34,11 +34,15 @@ func NewError(err error) *Error { // retrieve error details errType := reflect.TypeOf(err) + errElem := errType + if errType.Kind() == reflect.Ptr { + errElem = errType.Elem() + } inst := &Error{ Msg: err.Error(), Type: errType.String(), - Pkg: errType.Elem().PkgPath(), + Pkg: errElem.PkgPath(), Data: err, } @@ -80,9 +84,9 @@ func (e *Error) Format(s fmt.State, verb rune) { switch verb { case 'v': if s.Flag('+') { - fmt.Fprintf(s, "%s.(%s)\n", e.Pkg, e.Type) + _, _ = fmt.Fprintf(s, "%s.(%s)\n", e.Pkg, e.Type) if e.Data != nil { - fmt.Fprintf(s, "Data: %v\n", e.Data) + _, _ = fmt.Fprintf(s, "Data: %v\n", e.Data) } } fallthrough @@ -106,10 +110,14 @@ func (e *Error) Is(err error) bool { } errType := reflect.TypeOf(err) + errElem := errType + if errType.Kind() == reflect.Ptr { + errElem = errType.Elem() + } if e.Msg == err.Error() && errType.String() == e.Type && - errType.Elem().PkgPath() == e.Pkg { + errElem.PkgPath() == e.Pkg { return true } diff --git a/example/errors/handler/backend/handler.go b/example/errors/handler/backend/handler.go index 31443d1..3f86065 100644 --- a/example/errors/handler/backend/handler.go +++ b/example/errors/handler/backend/handler.go @@ -10,6 +10,14 @@ import ( type ( ScalarError string + StructError struct { + Msg string + Map map[string]string + Slice []string + Struct struct { + A string + } + } CustomError struct { Msg string Map map[string]string @@ -33,6 +41,19 @@ func (e *ScalarError) Error() string { return string(*e) } +func NewStructError(msg string) StructError { + return StructError{ + Msg: msg, + Map: map[string]string{"a": "b"}, + Slice: []string{"a", "b"}, + Struct: struct{ A string }{A: "b"}, + } +} + +func (e StructError) Error() string { + return e.Msg +} + func NewCustomError(msg string) *CustomError { return &CustomError{ Msg: msg, @@ -86,6 +107,10 @@ func (h *Handler) TypedError(w http.ResponseWriter, r *http.Request) (e error) { return ErrTyped } +func (h *Handler) StructError(w http.ResponseWriter, r *http.Request) (e error) { + return NewStructError("struct error") +} + func (h *Handler) ScalarError(w http.ResponseWriter, r *http.Request) (e error) { return NewScalarError(ScalarErrorOne) } diff --git a/example/errors/main.go b/example/errors/main.go index e0317d0..3f8174b 100644 --- a/example/errors/main.go +++ b/example/errors/main.go @@ -147,6 +147,28 @@ func call() { } } + { + fmt.Println("--- StructError ----------------") + var structErr backend.StructError + var gotsrpcErr *gotsrpc.Error + serviceErr, err := c.StructError(ctx) + if err != nil { + panic("client error should be nil") + } else if serviceErr == nil { + panic("service error should not be nil") + } else if serviceErr != nil { + fmt.Printf("%s\n", serviceErr) + fmt.Printf("%q\n", serviceErr) + fmt.Printf("%+v\n", serviceErr) + } + if errors.As(serviceErr, &gotsrpcErr) { + fmt.Println(gotsrpcErr) + } + if errors.As(serviceErr, &structErr) { + fmt.Println(structErr) + } + } + { fmt.Println("--- CustomError ----------------") var customErr *backend.CustomError diff --git a/example/errors/service/backend/gotsrpc_gen.go b/example/errors/service/backend/gotsrpc_gen.go index efe58fb..3a7f7aa 100644 --- a/example/errors/service/backend/gotsrpc_gen.go +++ b/example/errors/service/backend/gotsrpc_gen.go @@ -17,6 +17,7 @@ const ( ServiceGoTSRPCProxyScalar = "Scalar" ServiceGoTSRPCProxyScalarError = "ScalarError" ServiceGoTSRPCProxyStruct = "Struct" + ServiceGoTSRPCProxyStructError = "StructError" ServiceGoTSRPCProxyTypedCustomError = "TypedCustomError" ServiceGoTSRPCProxyTypedError = "TypedError" ServiceGoTSRPCProxyTypedScalarError = "TypedScalarError" @@ -164,6 +165,24 @@ func (p *ServiceGoTSRPCProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) } gotsrpc.Monitor(w, r, args, rets, callStats) return + case ServiceGoTSRPCProxyStructError: + var ( + args []interface{} + rets []interface{} + ) + executionStart := time.Now() + rw := gotsrpc.ResponseWriter{ResponseWriter: w} + structErrorE := p.service.StructError(&rw, r) + callStats.Execution = time.Since(executionStart) + if rw.Status() == http.StatusOK { + rets = []interface{}{structErrorE} + if err := gotsrpc.Reply(rets, callStats, r, w); err != nil { + gotsrpc.ErrorCouldNotReply(w) + return + } + } + gotsrpc.Monitor(w, r, args, rets, callStats) + return case ServiceGoTSRPCProxyTypedCustomError: var ( args []interface{} diff --git a/example/errors/service/backend/gotsrpcclient_gen.go b/example/errors/service/backend/gotsrpcclient_gen.go index 928d243..c67658b 100644 --- a/example/errors/service/backend/gotsrpcclient_gen.go +++ b/example/errors/service/backend/gotsrpcclient_gen.go @@ -17,6 +17,7 @@ type ServiceGoTSRPCClient interface { Scalar(ctx go_context.Context) (e *ScalarError, clientErr error) ScalarError(ctx go_context.Context) (e error, clientErr error) Struct(ctx go_context.Context) (e *StructError, clientErr error) + StructError(ctx go_context.Context) (e error, clientErr error) TypedCustomError(ctx go_context.Context) (e error, clientErr error) TypedError(ctx go_context.Context) (e error, clientErr error) TypedScalarError(ctx go_context.Context) (e error, clientErr error) @@ -105,6 +106,16 @@ func (tsc *HTTPServiceGoTSRPCClient) Struct(ctx go_context.Context) (e *StructEr return } +func (tsc *HTTPServiceGoTSRPCClient) StructError(ctx go_context.Context) (e error, clientErr error) { + args := []interface{}{} + reply := []interface{}{&e} + clientErr = tsc.Client.Call(ctx, tsc.URL, tsc.EndPoint, "StructError", args, reply) + if clientErr != nil { + clientErr = pkg_errors.WithMessage(clientErr, "failed to call backend.ServiceGoTSRPCProxy StructError") + } + return +} + func (tsc *HTTPServiceGoTSRPCClient) TypedCustomError(ctx go_context.Context) (e error, clientErr error) { args := []interface{}{} reply := []interface{}{&e} diff --git a/example/errors/service/backend/service.go b/example/errors/service/backend/service.go index 7fe19bf..879a46c 100644 --- a/example/errors/service/backend/service.go +++ b/example/errors/service/backend/service.go @@ -54,6 +54,7 @@ type Service interface { Scalar(w http.ResponseWriter, r *http.Request) (e *ScalarError) MultiScalar(w http.ResponseWriter, r *http.Request) (e *MultiScalar) Struct(w http.ResponseWriter, r *http.Request) (e *StructError) + StructError(w http.ResponseWriter, r *http.Request) (e error) TypedError(w http.ResponseWriter, r *http.Request) (e error) ScalarError(w http.ResponseWriter, r *http.Request) (e error) CustomError(w http.ResponseWriter, r *http.Request) (e error) diff --git a/gotsrpc.go b/gotsrpc.go index fa18217..01345a7 100644 --- a/gotsrpc.go +++ b/gotsrpc.go @@ -120,7 +120,7 @@ func Reply(response []interface{}, stats *CallStats, r *http.Request, w http.Res if len(response) > 0 { errResp := response[len(response)-1] if v, ok := errResp.(error); ok && v != nil { - if !reflect.ValueOf(v).IsNil() { + if !reflect.ValueOf(v).IsZero() { stats.ErrorCode = 1 stats.ErrorType = fmt.Sprintf("%T", v) stats.ErrorMessage = v.Error() diff --git a/transport.go b/transport.go index ea07faf..8ea7d95 100644 --- a/transport.go +++ b/transport.go @@ -33,7 +33,7 @@ var msgpackClientHandle = &clientHandle{ beforeEncodeReply: func(resp *[]interface{}) error { for k, v := range *resp { if e, ok := v.(error); ok { - if r := reflect.ValueOf(e); !r.IsNil() { + if r := reflect.ValueOf(e); !r.IsZero() { (*resp)[k] = NewError(e) } } @@ -43,7 +43,11 @@ var msgpackClientHandle = &clientHandle{ beforeDecodeReply: func(reply []interface{}) ([]interface{}, error) { ret := make([]interface{}, len(reply)) for k, v := range reply { - if reflect.TypeOf(v).Elem().Implements(errorType) { + val := reflect.TypeOf(v) + if val.Kind() == reflect.Ptr { + val = val.Elem() + } + if val.Implements(errorType) { var e *Error ret[k] = e } else { From 06f45162563e923410b2d8d2f32af1cd8b3828fe Mon Sep 17 00:00:00 2001 From: Kevin Franklin Kim Date: Thu, 6 Mar 2025 16:08:57 +0100 Subject: [PATCH 5/6] fix: lint issues --- README.md | 2 +- client.go | 2 +- client_test.go | 9 +++++---- config/config_test.go | 5 +++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f280759..c215b2d 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Release downloads: ## How to Contribute -Make a pull request... +Please refer to the [CONTRIBUTING](.gihub/CONTRIBUTING.md) details and follow the [CODE_OF_CONDUCT](.gihub/CODE_OF_CONDUCT.md) and [SECURITY](.github/SECURITY.md) guidelines. ## License diff --git a/client.go b/client.go index 9d937c9..67ee8bf 100644 --- a/client.go +++ b/client.go @@ -12,7 +12,7 @@ import ( ) const ( - HeaderServiceToService = "X-Foomo-S2S" + HeaderServiceToService = "X-Foomo-S2s" ) // ClientTransport to use for calls diff --git a/client_test.go b/client_test.go index 35f08ce..f6f4b5a 100644 --- a/client_test.go +++ b/client_test.go @@ -6,20 +6,21 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_newRequest(t *testing.T) { t.Run("custom headers", func(t *testing.T) { headers := http.Header{} - headers.Set("test", "test") + headers.Set("Test", "test") request, err := newRequest(context.Background(), "/test", "text/html", nil, headers) - assert.NoError(t, err) - assert.Equal(t, "test", request.Header.Get("test")) + require.NoError(t, err) + assert.Equal(t, "test", request.Header.Get("Test")) }) t.Run("default", func(t *testing.T) { request, err := newRequest(context.Background(), "/test", "text/html", nil, nil) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "/test", request.URL.Path) assert.Equal(t, "text/html", request.Header.Get("Accept")) assert.Equal(t, "text/html", request.Header.Get("Content-Type")) diff --git a/config/config_test.go b/config/config_test.go index b106e78..fad3da1 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const sampleConf = `--- @@ -70,13 +71,13 @@ func TestLoadConfig(t *testing.T) { func TestLoadConfigFile_GomodAbsolute(t *testing.T) { config, err := LoadConfigFile("testdata/gomod.absolute.yml") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "/go/src/github.com/foomo/gotsrpc", config.Module.Path) } func TestLoadConfigFile_GomodRelative(t *testing.T) { config, err := LoadConfigFile("testdata/gomod.relative.yml") - assert.NoError(t, err) + require.NoError(t, err) fmt.Println(config.Module.Path) assert.True(t, strings.HasSuffix(config.Module.Path, "gotsrpc/config/demo")) } From f91bc6c74422d1b4043efc394b6110750c94471a Mon Sep 17 00:00:00 2001 From: Kevin Franklin Kim Date: Thu, 6 Mar 2025 16:09:06 +0100 Subject: [PATCH 6/6] feat: bump deps --- go.mod | 14 +++++++------- go.sum | 32 ++++++++++++++++---------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/go.mod b/go.mod index c357af9..71704a3 100644 --- a/go.mod +++ b/go.mod @@ -7,12 +7,12 @@ require ( github.com/iancoleman/strcase v0.2.0 // Be aware of https://github.com/iancoleman/strcase/pull/49 github.com/mitchellh/mapstructure v1.5.0 github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.20.5 + github.com/prometheus/client_golang v1.21.1 github.com/stretchr/testify v1.10.0 github.com/ugorji/go/codec v1.2.12 github.com/valyala/gorpc v0.0.0-20160519171614-908281bef774 - golang.org/x/mod v0.23.0 - golang.org/x/tools v0.30.0 + golang.org/x/mod v0.24.0 + golang.org/x/tools v0.31.0 gopkg.in/yaml.v2 v2.4.0 ) @@ -23,10 +23,10 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect - golang.org/x/sync v0.11.0 // indirect - golang.org/x/sys v0.30.0 // indirect - google.golang.org/protobuf v1.34.2 // indirect + golang.org/x/sync v0.12.0 // indirect + golang.org/x/sys v0.31.0 // indirect + google.golang.org/protobuf v1.36.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 5c13846..219a4a1 100644 --- a/go.sum +++ b/go.sum @@ -9,8 +9,8 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= -github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -23,12 +23,12 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= -github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk= +github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= -github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= +github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= @@ -39,16 +39,16 @@ github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65E github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/valyala/gorpc v0.0.0-20160519171614-908281bef774 h1:SUHFQHAaySqF0YHCmmm0EIFooFZpDPpi5KTom7YJ07c= github.com/valyala/gorpc v0.0.0-20160519171614-908281bef774/go.mod h1:8uNqM1i7pr0jO7gdvbNCgsSa8Ki2vMh7JCQxO9BlF90= -golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= -golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= -golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= -golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= -golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= -golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= +golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= +golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= +google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= +google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=