Skip to content
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: Only use EmitInvalidToolchainVersion if installed toolchain is >=1.21 && <1.23 #18499

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions go/extractor/project/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,24 @@ func findGoModFiles(root string) []string {
// A regular expression for the Go toolchain version syntax.
var toolchainVersionRe *regexp.Regexp = regexp.MustCompile(`(?m)^([0-9]+\.[0-9]+\.[0-9]+)$`)

// Returns true if the `go.mod` file specifies a Go language version, that version is `1.21` or greater, and
// there is no `toolchain` directive, and the Go language version is not a valid toolchain version.
func hasInvalidToolchainVersion(modFile *modfile.File) bool {
return modFile.Toolchain == nil && modFile.Go != nil &&
!toolchainVersionRe.Match([]byte(modFile.Go.Version)) && util.NewSemVer(modFile.Go.Version).IsAtLeast(toolchain.V1_21)
// Returns true if the `go.mod` file specifies a Go language version which is not of the format that
// is expected by the Go 1.21 and Go 1.22 toolchains for toolchain versions, and there is no
// explicit toolchain version declared.
func hasInvalidToolchainVersion(installedToolchainVersion util.SemVer, modFile *modfile.File) bool {
if modFile.Toolchain != nil {
// There is an explicit toolchain directive, so it doesn't matter what format the
// Go language version is in, since it will not be used as a fallback toolchain version.
return false
} else if modFile.Go != nil && !toolchainVersionRe.Match([]byte(modFile.Go.Version)) {
// There's no explicit toolchain directive, but we have a language version which
// does not match the toolchain version format in Go 1.21 and Go 1.22.
// This is a problem if the installed Go toolchain is within that version range
// as it will try to use the language version as the toolchain version.
return util.NewSemVer(modFile.Go.Version).IsAtLeast(toolchain.V1_21) &&
installedToolchainVersion.IsAtLeast(toolchain.V1_21) &&
installedToolchainVersion.IsOlderThan(toolchain.V1_23)
}
return false
}

// Given a list of `go.mod` file paths, try to parse them all. The resulting array of `GoModule` objects
Expand Down Expand Up @@ -232,7 +245,7 @@ func LoadGoModules(emitDiagnostics bool, goModFilePaths []string) []*GoModule {
// there is no `toolchain` directive, check that it is a valid Go toolchain version. Otherwise,
// `go` commands which try to download the right version of the Go toolchain will fail. We detect
// this situation and emit a diagnostic.
if hasInvalidToolchainVersion(modFile) {
if hasInvalidToolchainVersion(util.NewSemVer(toolchain.GetEnvGoVersion()), modFile) {
diagnostics.EmitInvalidToolchainVersion(goModFilePath, modFile.Go.Version)
}
}
Expand Down
10 changes: 6 additions & 4 deletions go/extractor/project/project_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,20 @@ func parseModFile(t *testing.T, contents string) *modfile.File {
return modFile
}

func testHasInvalidToolchainVersion(t *testing.T, contents string) bool {
return hasInvalidToolchainVersion(parseModFile(t, contents))
func testHasInvalidToolchainVersion(t *testing.T, installedToolchainVersion util.SemVer, contents string) bool {
return hasInvalidToolchainVersion(installedToolchainVersion, parseModFile(t, contents))
}

func TestHasInvalidToolchainVersion(t *testing.T) {
installedToolchainVersion := util.NewSemVer("1.21")

invalid := []string{
"go 1.21\n",
"go 1.22\n",
}

for _, v := range invalid {
if !testHasInvalidToolchainVersion(t, v) {
if !testHasInvalidToolchainVersion(t, installedToolchainVersion, v) {
t.Errorf("Expected testHasInvalidToolchainVersion(\"%s\") to be true, but got false", v)
}
}
Expand All @@ -62,7 +64,7 @@ func TestHasInvalidToolchainVersion(t *testing.T) {
}

for _, v := range valid {
if testHasInvalidToolchainVersion(t, v) {
if testHasInvalidToolchainVersion(t, installedToolchainVersion, v) {
t.Errorf("Expected testHasInvalidToolchainVersion(\"%s\") to be false, but got true", v)
}
}
Expand Down
1 change: 1 addition & 0 deletions go/extractor/toolchain/toolchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ var V1_14 = util.NewSemVer("v1.14.0")
var V1_16 = util.NewSemVer("v1.16.0")
var V1_18 = util.NewSemVer("v1.18.0")
var V1_21 = util.NewSemVer("v1.21.0")
var V1_23 = util.NewSemVer("v1.23.0")

// Check if Go is installed in the environment.
func IsInstalled() bool {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,3 @@
{
"location": {
"file": "go.mod"
},
"markdownMessage": "As of Go 1.21, toolchain versions [must use the 1.N.P syntax](https://go.dev/doc/toolchain#version).\n\n`1.21` in `go.mod` does not match this syntax and there is no additional `toolchain` directive, which may cause some `go` commands to fail.",
"severity": "warning",
"source": {
"extractorName": "go",
"id": "go/autobuilder/invalid-go-toolchain-version",
"name": "Invalid Go toolchain version"
},
"visibility": {
"cliSummaryTable": true,
"statusPage": true,
"telemetry": true
}
}
{
"markdownMessage": "A single `go.mod` file was found.\n\n`go.mod`",
"severity": "note",
Expand Down
17 changes: 0 additions & 17 deletions go/ql/integration-tests/go-version-bump/diagnostics.expected
Original file line number Diff line number Diff line change
@@ -1,20 +1,3 @@
{
"location": {
"file": "go.mod"
},
"markdownMessage": "As of Go 1.21, toolchain versions [must use the 1.N.P syntax](https://go.dev/doc/toolchain#version).\n\n`1.21` in `go.mod` does not match this syntax and there is no additional `toolchain` directive, which may cause some `go` commands to fail.",
"severity": "warning",
"source": {
"extractorName": "go",
"id": "go/autobuilder/invalid-go-toolchain-version",
"name": "Invalid Go toolchain version"
},
"visibility": {
"cliSummaryTable": true,
"statusPage": true,
"telemetry": true
}
}
{
"markdownMessage": "A single `go.mod` file was found.\n\n`go.mod`",
"severity": "note",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,3 @@
{
"location": {
"file": "go.mod"
},
"markdownMessage": "As of Go 1.21, toolchain versions [must use the 1.N.P syntax](https://go.dev/doc/toolchain#version).\n\n`1.22` in `go.mod` does not match this syntax and there is no additional `toolchain` directive, which may cause some `go` commands to fail.",
"severity": "warning",
"source": {
"extractorName": "go",
"id": "go/autobuilder/invalid-go-toolchain-version",
"name": "Invalid Go toolchain version"
},
"visibility": {
"cliSummaryTable": true,
"statusPage": true,
"telemetry": true
}
}
{
"markdownMessage": "A single `go.mod` file was found.\n\n`go.mod`",
"severity": "note",
Expand Down