Skip to content

Fix golangci-lint installation path in dev container #4729

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

kyu08
Copy link
Contributor

@kyu08 kyu08 commented Jul 12, 2025

Problem I encountered

Currently, make lint is not executable in Dev Containers or Codespaces because installation path of golangci-lint is not a expected location of scripts/lint.sh like below.

Path
Current installation path for Codespaces $(go env GOPATH)/bin
The location scripts/lint.sh expects ./.bin
@kyu08 ➜ /workspaces/lazygit (update-dev-container) $ make lint
./scripts/lint.sh
You need to install golangci-lint into .bin
One way to do this is to run
  GOBIN=$(pwd)/.bin go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.2.1
make: *** [Makefile:43: lint] Error 1

How I solved and tested

So I've fixed installation path of golangci-lint to under ./.bin.

I have tested that I can run make lint after launching dev container like below.

@kyu08 ➜ /workspaces/lazygit (update-dev-container-settings) $ make lint
./scripts/lint.sh
0 issues.

Please check if the PR fulfills these requirements

  • Cheatsheets are up-to-date (run go generate ./...)
  • Code has been formatted (see here)
  • Tests have been added/updated (see here for the integration test guide)
  • Text is internationalised (see here)
  • If a new UserConfig entry was added, make sure it can be hot-reloaded (see here)
  • Docs have been updated if necessary
  • You've read through your own file changes for silly mistakes etc

Comment on lines -8 to -9
RUN curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.50.0
RUN golangci-lint --version
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At first, I fixed this line like below:

RUN curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b ./.bin

But golangci-lint binary is not installed to ./.bin for some reason.

So I use postStartCommand in devcontainer.json and it worked.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After some testing, I deleted golangci-lint installation from Dockerfile in 32e7b92.

I found that major golang dev tool is installed with this specify. (dlv golangci-lint golint gomodifytags goplay gopls gotests impl revive staticcheck)
https://github.com/kyu08/lazygit/blob/32e7b92311b933ab76e160d11b622ee190d64023/.devcontainer/devcontainer.json#L15-L17

So we don't need install golangci-lint in Dockerfile.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would still be good to install the specific version that we are using on CI (2.2.1 at this time), to avoid false positives when golanci-lint gets updated and adds new checks that are enabled by default. This was the very point of introducing the .bin folder.

Of course, if we then later bump the golangci-lint version that we are using, people will still have to fix their installed version manually, but you also have to do that when working locally, and I don't see a good way around that. (We could add a version check to scripts/lint.sh and warn about this, but this wouldn't help with the lint-on-save function in vscode, which is the main use of linting for me.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see.
Then go tool may be suitable solution.

It allows us to manage versions of tools which are written in Go using go.mod.
So we can unify versions of dev tools such as golang-lint or gofumpt easily.

I'll take some time to try it out next week.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No experience with that, but on https://golangci-lint.run/welcome/install/ it says We don't recommend using go tool. They don't really say why, though.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great idea. I made a separate PR (#4733) to take this a bit further and also make it work for lint-on-save in vscode. I didn't test if this works in a dev container, but it should; if you have time to test this, that would be great.

Copy link
Contributor Author

@kyu08 kyu08 Jul 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks.

if you have time to test this, that would be great.

Just to clarify, are you asking me to test #4733 specifically, or to test changing the make lint target to go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.2.1 run?

If it's second option, I confirmed it worked.

This is a head of the command.
 2025-07-13 at 22 53 52

And this is the tail of it.

 2025-07-13 at 22 54 02

About your PR, it'll take a while because I'm not familiar with VSCode. Maybe sometime in next week.

And how should we divide the roles between this PR and your
PR(#4733 )?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I meant to test #4733. If I'm not missing anything, that PR can completely replace this one.

Copy link
Contributor Author

@kyu08 kyu08 Jul 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK.
If you don't mind, could you add me as co-author of your first commit of #4733?
I'd be happy if my contribution remained in a clear and visible form.

Anyway, I'll take time for it next week.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you don't mind, could you add me as co-author of your first commit of #4733?

Sure. Let me know if you'd like to appear with a different name or email address than what I added. Also mentioning you in the PR description now.

.gitignore Outdated
@@ -14,7 +14,8 @@ coverage.txt
.idea/

# Binaries
.bin/
.bin/*
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is necessary to ignoring binaries.

.gitignore Outdated
@@ -14,7 +14,8 @@ coverage.txt
.idea/

# Binaries
.bin/
.bin/*
!.bin/.gitkeep
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is necessary to manage .bin directory under Git.

@kyu08 kyu08 changed the title Fix installation path of golangci-lint in dev container Fix golangci-lint installation path in dev container Jul 12, 2025
@kyu08 kyu08 force-pushed the update-dev-container-settings branch from a5c3f63 to e3f422f Compare July 12, 2025 11:03
@stefanhaller
Copy link
Collaborator

Thanks. I'm very unfamiliar with containers in general, and with dev containers in VS Code in particular, but I played with it a little bit just now to get a feeling for how all this works.

But I don't think this solution works well enough. When I spin up my existing working copy in a container, it will overwrite my Mac binary with a linux binary. If I then switch back to local development, linting now longer works on the Mac.

For the lint.sh script I suppose we could solve this by having subfolders in .bin (e.g. .bin/Darwin/golanci-lint), and then use something like ./.bin/$(uname)/golangci-lint to call it. However, the path is also referenced from .vscode/settings.json (in the go.alternateTools section), to make linting on save work, and I don't know how to make this conditional based on the platform we're running on. (See microsoft/vscode#2809)

If anybody has ideas how to improve all this, I'm all ears.

@kyu08
Copy link
Contributor Author

kyu08 commented Jul 12, 2025

Thanks for the input. I understand your concern.

As far as I know, many of dev containers users don't switch frequently between dev containers and local develop environment. I think one of the purposes of using dev containers is for avoiding construct develop environment locally.

So this might not be a problem in practice.
What do you think?

@stefanhaller
Copy link
Collaborator

Sounds reasonable, but when I played with this, I thought this might be useful for cases where I need to debug a linux-specific problem. Instead of spinning up my linux VM I could simply switch to a dev container with the existing working copy, might be easier. So then I would run into this problem.

But what if we change it to keep the installation of golangci-lint in Dockerfile (just change it to install 2.2.1 so that it matches what we use on CI), and then in the postStartCommand add something like test -e .bin/golangci-lint || { mkdir -p .bin && ln -s $(go env GOPATH)/bin/golangci-lint .bin/golangci-lint }? This will create a symlink if it doesn't exist already.

With the mkdir we can also drop the .gitkeep change, which I find a bit ugly.

@kyu08
Copy link
Contributor Author

kyu08 commented Jul 12, 2025

Sounds reasonable, but when I played with this, I thought this might be useful for cases where I need to debug a linux-specific problem. Instead of spinning up my linux VM I could simply switch to a dev container with the existing working copy, might be easier. So then I would run into this problem.

That makes sense. As you said, dev containers is useful for debugging on Linux.

But what if we change it to keep the installation of golangci-lint in Dockerfile (just change it to install 2.2.1 so that it matches what we use on CI), and then in the postStartCommand add something like test -e .bin/golangci-lint || { mkdir -p .bin && ln -s $(go env GOPATH)/bin/golangci-lint .bin/golangci-lint }? This will create a symlink if it doesn't exist already.

I'm not sure if your approach resolves the issue.
If my understanding is correct, in the below scenario, the problem still exist.

  1. The binary for darwin exists in .bin/.
  2. Enter into dev containers. There is the binary for darwin in .bin/ because it already exists.
  3. You can't run make lint because there is the binary for darwin but running OS is linux.

I think the same issue could occur in reverse scenerio(linux -> macOS) as well.

If I miss or misunderstand something, please let me know.

With the mkdir we can also drop the .gitkeep change, which I find a bit ugly.

I have no objections about this.

@stefanhaller
Copy link
Collaborator

Of course, it doesn't solve it perfectly, but I think it's a reasonable compromise that works well enough in the important cases:

  1. You use a working copy exclusively with a dev container: just works
  2. You use your existing Mac working copy with a dev container occasionally: you won't be able to lint while in the dev container, but at least it doesn't "corrupt" your working copy, and when you go back to local development, you can lint again on Mac.

This would be perfectly acceptable for me.

@kyu08
Copy link
Contributor Author

kyu08 commented Jul 12, 2025

Ah I understand. Thanks for the information.

I'll fix it tomorrow as your suggestion.

@kyu08 kyu08 force-pushed the update-dev-container-settings branch from ccb97e6 to 32e7b92 Compare July 13, 2025 04:54
@@ -62,7 +62,7 @@

// See https://www.kenmuse.com/blog/avoiding-dubious-ownership-in-dev-containers/ for the safe.directory part
// The defaultBranch part is required for our deprecated integration tests.
"postStartCommand": "git config --global --add safe.directory ${containerWorkspaceFolder} && git config --global init.defaultBranch master",
"postStartCommand": "git config --global --add safe.directory ${containerWorkspaceFolder} && git config --global init.defaultBranch master && test -e .bin/golangci-lint || { mkdir -p .bin && ln -s $(go env GOPATH)/bin/golangci-lint .bin/golangci-lint; }",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added just ;. And it works.

@kyu08
Copy link
Contributor Author

kyu08 commented Jul 13, 2025

@stefanhaller
I added fixup commit 32e7b92 and some comments for explanation.

Please check the comments and diff.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants