version: "2"

run:
  modules-download-mode: readonly

issues:
  max-issues-per-linter: 0
  max-same-issues: 0

linters:
  default: none
  enable:
    # 1. This is the default enabled set of golanci

    # We should consider enabling errcheck
    # - errcheck
    - govet
    - ineffassign
    - staticcheck
    - unused

    # 2. These are not part of the default set

    # Important to prevent import of certain packages
    - depguard
    # Removes unnecessary conversions
    - unconvert
    # Flag common typos
    - misspell
    # A meta-linter seen as a good replacement for golint
    - revive
    # Gocritic
    - gocritic
    - forbidigo

    # 3. We used to use these, but have now removed them

    # Use of prealloc is generally premature optimization and performance profiling should be done instead
    # https://golangci-lint.run/usage/linters/#prealloc
    # - prealloc
    # Provided by revive in a better way
    # - nakedret

  settings:
    forbidigo:
      forbid:
        # FIXME: there are still calls to os.WriteFile in tests under `cmd`
        - pattern: ^os\.WriteFile.*$
          pkg: github.com/containerd/nerdctl/v2/pkg
          msg: os.WriteFile is neither atomic nor durable - use nerdctl filesystem.WriteFile instead
        - pattern: ^os\.ReadFile.*$
          pkg: github.com/containerd/nerdctl/v2/pkg
          msg: use filesystem.ReadFile instead of os.ReadFile
    staticcheck:
      checks:
        # Below is the default set
        - "all"
        - "-ST1000"
        - "-ST1003"
        - "-ST1016"
        - "-ST1020"
        - "-ST1021"
        - "-ST1022"

        ##### TODO: fix and enable these
        # 6 occurrences.
        # Apply De Morgan’s law https://staticcheck.dev/docs/checks#QF1001
        - "-QF1001"
        # 10 occurrences.
        # Convert if/else-if chain to tagged switch https://staticcheck.dev/docs/checks#QF1003
        - "-QF1003"

        ##### These have been vetted to be disabled.
        # 55 occurrences. Omit embedded fields from selector expression https://staticcheck.dev/docs/checks#QF1008
        # Usefulness is questionable.
        - "-QF1008"

    revive:
      enable-all-rules: true
      rules:
        # See https://revive.run/r

        ##### P0: we should do it ASAP.
        - name: max-control-nesting
          # 10 occurences (at default 5). Deep nesting hurts readibility.
          arguments: [7]
        - name: deep-exit
          # 11 occurrences. Do not exit in random places.
          disabled: true
        - name: unchecked-type-assertion
          # 14 occurrences. This is generally risky and encourages bad coding for newcomers.
          disabled: true
        - name: bare-return
          # 31 occurrences. Bare returns are just evil, very unfriendly, and make reading and editing much harder.
          disabled: true
        - name: import-shadowing
          # 44 occurrences. Shadowing makes things prone to errors / confusing to read.
          disabled: true
        - name: use-errors-new
          # 84 occurrences. Improves error testing.
          disabled: true
        - name: struct-tag
          # 2 occurrences.
          disabled: true

        ##### P1: consider making a dent on these, but not critical.
        - name: argument-limit
          # 4 occurrences (at default 8). Long windy arguments list for functions are hard to read. Use structs instead.
          arguments: [12]
        - name: unnecessary-stmt
          # 5 occurrences. Increase readability.
          disabled: true
        - name: defer
          # 7 occurrences. Confusing to read for newbies.
          disabled: true
        - name: confusing-naming
          # 10 occurrences. Hurts readability.
          disabled: true
        - name: early-return
          # 10 occurrences. Would improve readability.
          disabled: true
        - name: function-result-limit
          # 12 occurrences (at default 3). A function returning many results is probably too big.
          arguments: [7]
        - name: function-length
          # 155 occurrences (at default 0, 75). Really long functions should really be broken up in most cases.
          arguments: [0, 500]
        - name: cyclomatic
          # 204 occurrences (at default 10)
          arguments: [100]
        - name: unhandled-error
          # 222 occurrences. Could indicate failure to handle broken conditions.
          disabled: true
        - name: cognitive-complexity
          arguments: [205]
          # 441 occurrences (at default 7). We should try to lower it (involves significant refactoring).
        - name: var-naming
          # 1 occurrence.
          disabled: true

        ##### P2: nice to have.
        - name: max-public-structs
          # 7 occurrences (at default 5). Might indicate overcrowding of public API.
          arguments: [25]
        - name: confusing-results
          # 13 occurrences. Have named returns when the type stutters.
          # Makes it a bit easier to figure out function behavior just looking at signature.
          disabled: true
        - name: comment-spacings
          # 50 occurrences. Makes code look less wonky / ease readability.
          disabled: true
        - name: use-any
          # 30 occurrences. `any` instead of `interface{}`. Cosmetic.
          disabled: true
        - name: empty-lines
          # 85 occurrences. Makes code look less wonky / ease readability.
          disabled: true
        - name: package-comments
          # 100 occurrences. Better for documentation...
          disabled: true
        - name: exported
          # 577 occurrences. Forces documentation of any exported symbol.
          disabled: true
        - name: unnecessary-format
          # Many occurrences.
          disabled: true

        ###### Permanently disabled. Below have been reviewed and vetted to be unnecessary.
        - name: line-length-limit
          # Formatter `golines` takes care of this.
          disabled: true
        - name: nested-structs
          # 5 occurrences. Trivial. This is not that hard to read.
          disabled: true
        - name: flag-parameter
          # 52 occurrences. Not sure if this is valuable.
          disabled: true
        - name: unused-parameter
          # 505 occurrences. A lot of work for a marginal improvement.
          disabled: true
        - name: unused-receiver
          # 31 occurrences. Ibid.
          disabled: true
        - name: add-constant
          # 2605 occurrences. Kind of useful in itself, but unacceptable amount of effort to fix
          disabled: true
        - name: enforce-switch-style
          # Many occurrences.
          disabled: true

    depguard:
      rules:
        no-patent:
          # do not link in golang-lru anywhere (problematic patent)
          deny:
            - pkg: github.com/hashicorp/golang-lru/arc/v2
              desc: patented (https://github.com/hashicorp/golang-lru/blob/arc/v2.0.7/arc/arc.go#L18)
        pkg:
          # pkg files must not depend on cobra nor anything in cmd
          files:
            - '**/pkg/**/*.go'
          deny:
            - pkg: github.com/spf13/cobra
              desc: pkg must not depend on cobra
            - pkg: github.com/spf13/pflag
              desc: pkg must not depend on pflag
            - pkg: github.com/spf13/viper
              desc: pkg must not depend on viper
            - pkg: github.com/containerd/nerdctl/v2/cmd
              desc: pkg must not depend on any cmd files
    gocritic:
      disabled-checks:
        # Below are normally enabled by default, but we do not pass
        - appendAssign
        - ifElseChain
        - unslice
        - badCall
        - assignOp
        - commentFormatting
        - captLocal
        - singleCaseSwitch
        - wrapperFunc
        - elseif
        - regexpMust
      enabled-checks:
        # Below used to be enabled, but we do not pass anymore
        # - paramTypeCombine
        # - octalLiteral
        # - unnamedResult
        # - equalFold
        # - sloppyReassign
        # - emptyStringTest
        # - hugeParam
        # - appendCombine
        # - stringXbytes
        # - ptrToRefParam
        # - commentedOutCode
        # - rangeValCopy
        # - methodExprCall
        # - yodaStyleExpr
        # - typeUnparen

        # We enabled these and we pass
        - nilValReturn
        - weakCond
        - indexAlloc
        - rangeExprCopy
        - boolExprSimplify
        - commentedOutImport
        - docStub
        - emptyFallthrough
        - hexLiteral
        - typeAssertChain
        - unlabelStmt
        - builtinShadow
        - initClause
        - nestingReduce
        - unnecessaryBlock
  exclusions:
    generated: disable

formatters:
  settings:
    gci:
      sections:
        - standard
        - default
        - prefix(github.com/containerd)
        - localmodule
      no-inline-comments: true
      no-prefix-comments: true
      custom-order: true
    gofumpt:
      extra-rules: true
    golines:
      max-len: 500
      tab-len: 4
      shorten-comments: true
  enable:
    - gci
    - gofmt
    # We might consider enabling the following:
    #    - gofumpt
    - golines
  exclusions:
    generated: disable
