golangci / golangci-lint

Fast linters runner for Go
https://golangci-lint.run
GNU General Public License v3.0
15.63k stars 1.39k forks source link

Error with go1.18 workspace #2654

Closed lx-world closed 1 year ago

lx-world commented 2 years ago

Welcome

Description of the problem

Error about go1.18 go.work(workspace):

ERRO [linters context] typechecking error: pattern ./...: directory prefix . does not contain modules listed in go.work or their selected dependencies

Version of golangci-lint

```console $ golangci-lint --version golangci-lint has version v1.44.2 built from (unknown, mod sum: "h1:MzvkDt1j1OHkv42/feNJVNNXRFACPp7aAWBWDo5aYQw=") on (unknown) ```

Configuration file

```console $ cat .golangci.yml linters: enable: - nilerr - goconst - goprintffuncname - importas - predeclared - revive - rowserrcheck - tenv - testpackage - tparallel - unconvert - unparam - wastedassign - bodyclose # from krts - deadcode - dogsled - durationcheck - exportloopref - govet - gosimple - gofmt - gofumpt - errcheck - goimports - gomnd - gocyclo - ineffassign - lll - prealloc - staticcheck - structcheck - typecheck - unused - varcheck - whitespace - exhaustive ```

Go environment

```console $ go version && go env go version go1.18 linux/amd64 GO111MODULE="" GOARCH="amd64" GOBIN="" GOCACHE=".cache/go-build" GOENV=".config/go/env" GOEXE="" GOEXPERIMENT="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="linux" GOINSECURE="" GOMODCACHE="/go/pkg/mod" GONOPROXY="" GONOSUMDB="" GOOS="linux" GOPATH="/go" GOPRIVATE="" GOPROXY="https://proxy.golang.org,direct" GOROOT="/usr/local/go" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64" GOVCS="" GOVERSION="go1.18" GCCGO="gccgo" GOAMD64="v1" AR="ar" CC="gcc" CXX="g++" CGO_ENABLED="1" GOMOD="/dev/null" GOWORK="go.work" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build1941441636=/tmp/go-build -gno-record-gcc-switches" ```

Verbose output of running

```console $ golangci-lint cache clean $ golangci-lint run -v ERRO [linters context] typechecking error: pattern ./...: directory prefix . does not contain modules listed in go.work or their selected dependencies ```

Code example or link to a public repository

```go // add your code here ```
boring-cyborg[bot] commented 2 years ago

Hey, thank you for opening your first Issue ! πŸ™‚ If you would like to contribute we have a guide for contributors.

ldez commented 2 years ago

Hello,

can you provide a reproducible context (full example or public repo)?

lx-world commented 2 years ago

Project  A   -go.mod   -go.sum  B   -go.mod   -go.sum

go.work

now , golangcli-lint run

bombsimon commented 2 years ago

Not reproducible, please provide your real code.

$ tree
.
β”œβ”€β”€ A
β”‚Β Β  β”œβ”€β”€ go.mod
β”‚Β Β  └── main.go
└── B
    β”œβ”€β”€ go.mod
    └── main.go

2 directories, 4 files
$ tail A/main.go B/main.go
==> A/main.go <==
package main

import "fmt"

func main() {

        fmt.Println("vim-go")
}

==> B/main.go <==
package main

import "fmt"

func main() {
        fmt.Println("vim-go")

}
$ golangci-lint run --print-issued-lines=false
B/main.go:7: File is not `gofumpt`-ed (gofumpt)
A/main.go:6: File is not `gofumpt`-ed (gofumpt)
A/main.go:5: unnecessary leading newline (whitespace)
steakyan commented 2 years ago

I think this may be the problem of go.work, I could reproduce the problem as follow:

~/go/src/github.com/user/hello$` tree

β”œβ”€β”€ A
β”‚Β Β  β”œβ”€β”€ go.mod
β”‚Β Β  └── main.go
β”œβ”€β”€ B
β”‚Β Β  β”œβ”€β”€ go.mod
β”‚Β Β  └── main.go
└── go.work
~/go/src/github.com/user/hello$ cat A/go.mod A/main.go
module github.com/user/hello/A

go 1.18
package A

import "fmt"

func main() {

        fmt.Println("vim-go")
}

func A() {
        fmt.Println("A")
}
~/go/src/github.com/user/hello$ cat B/go.mod  B/main.go
module github.com/user/hello/B

go 1.18
package main

import (
        "fmt"
        "github.com/user/hello/A"
)

func main() {

        fmt.Println("vim-go")
        A.A()
}
~/go/src/github.com/user/hello$ cat go.work
go 1.18

use (
    ./A
    ./B
)

I could run this code by

~/go/src/github.com/user/hello$ go run B/main.go
vim-go
A

but when I try to run golangci-lint, I get the results as below

~/go/src/github.com/user/hello$ golangci-lint run
ERRO [linters context] typechecking error: pattern ./...: directory prefix . does not contain modules listed in go.work or their selected dependencies

My go version is go version go1.18 linux/amd64 and golangci-lint version is golangci-lint has version v1.45.0 built from (unknown, mod sum: "h1:T2oCVkYoeckBxcNS6DTYiSXN2QcTNuAWaHyLGfqzMlU=") on (unknown)

glebsts commented 2 years ago

I get same error when run go test -v ./... after converting to multi-module workspace with same structure. This test run command I used to run before conversion, so it was quite natural.. but it doesn't work anymore. Had to run this command in every module subdirectory instead. Seems like same case.

schellj commented 2 years ago

I get same error when run go test -v ./... after converting to multi-module workspace with same structure. This test run command I used to run before conversion, so it was quite natural.. but it doesn't work anymore. Had to run this command in every module subdirectory instead. Seems like same case.

I have this issue as well. Is there a new canonical way to run all tests in a module?

schellj commented 2 years ago

Nevermind. go test ./... works after doing go work use . - cc @glebsts

Edit: except gopls now complains no go.mod file found in <MODULE_DIRECTORY>, even though that file exists and go test ./... runs fine.

leighmcculloch commented 2 years ago

I'm seeing this also. Reproducible with the below and golangci-lint v1.45.2.

https://github.com/stellar/starlight/pull/446

❯ git clone https://github.com/stellar/starlight
❯ cd starlight
❯ git checkout go118
❯ golangci-lint run
ERRO [linters context] typechecking error: pattern ./...: directory prefix . does not contain modules listed in go.work or their selected dependencies
✘ exit status 7
❯ golangci-lint run sdk
ERRO Running error: context loading failed: failed to load packages: package ./sdk: no go files to analyze
✘ exit status 5
BarbieroDB1 commented 2 years ago

This problem still happens on v1.46.2

Just want to add for folks reading this that you can "hack" multiple golangci-lint runs by using go word edit -json, jq and xargs:

go work edit -json | jq -r '.Use[].DiskPath'  | xargs -I{} golangci-lint run {}/...

This is still not ideal(it's the equivalent of running it once per module rather than running it once for the entire workspace, it's also a pain to get error codes), but it's a good way to at least get some information about the project manually

tie commented 2 years ago

it's the equivalent of running it once per module rather than running it once for the entire workspace

You can pass multiple paths to run subcommand.

golangci-lint run --out-format=github-actions -- $(go work edit -json | jq -c -r '[.Use[].DiskPath] | map_values(. + "/...")[]')

https://github.com/pact-im/go-pkg/blob/545991847d753f47c8b715f230657e7f4a692e44/.github/workflows/lint.yml#L43-L48

maufranchini commented 2 years ago

This problem still happens on v1.46.2

Just want to add for folks reading this that you can "hack" multiple golangci-lint runs by using go word edit -json, jq and xargs:

go work edit -json | jq -r '.Use[].DiskPath'  | xargs -I{} golangci-lint run {}/...

This is still not ideal(it's the equivalent of running it once per module rather than running it once for the entire workspace, it's also a pain to get error codes), but it's a good way to at least get some information about the project manually

Indeed a good hack, not the best approach but better than nothing. The same happens with go test -v ./... ofc

go work edit -json | jq -r '.Use[].DiskPath' | xargs -I{} go test -v {}/...

tie commented 2 years ago

You can pass multiple packages to go test too.

go test $(go work edit -json | jq -c -r '[.Use[].DiskPath] | map_values("./" + . + "/...")[]')

If you are working in a workspace where modules have a common prefix (e.g. go.pact.im, source) that is not shared with dependencies you do not want to test, you can run

go test go.pact.im/x/...

Or even better, if you know that all your packages in the workspace build graph are well-behaved and do not attempt to run integration tests as part of the normal test suite,

go test all
fritzkeyzer commented 2 years ago

After publishing some projects i had the same issues. I had to update my test command.

From this: go test ./...

To this: go test github.com/fritzkeyzer/go-utils/...

wangmir commented 1 year ago

What is current status about this..? I'm having this issue too.

wangmir commented 1 year ago

What is current status about this..? I'm having this issue too.

No never mind, I forgot to add nested module project somewhere.

ehiggs-deliverect commented 1 year ago

Some very complex commands here. You can simplify it with the following:

$ go list -f '{{.Dir}}' -m | xargs golangci-lint run --verbose
nodeselector commented 1 year ago

I would call the ability to invoke golangci-lint multiple times a suitable workaround for some use cases, but it does create a big problem when trying to integrate into common editors like vscode, for example. Can we expect a fix at some point for this at some point or is this considered working from a golangci-lint perspective?

alexandervantrijffel commented 1 year ago

I was able to get rid of this error with this config for NeoVim and nvim-lspconfig

local configs = require 'lspconfig/configs'
if not configs.golangcilsp then
  configs.golangcilsp = {
    default_config = {
      cmd = { 'golangci-lint-langserver' },
      root_dir = lspconfig.util.root_pattern('.git', 'go.mod', 'go.work'),
      init_options = {
        command = { "go", "list -f '{{.Dir}}' -m | xargs golangci-lint run --issues-exit-code=1" },
      }
    },
  }
end

lspconfig.golangci_lint_ls.setup {
  on_attach = on_attach,
  capabilities = capabilities,
  filetypes = { 'go', 'gomod' }
}
csm10495 commented 1 year ago

The current behavior breaks usage of pre-commit. For instance i have a repo with a go.work in the root and a few subprojects. How can i use this with pre-commit without this being fixed here?

mrsimonemms commented 1 year ago

@csm10495 I've found that creating a blank root go module and running go work add . solves the problem with pre-commit. I've also had to create a blank main.go file as well. I don't like it, but it works.

// This file exists to avoid the golanglint-ci erroring
// in a multi-module Go workspace
// @link https://github.com/golangci/golangci-lint/issues/2654
package main
rajkumarGosavi commented 1 year ago

Hi,

Did we resolve this yet?

I am still facing the issue in 1.52.x version of golangci-lint.

In my case it does not give any lint errors even though there are many.

How my project is structured

A
|-- go.mod
|-- go.sum
|-- .golangci.yml

B
|-- go.mod
|--go.sum
go.work

And I run my golangci-lint as cd B && golangci-lint run -c ../A/.golangci.yml And I get 0 lint errors.

But if I structure it without workspace

A
|-- go.mod
|-- go.sum
|-- .golangci.yml
B
|-- go.mod
|-- go.sum

And when i call cd B && golangci-lint run -c ../A/.golangci.yml i can see the lint errors listed as per the config.

There is no change in config in both the cases.

Only change is that the 1st one is using go workspace go.work and the later one is not.

ldez commented 1 year ago

Hello,

golangci-lint works mainly like go run/go test.

If you have to following directory structure:

.
β”œβ”€β”€ go.work
β”œβ”€β”€ example
β”‚   β”œβ”€β”€ ...
β”‚   β”œβ”€β”€ go.mod
β”‚   β”œβ”€β”€ go.sum
β”‚   └── template
β”œβ”€β”€ hello
β”‚   β”œβ”€β”€ ...
β”‚   β”œβ”€β”€ go.mod
β”‚   β”œβ”€β”€ go.sum
β”‚   └── hello.go
└── world
    β”œβ”€β”€ ...
    β”œβ”€β”€ go.mod
    β”œβ”€β”€ go.sum
    └── hello.go

and if you are at the root of the workspace, you have to run:

golangci-lint ./hello/... ./world/... ./example/...

You can "automate" that by running one of the following commands:

go list -f '{{.Dir}}/...' -m | xargs golangci-lint run
golangci-lint run -- $(go work edit -json | jq -c -r '[.Use[].DiskPath] | map_values(. + "/...")[]')
go work edit -json | jq -r '.Use[].DiskPath'  | xargs -I{} golangci-lint run {}/...

Note: some linters that use internally go mod list -m can have an unexpected behavior. If you have a problem with one of these linters, please open a new issue.

rajkumarGosavi commented 1 year ago

Thanks @ldez , I would like to highlight one thing. When I installed golangci-lint with go install I was facing the above issue https://github.com/golangci/golangci-lint/issues/2654#issuecomment-1518092018. But when I installed a binary using brew it magically worked. This was very fascinating for me.

glebsts commented 1 year ago

@rajkumarGosavi you can check binary versions on both binaries.

rajkumarGosavi commented 1 year ago

@glebsts both were 1.50.x both from go install as well the one installed using brew

DreamwareDevelopment commented 1 year ago

This issue shouldn't have been closed. This linter is not following the module paths listed in go.work file.

With a structure like the following:

.
β”œβ”€β”€ go.work
β”œβ”€β”€ apps
β”‚   β”œβ”€β”€ A
β”‚   β”‚   β”œβ”€β”€ main.go
β”‚   β”‚   └── go.mod
└── libs
    β”œβ”€β”€ B
    β”‚   β”œβ”€β”€ lib.go
    β”‚   └── go.mod

golangci-lint run ./libs/B/... Works for linting B, but that's not acceptable for true workspaces support which this tool should support.

EDIT: I've been looking into the repo and it seems like this is a result of golang.org/x/tools/go/packages not handling the ./... operator correctly in a workspace. So hopefully overtime the toolchain will evolve to better handle workspaces. I'll have to give up on lint errors showing up in VSCode for now and rely on CI to catch them Β―\(ツ)/Β―

sdavids commented 7 months ago

Still a problem with:

golangci-lint has version 1.56.2 built with go1.22.0 from 58a724a0 on 2024-02-15T18:01:51Z

.
β”œβ”€β”€ example
β”‚Β Β  β”œβ”€β”€ go.mod
β”‚Β Β  └── main.go
└── go.work

go.work

go 1.22

toolchain go1.22.0

use (
  ./example
)

Please reopen this issue ...

kleo-53 commented 7 months ago

Hello, For anyone trying to configure the build, this command worked for me to simply build and test different projects in one repository (not the original, but a related topic!): go list -f '{{.Dir}}' -m | xargs -I {} go build -v {}

General structure:

β”œβ”€β”€ A
β”‚   β”œβ”€β”€ main.go
β”‚   └── go.mod
β”œβ”€β”€ B
β”‚   β”œβ”€β”€ main.go
β”‚   └── go.mod
└── C
    β”œβ”€β”€ main.go
    └── go.mod
sedyh commented 1 month ago

golangci-lint works mainly like go run / go test. and if you are at the root of the workspace, you have to run: golangci-lint ./hello/...

I think it doesn't since go run and go test will recognize module name from go.work.

When use ./hello is in go.work: