-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Go: change logic in go-autobuilder --identify-environment
#13040
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
Go: change logic in go-autobuilder --identify-environment
#13040
Conversation
The failing integration test is because an old macOS image was specified. It has since been removed. |
This does not change the version returned. In the case the the go mod version is supported and the go env version is below goMinVersion, the message now talks about go env version being unsupported instead of it being less than go mod version. This seems more sensible to me.
a60b88e
to
d329da6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. One small comment about incorporating some of the reasoning behind the logic we have implemented here in the code so that it doesn't disappear over time.
ab1c627
to
f86451e
Compare
I've updated this to deal with the following situation: if the go.mod file says 1.11 and our minimum supported version is 1.12 then previously we were not installing a version of Go, whereas now we are installing version 1.12. Because our current minimum supported version is 1.11 and go.mod files were only supported in version 1.11 this is highly unlikely to happen in practice, but it seemed worth dealing with it now as we won't think of it if we ever raise our minimum supported version. |
f86451e
to
c09f616
Compare
c09f616
to
375be68
Compare
func belowSupportedRange(version string) bool { | ||
return semver.Compare(semver.MajorMinor("v"+version), "v"+minGoVersion) < 0 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I keep thinking that I really wish Go had something like Haskell's newtype
which let you create a new nominal type to distinguish e.g. between version strings that include the "v"
and ones that don't.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know Haskell, but perhaps you can create a new type with the same underlying type with type semverVersion string
.
I admit that the treatment of version strings in this file is a mess. I've stuck with no prefix in the code I've added, but I haven't changed it elsewhere, which just stores up the problem for later. I wanted to avoid accidentally changing current behaviour.
// We definitely need to install a version. We have no indication which version was | ||
// intended to be used to build this project. Go versions are generally backwards | ||
// compatible, so we install the maximum supported version. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is the same as for the previous condition, so based on the comments it is not clear how these are different.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have updated it now. I tried not to repeat information that is already in the msg
in the comment, but instead focus on explaining the reasoning behind why we act that way. (No doubt I could have done better.)
msg = "No `go.mod` file found. The version of Go installed in the environment (" + | ||
v.goEnvVersion + ") is outside of the supported range (" + minGoVersion + "-" + | ||
maxGoVersion + "). Writing an environment file specifying the maximum supported " + | ||
"version of Go (" + maxGoVersion + ")." | ||
version = maxGoVersion | ||
diagnostics.EmitNoGoModAndGoEnvUnsupported(msg) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking about whether to suggest this during my last review, but I am not convinced that this is the right approach. Consider a self-hosted runner / custom image where a particular version of Go is installed on purpose. The behaviour that is implemented here would override whatever version of Go might be deliberately installed on the system. Perhaps we could do this if we find ourselves in a GHA environment (i.e. GITHUB_ACTIONS
is set) but not otherwise?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We try to use the version of Go in the environment if we can. This branch is dealing with the case that the version of Go in the environment is not supported, e.g. Go 1.21 has been released and we haven't added support for it yet.
// Assuming `v.goModVersion` is above the supported range, emit a diagnostic and return the | ||
// version to install, or the empty string if we should not attempt to install a version of Go. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment suggests that this function may return a version to install, which it never does.
msg = "The version of Go found in the `go.mod` file (" + v.goModVersion + | ||
") is above the supported range (" + minGoVersion + "-" + maxGoVersion + | ||
"). Writing an environment file not specifying any version of Go." | ||
version = "" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this lead to automatic failure if no version of Go is installed on the system? Would it be better to at least try to proceed with the latest supported version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If they have Go 1.21 in their go.mod and we don't support that yet, then the behaviour currently specified by this PR is to not install a version of Go, even if there is no version installed. I think it would be weird if we install version 1.20 and then potentially fall over on some incompatibility, not to mention showing them a diagnostic on the Tools Status Page that they need to install a newer version of Go.
// Assuming `v.goModVersion` is above the supported range, emit a diagnostic and return the | ||
// version to install, or the empty string if we should not attempt to install a version of Go. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment here is the same as for getVersionWhenGoModVersionTooHigh
but should really read:
// Assuming `v.goModVersion` is above the supported range, emit a diagnostic and return the | |
// version to install, or the empty string if we should not attempt to install a version of Go. | |
// Assuming `v.goModVersion` is below the supported range, emit a diagnostic and return the | |
// version to install, or the empty string if we should not attempt to install a version of Go. |
// Assuming `v.goModVersion` is above the supported range, emit a diagnostic and return the | ||
// version to install, or the empty string if we should not attempt to install a version of Go. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment here is the same as for getVersionWhenGoModVersionTooHigh
but should really read:
// Assuming `v.goModVersion` is above the supported range, emit a diagnostic and return the | |
// version to install, or the empty string if we should not attempt to install a version of Go. | |
// Assuming `v.goModVersion` is below the supported range, emit a diagnostic and return the | |
// version to install, or the empty string if we should not attempt to install a version of Go. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be the same as the comment above. I'm not sure how that's possible.
// compatible, so we install the maximum supported version. | ||
msg = "No `go.mod` file found. The version of Go installed in the environment (" + | ||
v.goEnvVersion + ") is outside of the supported range (" + minGoVersion + "-" + | ||
maxGoVersion + "). Writing an environment file specifying the maximum supported " + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since these diagnostics are potentially user-facing, maybe use "Requesting" instead of "Writing an environment file"
msg = "No version of Go installed and no `go.mod` file found. Writing an environment " + | ||
"file specifying the maximum supported version of Go (" + maxGoVersion + ")." | ||
version = maxGoVersion | ||
diagnostics.EmitNoGoModAndNoGoEnv(msg) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note we're liable to be running --identify-environment
before codeql-init ==> no database ==> nowhere to put diagnostics at this stage. We'd need to work with the action to put diagnostics somewhere, or just emit these as log prints pending such a solution.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are diagnostics put in the database? I thought they were just written as files somewhere, but I admit I don't know what happens after that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I now understand what you mean. If the diagnostic directory environment variable is not set, no diagnostics will be emitted, and one log line will be printed stating that. If we want to gather the diagnostics we'll have to set the env var and collect the diagnostic files ourselves in the action. This can be a future task.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense -- if identify-environment can raise diagnostics, this could be included in its output for the Action to record once that makes sense.
@@ -803,18 +871,19 @@ func compareVersions(v versionInfo) (msg, version string) { | |||
// Check the versions of Go found in the environment and in the `go.mod` file, and return a | |||
// version to install. If the version is the empty string then no installation is required. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So at the moment this is...
Requested > Installed \/ | None | Unsupported old | Unsupported new | Supported |
---|---|---|---|---|
None | Install max supported | Install min supported | No action (!) | Install requested |
Unsupported old | Install max supported | Install min supported | No action (!) | Install requested |
Unsupported new | Install max supported | Install min supported | No action | Install requested |
Supported | No action | No action | No action (!!) | Install requested if newer than installed |
Suggest the cells highlighted with (!) should be install max supported, in keeping with our practice elsewhere of not intentionally upgrading to a too-new Go, but responding constructively to a too-old or missing environmental Go.
Suggest the cell highlighted with (!!) should be install max supported if newer than installed, since it would be odd to rule that have go 1.17, request go 1.20 ==> upgrade to 1.20; have go 1.17, request go 1.21 ==> try with go 1.17.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You and @mbg seem to agree on this, so I'll make the change
Currently our supported range is 1.11-1.20. If the version of Go installed in the environment is outside of that range we decide not to do anything. It would actually be fine to just install the desired version of Go (if that’s supported). I guess this would guard against the case that the image used in Actions gets a new version of Go (1.21, say) before we start supporting it. Or if it’s a really old image, and has Go 1.10 on it.