[run]
deadline = "10m"
tests = true
[linters]
disable-all = true
enable = [
"asciicheck",
"bidichk",
"bodyclose",
"containedctx",
"contextcheck",
"depguard",
"durationcheck",
"errcheck",
"errchkjson",
"errname",
"errorlint",
"exhaustive",
"exportloopref",
"forbidigo",
# We tried this liner but most places we do forced type asserts are
# pretty safe, e.g., an atomic.Value when everything is encapsulated
# in a small package.
# "forcetypeassert",
"goconst",
"gocyclo",
"gocritic",
"godot",
"gofumpt",
"gomodguard",
"gosec",
"gosimple",
"govet",
"grouper",
"ineffassign",
"lll",
"makezero",
# Maintainability Index. Seems like it could be a good idea, but a
# lot of things fail and we would need to make some decisions about
# what to allow.
# "maintidx",
"misspell",
"nakedret",
"nilerr",
"noctx",
"nolintlint",
"nosprintfhostport",
"predeclared",
"revive",
"rowserrcheck",
# https://github.com/golangci/golangci-lint/issues/287
# "safesql",
"sqlclosecheck",
"staticcheck",
"stylecheck",
"tenv",
"tparallel",
"typecheck",
"unconvert",
"unparam",
"unused",
"vetshadow",
"wastedassign",
"wrapcheck",
]
# Please note that we only use depguard for stdlib as gomodguard only
# supports modules currently. See https://github.com/ryancurrah/gomodguard/issues/12
[linters-settings.depguard]
list-type = "blacklist"
include-go-root = true
packages = [
# We should use github.com/pkg/errors instead
"errors",
]
[linters-settings.errcheck]
# Ignoring Close so that we don't have to have a bunch of
# `defer func() { _ = r.Close() }()` constructs when we
# don't actually care about the error.
ignore = "Close,fmt:.*"
[linters-settings.errorlint]
errorf = true
asserts = true
comparison = true
[linters-settings.exhaustive]
default-signifies-exhaustive = true
[linters-settings.gocritic]
enabled-checks = [
"appendAssign",
"appendCombine",
"argOrder",
"assignOp",
"badCall",
"badCond",
"badLock",
"badRegexp",
"badSorting",
"boolExprSimplify",
"builtinShadow",
"builtinShadowDecl",
"captLocal",
"caseOrder",
"codegenComment",
"commentedOutCode",
"commentedOutImport",
"commentFormatting",
"defaultCaseOrder",
# Revive's defer rule already captures this. This caught no extra cases.
# "deferInLoop",
"deferUnlambda",
"deprecatedComment",
"docStub",
"dupArg",
"dupBranchBody",
"dupCase",
"dupImport",
"dupSubExpr",
"dynamicFmtString",
"elseif",
"emptyDecl",
"emptyFallthrough",
"emptyStringTest",
"equalFold",
"evalOrder",
"exitAfterDefer",
"exposedSyncMutex",
"externalErrorReassign",
# Given that all of our code runs on Linux and the / separate should
# work fine, this seems less important.
# "filepathJoin",
"flagDeref",
"flagName",
"hexLiteral",
"ifElseChain",
"importShadow",
"indexAlloc",
"initClause",
"mapKey",
"methodExprCall",
"nestingReduce",
"newDeref",
"nilValReturn",
"octalLiteral",
"offBy1",
"paramTypeCombine",
"preferDecodeRune",
"preferFilepathJoin",
"preferFprint",
"preferStringWriter",
"preferWriteByte",
"ptrToRefParam",
"rangeExprCopy",
"rangeValCopy",
"redundantSprint",
"regexpMust",
"regexpPattern",
# This might be good, but I don't think we want to encourage
# significant changes to regexes as we port stuff from Perl.
# "regexpSimplify",
"ruleguard",
"singleCaseSwitch",
"sliceClear",
"sloppyLen",
# This seems like it might also be good, but a lot of existing code
# fails.
# "sloppyReassign",
"returnAfterHttpError",
"sloppyTypeAssert",
"sortSlice",
"sprintfQuotedString",
"sqlQuery",
"stringsCompare",
"stringXbytes",
"switchTrue",
"syncMapLoadAndDelete",
"timeExprSimplify",
"todoCommentWithoutDetail",
"tooManyResultsChecker",
"truncateCmp",
"typeAssertChain",
"typeDefFirst",
"typeSwitchVar",
"typeUnparen",
"underef",
"unlabelStmt",
"unlambda",
# I am not sure we would want this linter and a lot of existing
# code fails.
# "unnamedResult",
"unnecessaryBlock",
"unnecessaryDefer",
"unslice",
"valSwap",
"weakCond",
"wrapperFunc",
"yodaStyleExpr",
# This requires explanations for "nolint" directives. This would be
# nice for gosec ones, but I am not sure we want it generally unless
# we can get the false positive rate lower.
# "whyNoLint"
]
[linters-settings.gofumpt]
extra-rules = true
lang-version = "1.17"
[linters-settings.gomodguard]
[[linters-settings.gomodguard.blocked.modules]]
[linters-settings.gomodguard.blocked.modules."github.com/avct/uasurfer"]
recommendations = ["github.com/xavivars/uasurfer"]
reason = "The original avct module appears abandoned."
[[linters-settings.gomodguard.blocked.modules]]
[linters-settings.gomodguard.blocked.modules."github.com/BurntSushi/toml"]
recommendations = ["github.com/pelletier/go-toml/v2"]
reason = "This library panics frequently on invalid input."
[[linters-settings.gomodguard.blocked.modules]]
[linters-settings.gomodguard.blocked.modules."github.com/gofrs/uuid"]
recommendations = ["github.com/google/uuid"]
[[linters-settings.gomodguard.blocked.modules]]
[linters-settings.gomodguard.blocked.modules."github.com/satori/go.uuid"]
recommendations = ["github.com/google/uuid"]
[[linters-settings.gomodguard.blocked.modules]]
[linters-settings.gomodguard.blocked.modules."github.com/lib/pq"]
recommendations = ["github.com/jackc/pgx"]
reason = "This library is no longer actively maintained."
[[linters-settings.gomodguard.blocked.modules]]
[linters-settings.gomodguard.blocked.modules."github.com/neilotoole/errgroup"]
recommendations = ["golang.org/x/sync/errgroup"]
reason = "This library can lead to subtle deadlocks in certain use cases."
[[linters-settings.gomodguard.blocked.modules]]
[linters-settings.gomodguard.blocked.modules."github.com/pariz/gountries"]
reason = "This library's data is not actively maintained. Use GeoInfo data."
[[linters-settings.gomodguard.blocked.modules]]
[linters-settings.gomodguard.blocked.modules."github.com/RackSec/srslog"]
recommendations = ["github.com/RackSec/srslog"]
reason = "This library's data is not actively maintained."
[[linters-settings.gomodguard.blocked.modules]]
[linters-settings.gomodguard.blocked.modules."github.com/ua-parser/uap-go/uaparser"]
recommendations = ["github.com/xavivars/uasurfer"]
reason = "The performance of this library is absolutely abysmal."
[[linters-settings.gomodguard.blocked.modules]]
[linters-settings.gomodguard.blocked.modules."github.com/ugorji/go/codec"]
recommendations = ["encoding/json", "github.com/mailru/easyjson"]
reason = "This library is poorly maintained. We should default to using encoding/json and use easyjson where performance really matters."
[[linters-settings.gomodguard.blocked.versions]]
[linters-settings.gomodguard.blocked.versions."github.com/jackc/pgx"]
version = "< 4.0.0"
reason = "Use github.com/jackc/pgx/v4"
[linters-settings.govet]
"enable-all" = true
[linters-settings.lll]
line-length = 120
tab-width = 4
[linters-settings.nolintlint]
allow-leading-space = false
allow-unused = false
allow-no-explanation = ["lll", "misspell"]
require-explanation = true
require-specific = true
[linters-settings.revive]
ignore-generated-header = true
severity = "warning"
# This might be nice but it is so common that it is hard
# to enable.
# [[linters-settings.revive.rules]]
# name = "add-constant"
# [[linters-settings.revive.rules]]
# name = "argument-limit"
[[linters-settings.revive.rules]]
name = "atomic"
[[linters-settings.revive.rules]]
name = "bare-return"
[[linters-settings.revive.rules]]
name = "blank-imports"
[[linters-settings.revive.rules]]
name = "bool-literal-in-expr"
[[linters-settings.revive.rules]]
name = "call-to-gc"
# [[linters-settings.revive.rules]]
# name = "cognitive-complexity"
# Probably a good rule, but we have a lot of names that
# only have case differences.
# [[linters-settings.revive.rules]]
# name = "confusing-naming"
[[linters-settings.revive.rules]]
name = "confusing-results"
[[linters-settings.revive.rules]]
name = "constant-logical-expr"
[[linters-settings.revive.rules]]
name = "context-as-argument"
[[linters-settings.revive.rules]]
name = "context-keys-type"
# [[linters-settings.revive.rules]]
# name = "cyclomatic"
[[linters-settings.revive.rules]]
name = "deep-exit"
[[linters-settings.revive.rules]]
name = "defer"
[[linters-settings.revive.rules]]
name = "dot-imports"
[[linters-settings.revive.rules]]
name = "duplicated-imports"
[[linters-settings.revive.rules]]
name = "early-return"
[[linters-settings.revive.rules]]
name = "empty-block"
[[linters-settings.revive.rules]]
name = "empty-lines"
[[linters-settings.revive.rules]]
name = "errorf"
[[linters-settings.revive.rules]]
name = "error-naming"
[[linters-settings.revive.rules]]
name = "error-return"
[[linters-settings.revive.rules]]
name = "error-strings"
[[linters-settings.revive.rules]]
name = "exported"
# [[linters-settings.revive.rules]]
# name = "file-header"
# We have a lot of flag parameters. This linter probably makes
# a good point, but we would need some cleanup or a lot of nolints.
# [[linters-settings.revive.rules]]
# name = "flag-parameter"
# [[linters-settings.revive.rules]]
# name = "function-result-limit"
[[linters-settings.revive.rules]]
name = "get-return"
[[linters-settings.revive.rules]]
name = "identical-branches"
[[linters-settings.revive.rules]]
name = "if-return"
[[linters-settings.revive.rules]]
name = "imports-blacklist"
[[linters-settings.revive.rules]]
name = "import-shadowing"
[[linters-settings.revive.rules]]
name = "increment-decrement"
[[linters-settings.revive.rules]]
name = "indent-error-flow"
# [[linters-settings.revive.rules]]
# name = "line-length-limit"
# [[linters-settings.revive.rules]]
# name = "max-public-structs"
[[linters-settings.revive.rules]]
name = "modifies-parameter"
[[linters-settings.revive.rules]]
name = "modifies-value-receiver"
# We frequently use nested structs, particularly in tests.
# [[linters-settings.revive.rules]]
# name = "nested-structs"
[[linters-settings.revive.rules]]
name = "optimize-operands-order"
[[linters-settings.revive.rules]]
name = "package-comments"
[[linters-settings.revive.rules]]
name = "range"
[[linters-settings.revive.rules]]
name = "range-val-address"
[[linters-settings.revive.rules]]
name = "range-val-in-closure"
[[linters-settings.revive.rules]]
name = "receiver-naming"
[[linters-settings.revive.rules]]
name = "redefines-builtin-id"
[[linters-settings.revive.rules]]
name = "string-of-int"
[[linters-settings.revive.rules]]
name = "struct-tag"
[[linters-settings.revive.rules]]
name = "superfluous-else"
[[linters-settings.revive.rules]]
name = "time-naming"
[[linters-settings.revive.rules]]
name = "unconditional-recursion"
[[linters-settings.revive.rules]]
name = "unexported-naming"
[[linters-settings.revive.rules]]
name = "unexported-return"
# This is covered elsewhere and we want to ignore some
# functions such as fmt.Fprintf.
# [[linters-settings.revive.rules]]
# name = "unhandled-error"
[[linters-settings.revive.rules]]
name = "unnecessary-stmt"
[[linters-settings.revive.rules]]
name = "unreachable-code"
[[linters-settings.revive.rules]]
name = "unused-parameter"
# We generally have unused receivers in tests for meeting the
# requirements of an interface.
# [[linters-settings.revive.rules]]
# name = "unused-receiver"
[[linters-settings.revive.rules]]
name = "useless-break"
[[linters-settings.revive.rules]]
name = "var-declaration"
[[linters-settings.revive.rules]]
name = "var-naming"
[[linters-settings.revive.rules]]
name = "waitgroup-by-value"
[linters-settings.unparam]
check-exported = true
[linters-settings.wrapcheck]
"ignoreSigs" = [
".Errorf(",
"errgroup.NewMultiError(",
"errors.New(",
".Wait(",
".WithMessage(",
".WithMessagef(",
".WithStack(",
".Wrap(",
".Wrapf(",
"v4.Retry(",
"v4.RetryNotify(",
]
[issues]
exclude-use-default = false
# This goes off for MD5 usage, which we use heavily
[[issues.exclude-rules]]
text = "weak cryptographic primitive"
linters = ["gosec"]
[[issues.exclude-rules]]
linters = [
"gocritic"
]
# For some reason the imports stuff in ruleguard doesn't work in golangci-lint.
# Perhaps it has an outdated version or something
path = "_test.go"
text = "ruleguard: Prefer the alternative Context method instead"
[[issues.exclude-rules]]
linters = [
"gocritic"
]
## The nolintlint linter behaves oddly with ruleguard rules
source = "// *no-ruleguard"
[[issues.exclude-rules]]
linters = [
"gosec"
]
# G306 - "Expect WriteFile permissions to be 0600 or less".
text = "G306"
[[issues.exclude-rules]]
linters = [
"govet"
]
# we want to enable almost all govet rules. It is easier to just filter out
# the ones we don't want:
#
# * fieldalignment - way too noisy. Although it is very useful in particular
# cases where we are trying to use as little memory as possible, having
# it go off on every struct isn't helpful.
# * shadow - although often useful, it complains about _many_ err
# shadowing assignments and some others where shadowing is clear.
text = "^(fieldalignment|shadow)"
[[issues.exclude-rules]]
linters = [
"govet"
]
text = "shadow: declaration of \"err\" shadows declaration"
[[issues.exclude-rules]]
linters = [
"contextcheck",
"nilerr",
"wrapcheck",
]
path = "_test.go"
[[issues.exclude-rules]]
linters = [
"stylecheck",
]
# ST1016 - methods on the same type should have the same receiver name.
# easyjson doesn't interact well with this.
text = "ST1016"
[[issues.exclude-rules]]
linters = [
"staticcheck",
]
# SA5008: unknown JSON option "intern" - easyjson specific option.
text = 'SA5008: unknown JSON option "intern"'
[[issues.exclude-rules]]
linters = [
"wrapcheck"
]
text = "github.com/maxmind/geoipupdate"
[[issues.exclude-rules]]
linters = [
"wrapcheck",
]
path = "_easyjson.go"
[[issues.exclude-rules]]
linters = [
"gocritic",
]
source = "Chmod|WriteFile"
text = "octalLiteral"