megalinter
megalinter copied to clipboard
Update golangci-lint to support go v1.24.x
Is your feature request related to a problem? Please describe.
The current version uses golangci-lint v1.64.8
Describe the solution you'd like Support the Latest 1.x version with support for 1.24 but also support the new major version for v2 as an option.
Describe alternatives you've considered I am not sure; I am using Github Actions and am not able to install packages (Afaik)
Theres some updates to that, but also https://github.com/oxsecurity/megalinter/pull/5059.
We might need some help with https://github.com/oxsecurity/megalinter/pull/5033 though, it seems it didn't work as is.
Do you know what we need to adapt to use v2 too?
@echoix Something tells me you will need to support both binaries for a while.
golangci lint have a CLI for you to convert your v1 yaml file to v2, but it will take a really long time for people to move to v2, so maybe an Env var is a fit here
Do you know if they have incompatible requirements? For example we would need to install two different go toolchains or libraries that might not work together?
Hope it's OK if I jump in since I'd love to see this as well. Go is backwards compatible so the go toolchain shouldn't be an issue and since it's compiled it doesn't use libraries at run time, the binaries are usually statically linked and stand alone.
From a quick look it's installed by calling the install.sh script from golangci-lint's repo: https://github.com/oxsecurity/megalinter/blob/main/linters/go_golangci_lint/Dockerfile#L152 and passes the version tag to target.
The install script uses binaries published on their github releases: https://github.com/golangci/golangci-lint/blob/main/install.sh#L59, since it's not built there even less chance of one using some libraries and the other one using others.
On the config side both version use the same file as "default" config but different content 😬 so that might be the tricky part, I guess that's what #5033 is partially about?
I've tested the following approach, set GO_GOLANGCI_LINT_CONFIG_FILE to .golangci.v1.yaml and create a migrated V2 config at .golangci.yaml. It seems to let me lint locally with V2 yet allows megalinter to happily work with a valid V1 config.
So technically you could even have 1 and 2 in the same repository at the same time, as long as it's configured correctly.
@echoix how do you imagine deploying both in parallel? Do you have examples of other linters where this happened?
- One option would be to keep 1 plugin but use an extra config flag to specify V1 or V2
- Another option could be to setup separate linter plugin entirely for V2
For option 1 something like in the Dockerfile might work:
RUN wget -O- -nv https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s "v${GO_GOLANGCI_LINT_V1_VERSION}" \
&& mv $(which golangci-lint) $(basename $(which golangci-lint))/golangci-lint-v1
&& golangci-lint-v1 --version
&& wget -O- -nv https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s "v${GO_GOLANGCI_LINT_V2_VERSION}" \
&& golangci-lint --version
Then based on which version is requested the handler script can call one or the other.
Actually GO_GOLANGCI_LINT_CLI_EXECUTABLE is available so doing the opposite and installing V2 as golangci-lint-v2 would allow using it by simply setting that config flag, without other changes, it feels more like a work around tho.
Thanks for the great news @pfiaux. I can't remember another weird migration like that. The one I can think of is ESLint v9, that is really hard for projects and is not done yet.
How hard is migrating to use golangcilint v2 for a project? Usually we are always looking forward, and it is projects that use Megalinter that needs to keep up with what the linters they use change (otherwise it's impossible to progress anything, we are not the ones breaking things). They can keep using older Megalinter versions if they can't get it working.
If golangci-lint can use the same go toolchain installed for both v1 and v2, we could place both. But on second thought, we always have the workaround where a user can run commands to install different software, they could use that to install an older golang ci lint version if they really need a new Megalinter version.
So, I think we could go and upgrade to v2 right away. The latest release was done this weekend, so the next release will be in about a month. So it'll give another month for projects to consider making it work. It would already be 2 months (or 3) after that major release, so we wouldn't be early either.
Golang 1.24 is still unsupported since the Golang version included in the latest MegaLinter Go flavor image (python:3.12.10-alpine3.21) is still 1.23.8.
I obtain the following output on running MegaLinter on a project where I have Go 1.24 specified in go.mod:
- Using [golangci-lint v2.1.5] https://megalinter.io/8.7.0/descriptors/go_golangci_lint
- MegaLinter key: [GO_GOLANGCI_LINT]
- Rules config: [.golangci.yml]
- Command: [golangci-lint run --fix --timeout 3m -c /action/lib/.automation/.golangci.yml]
--Error detail:
level=error msg="Running error: context loading failed: failed to load packages: failed to load packages: failed to load with go/packages: err: exit status 1: stderr: go: go.mod requires go >= 1.24.0 (running go 1.23.8; GOTOOLCHAIN=local)\n"
Is the :beta image instead of :latest different? Otherwise, we don't have a large range of choices for the golang toolchain. Alpine 3.22 is due anytime soon now, so the switch should be done when the base alpine+python images are released
Is the :beta image instead of :latest different? Otherwise, we don't have a large range of choices for the golang toolchain. Alpine 3.22 is due anytime soon now, so the switch should be done when the base alpine+python images are released
@echoix Do you mean the :beta of MegaLinter or python:3.12.10-alpine3.21 ?
Anyway, I agree with you: I think the easiest way, if we stick to the Python base image, is to wait for Alpine 3.22. Depending on the urgency, another option we have is to install go from sources rather than from the APK repository. One good opportunity provided by such choice is to finally remove this coupling of the Go version with the base image.
I'd prefer for the Megalinter repo to not compile a complete toolchain from sources, building the images is already quite long for everything. These new versions don't happen that often. But if you were talking about something that is doable on your side, sure, it's something possible.
Compiling go binaries from sources matters me less, as we can easily build them from a separate stage and copy the static binaries back, and compiling (pure) go projects is impressively fast and easy. (Probably the easiest that I know of for now!).
I'd prefer for the Megalinter repo to not compile a complete toolchain from sources, building the images is already quite long for everything. These new versions don't happen that often. But if you were talking about something that is doable on your side, sure, it's something possible.
Compiling go binaries from sources matters me less, as we can easily build them from a separate stage and copy the static binaries back, and compiling (pure) go projects is impressively fast and easy. (Probably the easiest that I know of for now!).
@echoix I think there has been a misunderstanding, my fault 🙂 .
My proposal was to simply to download an already pre-packaged Go distribution from a tarball and extract it in /usr/local/go: as simple as that, and nothing to compile.
In that case, maybe only compare the disk size requirements), as I think apk is able to make use of dynamic libraries even when using musl. And that the go compiler allows to use musl.
Then if you still feel like it, you can look at the descriptor files like https://github.com/oxsecurity/megalinter/blob/main/megalinter/descriptors/go.megalinter-descriptor.yml#L9-L10 and replace it with Dockerfile based instructions
the root cause is the GOTOOLCHAIN=local env var set by alpine. See here. I wonder why they are even doing this.
$ docker run --rm -ti --entrypoint go oxsecurity/megalinter-go:v8 env GOTOOLCHAIN
local
fixed by passing GOTOOLCHAIN=auto env var.
From https://go.dev/doc/toolchain:
The default GOTOOLCHAIN setting is auto, which enables the toolchain switching described earlier.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.
If you think this issue should stay open, please remove the O: stale 🤖 label or comment on the issue.