Go: remove invalid toolchain version diagnostics

This diagnostic was introduced by https://github.com/github/codeql/pull/15979.
However in the meantime the Go team [has backtracked](https://github.com/golang/go/issues/62278#issuecomment-2062002018)
on their decision, which leads to confusing alerts for user (e.g. https://github.com/github/codeql-action/issues/2868).
Even using Go toolchains from 1.21 to 1.22 we weren't immediately able
to reproduce the problem that this diagnostics was meant to guard
against. Therefore it was deemed simpler to just remove it.

_En passant_ the `Makefile` now accepts `rtjo` not being set.
This commit is contained in:
Paolo Tranquilli
2025-04-24 14:41:05 +02:00
parent ea83ecf802
commit 69b87a63b8
12 changed files with 11 additions and 155 deletions

View File

@@ -5,6 +5,8 @@
# and that we actually get are too big, the build fails on CI.
BAZEL := $(shell bash -c "which bazel")
rtjo ?= none
all: gen extractor
EXTRACTOR_PACK_OUT = extractor-pack

View File

@@ -425,7 +425,7 @@ func installDependencies(workspace project.GoWorkspace) {
} else {
if workspace.Modules == nil {
project.InitGoModForLegacyProject(workspace.BaseDir)
workspace.Modules = project.LoadGoModules(true, []string{filepath.Join(workspace.BaseDir, "go.mod")})
workspace.Modules = project.LoadGoModules([]string{filepath.Join(workspace.BaseDir, "go.mod")})
}
// get dependencies for all modules

View File

@@ -508,18 +508,3 @@ func EmitExtractionFailedForProjects(path []string) {
noLocation,
)
}
func EmitInvalidToolchainVersion(goModPath string, version string) {
emitDiagnostic(
"go/autobuilder/invalid-go-toolchain-version",
"Invalid Go toolchain version",
strings.Join([]string{
"As of Go 1.21, toolchain versions [must use the 1.N.P syntax](https://go.dev/doc/toolchain#version).",
fmt.Sprintf("`%s` in `%s` does not match this syntax and there is no additional `toolchain` directive, which may cause some `go` commands to fail.", version, goModPath),
},
"\n\n"),
severityWarning,
fullVisibility,
&locationStruct{File: goModPath},
)
}

View File

@@ -192,20 +192,10 @@ func findGoModFiles(root string) []string {
return util.FindAllFilesWithName(root, "go.mod", util.SkipVendorChecks...)
}
// A regular expression for the Go toolchain version syntax.
var toolchainVersionRe *regexp.Regexp = regexp.MustCompile(`(?m)^([0-9]+\.[0-9]+(\.[0-9]+|rc[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)
}
// Given a list of `go.mod` file paths, try to parse them all. The resulting array of `GoModule` objects
// will be the same length as the input array and the objects will contain at least the `go.mod` path.
// If parsing the corresponding file is successful, then the parsed contents will also be available.
func LoadGoModules(emitDiagnostics bool, goModFilePaths []string) []*GoModule {
func LoadGoModules(goModFilePaths []string) []*GoModule {
results := make([]*GoModule, len(goModFilePaths))
for i, goModFilePath := range goModFilePaths {
@@ -227,14 +217,6 @@ func LoadGoModules(emitDiagnostics bool, goModFilePaths []string) []*GoModule {
}
results[i].Module = modFile
// If this `go.mod` file specifies a Go language version, that version is `1.21` or greater, and
// 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) {
diagnostics.EmitInvalidToolchainVersion(goModFilePath, modFile.Go.Version)
}
}
return results
@@ -243,7 +225,7 @@ func LoadGoModules(emitDiagnostics bool, goModFilePaths []string) []*GoModule {
// Given a path to a `go.work` file, this function attempts to parse the `go.work` file. If unsuccessful,
// we attempt to discover `go.mod` files within subdirectories of the directory containing the `go.work`
// file ourselves.
func discoverWorkspace(emitDiagnostics bool, workFilePath string) GoWorkspace {
func discoverWorkspace(workFilePath string) GoWorkspace {
log.Printf("Loading %s...\n", workFilePath)
baseDir := filepath.Dir(workFilePath)
workFileSrc, err := os.ReadFile(workFilePath)
@@ -257,7 +239,7 @@ func discoverWorkspace(emitDiagnostics bool, workFilePath string) GoWorkspace {
return GoWorkspace{
BaseDir: baseDir,
Modules: LoadGoModules(emitDiagnostics, goModFilePaths),
Modules: LoadGoModules(goModFilePaths),
DepMode: GoGetWithModules,
ModMode: getModMode(GoGetWithModules, baseDir),
}
@@ -274,7 +256,7 @@ func discoverWorkspace(emitDiagnostics bool, workFilePath string) GoWorkspace {
return GoWorkspace{
BaseDir: baseDir,
Modules: LoadGoModules(emitDiagnostics, goModFilePaths),
Modules: LoadGoModules(goModFilePaths),
DepMode: GoGetWithModules,
ModMode: getModMode(GoGetWithModules, baseDir),
}
@@ -297,7 +279,7 @@ func discoverWorkspace(emitDiagnostics bool, workFilePath string) GoWorkspace {
return GoWorkspace{
BaseDir: baseDir,
WorkspaceFile: workFile,
Modules: LoadGoModules(emitDiagnostics, goModFilePaths),
Modules: LoadGoModules(goModFilePaths),
DepMode: GoGetWithModules,
ModMode: ModReadonly, // Workspaces only support "readonly"
}
@@ -325,7 +307,7 @@ func discoverWorkspaces(emitDiagnostics bool) []GoWorkspace {
for i, goModFile := range goModFiles {
results[i] = GoWorkspace{
BaseDir: filepath.Dir(goModFile),
Modules: LoadGoModules(emitDiagnostics, []string{goModFile}),
Modules: LoadGoModules([]string{goModFile}),
DepMode: GoGetWithModules,
ModMode: getModMode(GoGetWithModules, filepath.Dir(goModFile)),
}
@@ -342,7 +324,7 @@ func discoverWorkspaces(emitDiagnostics bool) []GoWorkspace {
results := make([]GoWorkspace, len(goWorkFiles))
for i, workFilePath := range goWorkFiles {
results[i] = discoverWorkspace(emitDiagnostics, workFilePath)
results[i] = discoverWorkspace(workFilePath)
}
// Add all stray `go.mod` files (i.e. those not referenced by `go.work` files)
@@ -374,7 +356,7 @@ func discoverWorkspaces(emitDiagnostics bool) []GoWorkspace {
log.Printf("Module %s is not referenced by any go.work file; adding it separately.\n", goModFile)
results = append(results, GoWorkspace{
BaseDir: filepath.Dir(goModFile),
Modules: LoadGoModules(emitDiagnostics, []string{goModFile}),
Modules: LoadGoModules([]string{goModFile}),
DepMode: GoGetWithModules,
ModMode: getModMode(GoGetWithModules, filepath.Dir(goModFile)),
})

View File

@@ -39,35 +39,6 @@ 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) {
invalid := []string{
"go 1.21\n",
"go 1.22\n",
}
for _, v := range invalid {
if !testHasInvalidToolchainVersion(t, v) {
t.Errorf("Expected testHasInvalidToolchainVersion(\"%s\") to be true, but got false", v)
}
}
valid := []string{
"go 1.20\n",
"go 1.21.1\n",
"go 1.22\n\ntoolchain go1.22.0\n",
}
for _, v := range valid {
if testHasInvalidToolchainVersion(t, v) {
t.Errorf("Expected testHasInvalidToolchainVersion(\"%s\") to be false, but got true", v)
}
}
}
func parseWorkFile(t *testing.T, contents string) *modfile.WorkFile {
workFile, err := modfile.ParseWork("go.work", []byte(contents), nil)

View File

@@ -1,5 +0,0 @@
{
"configuration" : {
"go" : { }
}
}

View File

@@ -1,31 +0,0 @@
{
"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",
"source": {
"extractorName": "go",
"id": "go/autobuilder/single-root-go-mod-found",
"name": "A single `go.mod` file was found in the root"
},
"visibility": {
"cliSummaryTable": false,
"statusPage": false,
"telemetry": true
}
}

View File

@@ -1,3 +0,0 @@
go 1.21
module example

View File

@@ -1,5 +0,0 @@
package main
func main() {
}

View File

@@ -1,6 +0,0 @@
import os
def test(codeql, go):
os.environ["LGTM_INDEX_IMPORT_PATH"] = "test"
codeql.database.create(source_root="src")

View File

@@ -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",

View File

@@ -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",