-
Notifications
You must be signed in to change notification settings - Fork 6.1k
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
Something about the go
and toolchain
directive in the go.mod
file
#9489
Comments
I think this topic is slowly killing me. 😅 Thank you for your comprehensive write up. I think what we need to definitely iron out here is what the valid versions are for the go directive. My position (loosely held because I find the Go docs for this hard to read) is that Let's start with this statement:
Jumping over to the go version doc:
And:
From this paragraph, As you called out:
Since I'm not aware of any language changes (like This has the advantage of not forcing every downstream consumer of your module to bump every time you change the patch version of your go.mod for no real reason (I understand you're not saying that people should do this, only that you think a patch version is required). As for the CI stuff, thank you very much for bringing it up. I'll definitely have a think about it but it feels like addressing this patch disagreement first seems the best. If you have any further reading about the necessity of patch versions in the go directive, please, please, please point me to it. Each of your well-researched comments of mine above were born out from me searching for this information. My decision to pin the go directive to the language version was primarily driven by looking at other large Go projects and seeing at least some of them behaved the same as I anticipated. Cheers! |
Hehe, can fully understand that 🙃. In regards of the patch version as go directive, I decided to ask the expects.
What would you expect from go in case you use the language version?
Did you looked at projects that are actual modules, so a small piece of software that can be included by someone? 🤔 Small update:Seems that is related (haven't read it yet): |
Thanks! I appreciate you asking this question. I understand why
That's a good question. In our particular usage, I would only expect the toolchain to be downloaded and it has a specific patch version. The In the case of
I think in an earlier comment I linked to etcd but you can look through https://github.com/search?q=path%3A**%2Fgo.mod+%2F%5Ego+1.22%24%2F&type=code |
Well, they changed that behaviour in 1.23, 1.22.4, and 1.21.9 🙈 See golang/go#68971 (comment) So using a language version in This also answers my question:
It will download the Because, in fact, if no toolchain is declared, it will use the Still, the question is "using a patch version YES or NO?".
The release versions (starting with 1.21) including patch versions. In general the issue golang/go#62278 is quite interesting to read.
This is of course 100% confusing for everyone. With that being said, I guess the Line 3 in 95a2f95
Agree? I'm happy to discuss the next chapter of that |
I've also spent too much time thinking about this 🙃, here's a relevant issue in |
Thanks so much for the investigation @StefMa. If the go tooling produces patch versions I'm happy to know that the CLI is fine as it is. I think the most important thing generally is that the So with regards CI, I guess the primary complaint is that we're downloading Was there anything I missed? |
This is something I mentioned in my initial description of this issue 🤓. So in my hoenstly opinion, youre fine to use the latest version in the If you don't want/like this (because maybe someone else uses this CLI as a module and you don't want to annoy them), you can keep it like it is of course. But this leads to another question/suggestions/improvement in my initial description issue. If you want to stay at 1.22.0 to keep backwards compatibily, but still want to enjoy reproducible builds as well as a streamlined developer (and CI) workflow, pointing the Being said, Or, you can simply say "I don't want to turn my head around To summarize:
Final summary:
That is exactly the point, yes 🙃 Feel free to close this issue aftwards. |
Sometimes people do important parts of the module: https://github.com/search?type=code&q=path%3A**%2Fgo.mod+%22github.com%2Fcli%2Fcli%22 There's not really an intention to support or not to support this. Personally, I wouldn't have a problem making breaking changes in the cli module to improve our lives, but I also don't want to make life harder for anyone else unnecessarily.
I'd be happy to have a PR for that, please open one if you'd like to. I don't want to bump the
I'll see what I can do here. I'm sure people care but I know the folks in actions have a lot on their plate. Thanks for all the conversation and investigation here to bring clarity. |
Hey together,
I just came across your
go.mod
file. I have to admit I am a bit confused how you decided the values of thego
andtoolchain
directive and I think those should be changed... 🤔Let me explain this.
Note
I am not an go developer by day. Also the toolchain feature is fairly new in the go ecosystem.
Therefore it might be the case that Iam totally wrong with all of this here. If so, please let me know 🙃.
Starting with go 1.21 the behavior of the
go
directive in thego.mod
file changed. Before that version, the statments acts more like an "information". It just indicates what go version that module needs to be compiled with. However, go was not very strict with that. If you used an go version lower than that, go just tried to compile the module. If its succeeded, it's fine, otherwise it's throws an (compile) error.In go 1.21 the
go
statement indicates the minimum go version required to build that module. Same as before, but now more strict.See the docs here
https://go.dev/ref/mod#go-mod-file-go
In go 1.21 they also introduce the
toolchain
directive. With that you can create reproducible builds across the developer (and CI) toolchain. As go will make sure it will always use that exactt go version to compile the module. It does this by downloading the specified go version if your local go version is lower than that.See the docs here
https://go.dev/doc/toolchain
With that change, they also changed their versioning. In the past a
major.minor
version was released. They changed that to release a full semver version instead. With that said, to amajor.minor.patch
version. (Notice the.patch
😉)See the docs here
https://go.dev/doc/toolchain#version
I guess using a non-patch version for higher go versions than 1.21 will only work because of backwards compatibility.
But in fact, it is "wrong". Or at least not considered as best practise anymore.
How does this relates to this project?
In this PR @matthewhughes934 wanted to fix your
go.mod
file by introducing the patch version. He also provided a lot of useful links there.(Note: I don't know why he faced the docker issue, I am not an expert in that field. But regardless of that error, using a patch version is more correct!)
You can checkout his first commit in this PR to see his change:
9fae21f
For reasons he decided together with @williammartin to introduce the toolchain directive.
That also fixed that issue. But not because "it is more correct" (to fix that specific error). But instead it would solve that problem because with the toolchain feature, go will look at this (and download the correct version) and not at the (still wrong) go directive.
I guess 🫠
Later this PR were opened.
Besides of other changes, the
go
directive was changed to1.22.0
(so basically what the first PR also wanted to do 😁 ), AND the toolchain was changed to1.22.5
(from1.22.2
).Here is also a nice comment by @williammartin on that PR, saying "we should report upstream that using a patch version is "wrong"". However, as already pointed out above, using a patch version is actually there more correct usage now. There is no release in go without a patch version anymore!
So actually using
1.22.0
is correct, while using1.22
for the go directive is just wrong.Something about CI.
Right now you are using the
setup-go
action together with thego-version-file: 'go.mod'
.Because you also declared the
toolchain
directive, you download right now 2 versions on your CI.First, the setup-action will download 1.22.0 (based on your go.mod
go
directive), afterwards go (version 1.22.0 you just downloaded) will download1.22.5
. This is because of yourtoolchain
directive in your go.mod file.Since 1.21 is the default go version on github hosted runners, I guess you could avoid downloading
1.22.0
and just rely on the toolchain directive. But I'm not 100% sure with that 🤷 At least, we could save a few seconds on CI 🤓To summarize:
go
directive declares the minimum version now. Nothing more.go
directive should be a valid semver version. (major.minor.patch)Because this CLI project here is a "final end product" and not a module that others use, I guess you are fine by just using the
go
directive that uses always the latest go version.Probably "no one" (assuption) depends on this project and therefore you might not need to declare any backward compatibily with others.
When you decide that, you might want to remove the
toolchain
directive. Why? Because starting with go 1.21, go will automatically download the version declared in thego
directive. Without antoolchain
, it will use automatically thego
declared version as atoolchain
version and hence download it.So there is no need for this.
On the other side, if you think that other go projects depends on you, then it make sense to have both,
go
andtoolchain
.While
go
should be "as low as possible", while thetoolchain
can be always be on the edge to enjoy bug fixes, faster compile time (assuming a greater go version is faster 😅 ), new features, and a streamlined go version across developers (and CI).What do you think? 🤔
The text was updated successfully, but these errors were encountered: