Результаты golangci-lint различаются для одного и того же файла.

Вопрос или проблема

У меня есть форк программного обеспечения Polygon Edge, разработанного на Go v1.20. Проект использует golangci-lint в своих рабочих процессах GitHub Actions. Я включил golangci-lint, но сначала запустил его вручную как на оригинальном, так и на форкнутом проектах, чтобы сравнить результаты.

В оригинальном проекте ошибок не найдено. Однако в форкнутом проекте появилось множество ошибок — даже для идентичных файлов, что довольно необычно. Вот код из одного из затронутых файлов:

//nolint:forcetypeassert
package evm

import (
...
)

...

func opExp(c *state) {
    x := c.pop()
    y := c.top()

    var gas uint64
    if c.config.EIP158 {
        gas = 50
    } else {
        gas = 10
    }

    gasCost := uint64((y.BitLen()+7)/8) * gas
    if !c.consumeGas(gasCost) {
        return
    }

    z := acquireBig().Set(one)

    // https://www.programminglogic.com/fast-exponentiation-algorithms/
    for _, d := range y.Bits() {
        for i := 0; i < _W; i++ {
            if d&1 == 1 {
                toU256(z.Mul(z, x))
            }

            d >>= 1

            toU256(x.Mul(x, x))
        }
    }

    y.Set(z)
    releaseBig(z)
}

func opAddMod(c *state) {
    a := c.pop()
    b := c.pop()
    z := c.top()

    if z.Sign() == 0 {
        // деление на ноль
        z.Set(zero)
    } else {
        a = a.Add(a, b)
        z = z.Mod(a, z)
        toU256(z)
    }
}

func opMulMod(c *state) {
    a := c.pop()
    b := c.pop()
    z := c.top()

    if z.Sign() == 0 {
        // деление на ноль
        z.Set(zero)
    } else {
        a = a.Mul(a, b)
        z = z.Mod(a, z)
        toU256(z)
    }
}

func opAnd(c *state) {
    a := c.pop()
    b := c.top()

    b.And(a, b)
}

func opOr(c *state) {
    a := c.pop()
    b := c.top()

    b.Or(a, b)
}

func opXor(c *state) {
    a := c.pop()
    b := c.top()

    b.Xor(a, b)
}

var opByteMask = big.NewInt(255)

func opByte(c *state) {
    x := c.pop()
    y := c.top()

    indx := x.Int64()
    if indx > 31 {
        y.Set(zero)
    } else {
                sh := (31 - indx) * 8
line,220:       y.Rsh(y, uint(sh))
                y.And(y, opByteMask)
    }
}

func opNot(c *state) {
    a := c.top()

    a.Not(a)
    toU256(a)
}

...

Я выполнил следующую команду: golangci-lint run --out-format=github-actions --timeout 10m --verbose

Результаты следующие:

  • Оригинальный проект:
INFO golangci-lint has version v1.61.0 built with go1.23.2 from (unknown, modified: ?, mod sum: "h1:VvbOLaRVWmyxCnUIMTbf1kDsaJbTzH20FAMXTAlQGu8=") on (unknown) 
INFO [config_reader] Config search paths: [./ /Users/vitomirpavlov/work/forks/polygon-edge /Users/vitomirpavlov/work/forks
/Users/vitomirpavlov/work/projects/project-node
/Users/vitomirpavlov/work/projects /Users/vitomirpavlov/work/projects /Users/vitomirpavlov /Users /] 
INFO [config_reader] Used config file .golangci.yml 
WARN [config_reader] The configuration option `run.skip-dirs` is deprecated, please use `issues.exclude-dirs`. 
WARN [config_reader] The output format `github-actions` is deprecated, please use `colored-line-number` 
INFO [lintersdb] Active 27 linters: [dogsled dupl errcheck errname errorlint forcetypeassert goconst gocritic godox gofmt goimports gosec importas lll makezero misspell nlreturn nolintlint prealloc predeclared stylecheck thelper tparallel unconvert wastedassign whitespace wsl] 
INFO [loader] Go packages loading at mode 575 (compiled_files|exports_file|files|imports|deps|name|types_sizes) took 7.44611625s 
INFO [runner/filename_unadjuster] Pre-built 0 adjustments in 44.592417ms 
INFO [linters_context] importas settings found, but no aliases listed. List aliases under alias: key. 
INFO [linters_context/goanalysis] analyzers took 0s with no stages 
INFO [runner/skip_dirs] Skipped 9 issues from dir tests by pattern tests 
INFO [runner/skip_dirs] Skipped 5 issues from dir helper/tests by pattern tests 
INFO [runner] Issues before processing: 2771, after processing: 0 
INFO [runner] Processors filtering stat (in/out): invalid_issue: 2771/2771, path_prettifier: 2771/2771, skip_dirs: 2771/2757, exclude-rules: 1756/845, uniq_by_line: 497/484, autogenerated_exclude: 2757/1756, identifier_marker: 1756/1756, exclude: 1756/1756, nolint: 845/497, diff: 484/0, cgo: 2771/2771, filename_unadjuster: 2771/2771 
INFO [runner] processing took 449.635086ms with stages: diff: 311.677791ms, nolint: 74.901458ms, identifier_marker: 21.505708ms, exclude-rules: 20.301417ms, path_prettifier: 9.993584ms, autogenerated_exclude: 9.421166ms, skip_dirs: 1.468625ms, cgo: 125.5µs, invalid_issue: 100.75µs, uniq_by_line: 87.291µs, filename_unadjuster: 48.876µs, max_same_issues: 1.168µs, fixer: 291ns, exclude: 250ns, source_code: 209ns, sort_results: 209ns, max_per_file_from_linter: 208ns, skip_files: 167ns, path_shortener: 167ns, max_from_linter: 126ns, path_prefixer: 84ns, severity-rules: 41ns 
INFO [runner] linters took 1.501898458s with stages: goanalysis_metalinter: 1.052092375s 
INFO File cache stats: 0 entries of total size 0B 
INFO Memory: 92 samples, avg is 37.5MB, max is 96.1MB 
INFO Execution took 9.001672292s
  • Форкнутый проект:
INFO golangci-lint has version v1.61.0 built with go1.23.2 from (unknown, modified: ?, mod sum: "h1:VvbOLaRVWmyxCnUIMTbf1kDsaJbTzH20FAMXTAlQGu8=") on (unknown) 
INFO [config_reader] Config search paths: [./ /Users/vitomirpavlov/work/projects/project-node /Users/vitomirpavlov/work/projects /Users/vitomirpavlov/work/ /Users/vitomirpavlov/work /Users/vitomirpavlov /Users /] 
INFO [config_reader] Used config file .golangci.yml 
WARN [config_reader] The output format `github-actions` is deprecated, please use `colored-line-number` 
INFO [lintersdb] Active 27 linters: [dogsled dupl errcheck errname errorlint forcetypeassert goconst gocritic godox gofmt goimports gosec importas lll makezero misspell nlreturn nolintlint prealloc predeclared stylecheck thelper tparallel unconvert wastedassign whitespace wsl] 
INFO [loader] Go packages loading at mode 575 (deps|files|types_sizes|compiled_files|imports|name|exports_file) took 3.602814584s 
INFO [runner/filename_unadjuster] Pre-built 0 adjustments in 41.664167ms 
INFO [linters_context] importas settings found, but no aliases listed. List aliases under alias: key. 
INFO [linters_context/goanalysis] analyzers took 0s with no stages 
WARN [runner] Can't process result by diff processor: can't prepare diff by revgrep: could not read git repo: error executing "git diff --color=never --no-ext-diff --relative origin/develop --": exit status 128: fatal: bad revision 'origin/develop' 
INFO [runner/skip_dirs] Skipped 5 issues from dir helper/tests by pattern tests 
INFO [runner/skip_dirs] Skipped 10 issues from dir tests by pattern tests 
INFO [runner/max_same_issues] 43/46 issues with text "G115: integer overflow conversion int -> uint64" were hidden, use --max-same-issues 
INFO [runner/max_same_issues] 23/26 issues with text "G115: integer overflow conversion int64 -> uint64" were hidden, use --max-same-issues 
INFO [runner/max_same_issues] 20/23 issues with text "G115: integer overflow conversion uint64 -> int64" were hidden, use --max-same-issues 
INFO [runner/max_same_issues] 14/17 issues with text "assignments should only be cuddled with other assignments" were hidden, use --max-same-issues 
INFO [runner/max_same_issues] 12/15 issues with text "only one cuddle assignment allowed before if statement" were hidden, use --max-same-issues 
INFO [runner/max_same_issues] 12/15 issues with text "G115: integer overflow conversion uint64 -> int" were hidden, use --max-same-issues 
INFO [runner/max_same_issues] 8/11 issues with text "expressions should not be cuddled with blocks" were hidden, use --max-same-issues 
INFO [runner/max_same_issues] 7/10 issues with text "ifElseChain: rewrite if-else to switch statement" were hidden, use --max-same-issues 
INFO [runner/max_same_issues] 6/9 issues with text "commentFormatting: put a space between `//` and comment text" were hidden, use --max-same-issues 
INFO [runner/max_same_issues] 6/9 issues with text "type assertion must be checked" were hidden, use --max-same-issues 
INFO [runner/max_same_issues] 2/5 issues with text "if statements should only be cuddled with assignments" were hidden, use --max-same-issues 
INFO [runner/max_same_issues] 1/4 issues with text "unslice: could simplify buf[:] to buf" were hidden, use --max-same-issues 
INFO [runner/max_same_issues] 1/4 issues with text "G115: integer overflow conversion int -> uint8" were hidden, use --max-same-issues 
INFO [runner] Issues before processing: 2613, after processing: 103 
INFO [runner] Processors filtering stat (in/out): max_same_issues: 258/103, max_from_linter: 103/103, source_code: 103/103, path_shortener: 103/103, path_prefixer: 103/103, invalid_issue: 2613/2613, identifier_marker: 1634/1634, max_per_file_from_linter: 258/258, uniq_by_line: 271/258, cgo: 2613/2613, filename_unadjuster: 2613/2613, exclude-rules: 1634/531, severity-rules: 103/103, fixer: 103/103, sort_results: 103/103, path_prettifier: 2613/2613, autogenerated_exclude: 2598/1634, nolint: 531/271, skip_files: 2613/2613, skip_dirs: 2613/2598, exclude: 1634/1634 
INFO [runner] processing took 497.365834ms with stages: diff: 379.893458ms, nolint: 46.737834ms, path_prettifier: 22.076375ms, identifier_marker: 20.3875ms, exclude-rules: 15.325542ms, autogenerated_exclude: 9.250959ms, source_code: 1.650209ms, skip_dirs: 1.501666ms, max_same_issues: 184.542µs, invalid_issue: 97.792µs, cgo: 97.751µs, uniq_by_line: 47.666µs, filename_unadjuster: 47.542µs, max_from_linter: 29.083µs, max_per_file_from_linter: 22.167µs, path_shortener: 12.667µs, skip_files: 2.125µs, fixer: 333ns, exclude: 291ns, sort_results: 167ns, severity-rules: 83ns, path_prefixer: 82ns 
INFO [runner] linters took 1.363894625s with stages: goanalysis_metalinter: 866.168459ms 
...
::high file=helper/staking/staking.go,line=198,col=31::G115: integer overflow conversion int -> uint64 (gosec)
::error file=state/runtime/evm/instructions.go,line=1257,col=3::assignOp: replace `availableGas = availableGas - availableGas/64` with `availableGas -= availableGas/64` (gocritic)
::error file=state/runtime/evm/instructions.go,line=1016,col=2::assignOp: replace `size = size - 1` with `size--` (gocritic)
::error file=state/runtime/evm/instructions.go,line=468,col=2::ifElseChain: rewrite if-else to switch statement (gocritic)
::error file=state/runtime/evm/instructions.go,line=508,col=3::ifElseChain: rewrite if-else to switch statement (gocritic)
::error file=state/runtime/evm/instructions.go,line=521,col=3::ifElseChain: rewrite if-else to switch statement (gocritic)
::high file=state/runtime/evm/instructions.go,line=220,col=16::G115: integer overflow conversion int64 -> uint (gosec)
::high file=state/runtime/evm/instructions.go,line=315,col=14::G115: integer overflow conversion uint -> int (gosec)
::high file=state/runtime/evm/instructions.go,line=611,col=28::G115: integer overflow conversion int64 -> uint64 (gosec)
::high file=state/runtime/evm/instructions.go,line=956,col=13::G115: integer overflow conversion uint64 -> int (gosec)
::high file=state/runtime/evm/instructions.go,line=968,col=14::G115: integer overflow conversion uint64 -> int (gosec)
::high file=state/runtime/evm/state.go,line=330,col=50::G115: integer overflow conversion uint64 -> int (gosec)
::error file=state/runtime/evm/instructions.go,line=631,col=6::function min has same name as predeclared identifier (predeclared)
...
INFO File cache stats: 45 entries of total size 343.1KiB 
INFO Memory: 52 samples, avg is 42.3MB, max is 100.6MB 
INFO Execution took 5.018112166s   

Версия линтера: golangci-lint has version v1.61.0 built with go1.23.2 from (unknown, modified: ?, mod sum: "h1:VvbOLaRVWmyxCnUIMTbf1kDsaJbTzH20FAMXTAlQGu8=") on (unknown)

Я пытался очистить кэш, проверял версии и всё, что приходит в голову, но ничего не сработало.

Ответ или решение

Вопрос различия результатов golangci-lint для одного и того же файла в различных проектах, даже при том, что они используют одну и ту же версию Go и golangci-lint, может вызывать недоумение. Давайте проанализируем возможные причины, основываясь на предоставленной информации.

Факторы, влияющие на различия в результатах

  1. Конфигурационные файлы:

    • Важно убедиться, что оба проекта используют идентичные файлы конфигурации .golangci.yml. Различия в этих файлах могут привести к отключению определенных линтеров или изменению их поведения.
    • Проверьте, нет ли дополнительных настроек в forked проекте, которые могут изменять работу golangci-lint.
  2. Изменения в коде:

    • Убедитесь, что нет никакой разницы в файлах кода в обоих репозиториях. Даже мелкие отличия могут привести к различным результатам линтинга. Проведите сверку всех файлов, используя инструменты сравнения, такие как diff.
  3. Зависимости и модули:

    • Проверьте, что зависимости (включая версии) и модули, используемые в обоих проектах, совпадают. Различные версии библиотек могут влиять на результаты линтинга.
    • Используйте команду go mod tidy для синхронизации зависимостей.
  4. Флаги и параметры запуска:

    • Возможно, в одном из проектов добавлены дополнительные флаги или параметры запуска для golangci-lint. Убедитесь, что команды, которые вы вводите, идентичны в обоих проектах.
  5. Кэш golangci-lint:

    • Иногда результаты могут кэшироваться, и это может привести к несоответствиям. Попробуйте очистить кэш с помощью команды golangci-lint cache clear.
  6. Проблемы с репозиторием Git:

    • В сообщении о результатах линтинга для forked проекта присутствует ошибка, связанная с Git: fatal: bad revision 'origin/develop'. Это может обозначать проблемы с ветвлением или доступностью определённых изменений в вашем локальном репозитории. Убедитесь, что все изменения загружены и репозиторий находится в согласованном состоянии.
  7. Разница в окружении:

    • Убедитесь, что окружения, в которых запускаются два проекта, идентичны. Различия в системах или установленных инструментах также могут привести к расхождениям в результатах.

Рекомендации по устранению проблемы

  1. Сравнение конфигураций:

    • Проверьте и сравните файлы конфигурации обоих проектов на наличие различий.
  2. Обновление модулей:

    • Убедитесь, что все модули актуальны. Используйте go get -u для обновления до последних стабильных версий.
  3. Запуск линтинга на чистом проекте:

    • Создайте новый проект и поэтапно добавляйте в него компоненты forked проекта, запуская golangci-lint после каждого добавления. Это поможет локализовать проблему.
  4. Логи и отладка:

    • Если разница в результатах не устраняется, создайте детальные логи выполнения и проанализируйте их на наличие отклонений.

Следуя этим рекомендациям, вы сможете выявить причины различий в результатах golangci-lint и принять необходимые меры для их устранения.

Оцените материал
Добавить комментарий

Капча загружается...