From 3649af3f0568fc544cbeef82f6e4e386aab62003 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Mon, 18 Mar 2024 17:56:59 +0000 Subject: [PATCH 01/12] Go: Add test for `go/autobuilder/invalid-go-toolchain-version` diagnostic --- .../diagnostics.expected | 31 +++++++++++++++++++ .../invalid-toolchain-version/src/go.mod | 3 ++ .../invalid-toolchain-version/src/main.go | 5 +++ .../invalid-toolchain-version/test.py | 19 ++++++++++++ 4 files changed, 58 insertions(+) create mode 100644 go/ql/integration-tests/all-platforms/go/diagnostics/invalid-toolchain-version/diagnostics.expected create mode 100644 go/ql/integration-tests/all-platforms/go/diagnostics/invalid-toolchain-version/src/go.mod create mode 100644 go/ql/integration-tests/all-platforms/go/diagnostics/invalid-toolchain-version/src/main.go create mode 100644 go/ql/integration-tests/all-platforms/go/diagnostics/invalid-toolchain-version/test.py diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/invalid-toolchain-version/diagnostics.expected b/go/ql/integration-tests/all-platforms/go/diagnostics/invalid-toolchain-version/diagnostics.expected new file mode 100644 index 000000000000..e506cc1e2300 --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/invalid-toolchain-version/diagnostics.expected @@ -0,0 +1,31 @@ +{ + "location": { + "file": "go.mod" + }, + "markdownMessage": "As of Go 1.21, toolchain versions [must use the 1.N.P syntax](https://tip.golang.org/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": "`1.21` is not a valid 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 + } +} diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/invalid-toolchain-version/src/go.mod b/go/ql/integration-tests/all-platforms/go/diagnostics/invalid-toolchain-version/src/go.mod new file mode 100644 index 000000000000..bee3365b8999 --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/invalid-toolchain-version/src/go.mod @@ -0,0 +1,3 @@ +go 1.21 + +module example diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/invalid-toolchain-version/src/main.go b/go/ql/integration-tests/all-platforms/go/diagnostics/invalid-toolchain-version/src/main.go new file mode 100644 index 000000000000..79058077776c --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/invalid-toolchain-version/src/main.go @@ -0,0 +1,5 @@ +package main + +func main() { + +} diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/invalid-toolchain-version/test.py b/go/ql/integration-tests/all-platforms/go/diagnostics/invalid-toolchain-version/test.py new file mode 100644 index 000000000000..2824c219d376 --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/invalid-toolchain-version/test.py @@ -0,0 +1,19 @@ +import os +import subprocess + +from create_database_utils import * +from diagnostics_test_utils import * + +# Set up a GOPATH relative to this test's root directory; +# we set os.environ instead of using extra_env because we +# need it to be set for the call to "go clean -modcache" later +goPath = os.path.join(os.path.abspath(os.getcwd()), ".go") +os.environ['GOPATH'] = goPath +os.environ['LGTM_INDEX_IMPORT_PATH'] = "test" +run_codeql_database_create([], lang="go", source="src") + +check_diagnostics() + +# Clean up the temporary GOPATH to prevent Bazel failures next +# time the tests are run; see https://github.com/golang/go/issues/27161 +subprocess.call(["go", "clean", "-modcache"]) From be027e217e9b55c4ea1120a14f40f0a62bd686c5 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 19 Mar 2024 16:26:06 +0000 Subject: [PATCH 02/12] Go: Emit diagnostic for invalid toolchain versions --- .../cli/go-autobuilder/go-autobuilder.go | 2 +- go/extractor/diagnostics/diagnostics.go | 15 ++++++++++ go/extractor/project/project.go | 28 +++++++++++++------ 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/go/extractor/cli/go-autobuilder/go-autobuilder.go b/go/extractor/cli/go-autobuilder/go-autobuilder.go index 91291c771448..33c0b0e04613 100644 --- a/go/extractor/cli/go-autobuilder/go-autobuilder.go +++ b/go/extractor/cli/go-autobuilder/go-autobuilder.go @@ -475,7 +475,7 @@ func installDependencies(workspace project.GoWorkspace) { } else { if workspace.Modules == nil { project.InitGoModForLegacyProject(workspace.BaseDir) - workspace.Modules = project.LoadGoModules([]string{filepath.Join(workspace.BaseDir, "go.mod")}) + workspace.Modules = project.LoadGoModules(true, []string{filepath.Join(workspace.BaseDir, "go.mod")}) } // get dependencies for all modules diff --git a/go/extractor/diagnostics/diagnostics.go b/go/extractor/diagnostics/diagnostics.go index c02af8afb92e..197d838a1215 100644 --- a/go/extractor/diagnostics/diagnostics.go +++ b/go/extractor/diagnostics/diagnostics.go @@ -508,3 +508,18 @@ func EmitExtractionFailedForProjects(path []string) { noLocation, ) } + +func EmitInvalidToolchainVersion(goModPath string, version string) { + emitDiagnostic( + "go/autobuilder/invalid-go-toolchain-version", + fmt.Sprintf("`%s` is not a valid Go toolchain version", version), + strings.Join([]string{ + "As of Go 1.21, toolchain versions [must use the 1.N.P syntax](https://tip.golang.org/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}, + ) +} diff --git a/go/extractor/project/project.go b/go/extractor/project/project.go index 187389ecd553..580be07eceb6 100644 --- a/go/extractor/project/project.go +++ b/go/extractor/project/project.go @@ -176,10 +176,13 @@ func findGoModFiles(root string) []string { return util.FindAllFilesWithName(root, "go.mod", "vendor") } +// A regular expression for the Go toolchain version syntax. +var toolchainVersionRe *regexp.Regexp = regexp.MustCompile(`(?m)^([0-9]+\.[0-9]+\.[0-9]+)$`) + // 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(goModFilePaths []string) []*GoModule { +func LoadGoModules(emitDiagnostics bool, goModFilePaths []string) []*GoModule { results := make([]*GoModule, len(goModFilePaths)) for i, goModFilePath := range goModFilePaths { @@ -201,6 +204,15 @@ func LoadGoModules(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 modFile.Toolchain == nil && modFile.Go != nil && + !toolchainVersionRe.Match([]byte(modFile.Go.Version)) && semver.Compare("v"+modFile.Go.Version, "v1.21.0") >= 0 { + diagnostics.EmitInvalidToolchainVersion(goModFilePath, modFile.Go.Version) + } } return results @@ -209,7 +221,7 @@ func LoadGoModules(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(workFilePath string) GoWorkspace { +func discoverWorkspace(emitDiagnostics bool, workFilePath string) GoWorkspace { log.Printf("Loading %s...\n", workFilePath) baseDir := filepath.Dir(workFilePath) workFileSrc, err := os.ReadFile(workFilePath) @@ -223,7 +235,7 @@ func discoverWorkspace(workFilePath string) GoWorkspace { return GoWorkspace{ BaseDir: baseDir, - Modules: LoadGoModules(goModFilePaths), + Modules: LoadGoModules(emitDiagnostics, goModFilePaths), DepMode: GoGetWithModules, ModMode: getModMode(GoGetWithModules, baseDir), } @@ -240,7 +252,7 @@ func discoverWorkspace(workFilePath string) GoWorkspace { return GoWorkspace{ BaseDir: baseDir, - Modules: LoadGoModules(goModFilePaths), + Modules: LoadGoModules(emitDiagnostics, goModFilePaths), DepMode: GoGetWithModules, ModMode: getModMode(GoGetWithModules, baseDir), } @@ -263,7 +275,7 @@ func discoverWorkspace(workFilePath string) GoWorkspace { return GoWorkspace{ BaseDir: baseDir, WorkspaceFile: workFile, - Modules: LoadGoModules(goModFilePaths), + Modules: LoadGoModules(emitDiagnostics, goModFilePaths), DepMode: GoGetWithModules, ModMode: ModReadonly, // Workspaces only support "readonly" } @@ -286,7 +298,7 @@ func discoverWorkspaces(emitDiagnostics bool) []GoWorkspace { for i, goModFile := range goModFiles { results[i] = GoWorkspace{ BaseDir: filepath.Dir(goModFile), - Modules: LoadGoModules([]string{goModFile}), + Modules: LoadGoModules(emitDiagnostics, []string{goModFile}), DepMode: GoGetWithModules, ModMode: getModMode(GoGetWithModules, filepath.Dir(goModFile)), } @@ -303,7 +315,7 @@ func discoverWorkspaces(emitDiagnostics bool) []GoWorkspace { results := make([]GoWorkspace, len(goWorkFiles)) for i, workFilePath := range goWorkFiles { - results[i] = discoverWorkspace(workFilePath) + results[i] = discoverWorkspace(emitDiagnostics, workFilePath) } // Add all stray `go.mod` files (i.e. those not referenced by `go.work` files) @@ -335,7 +347,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([]string{goModFile}), + Modules: LoadGoModules(emitDiagnostics, []string{goModFile}), DepMode: GoGetWithModules, ModMode: getModMode(GoGetWithModules, filepath.Dir(goModFile)), }) From 96a6dd72cdde1582b44b28ce9e279d95b6f286a9 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 20 Mar 2024 13:08:59 +0000 Subject: [PATCH 03/12] Go: Move `go version` command construction into its own function --- go/extractor/toolchain/toolchain.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/go/extractor/toolchain/toolchain.go b/go/extractor/toolchain/toolchain.go index 38abfd43874c..97b1d75e0857 100644 --- a/go/extractor/toolchain/toolchain.go +++ b/go/extractor/toolchain/toolchain.go @@ -25,7 +25,7 @@ func GetEnvGoVersion() string { // download the version of Go specified in there. That may either fail or result in us just // being told what's already in 'go.mod'. Setting 'GOTOOLCHAIN' to 'local' will force it // to use the local Go toolchain instead. - cmd := exec.Command("go", "version") + cmd := Version() cmd.Env = append(os.Environ(), "GOTOOLCHAIN=local") out, err := cmd.CombinedOutput() @@ -92,3 +92,9 @@ func VendorModule(path string) *exec.Cmd { modVendor.Dir = path return modVendor } + +// Constructs a command to run `go version`. +func Version() *exec.Cmd { + version := exec.Command("go", "version") + return version +} From 0d527b2f75c8a3006a10b9b6b44b54ebb3ffe70e Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 20 Mar 2024 13:51:17 +0000 Subject: [PATCH 04/12] Go: Keep track of all installed toolchains that we know of --- go/extractor/toolchain/toolchain.go | 55 +++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/go/extractor/toolchain/toolchain.go b/go/extractor/toolchain/toolchain.go index 97b1d75e0857..a91bf64ba7d4 100644 --- a/go/extractor/toolchain/toolchain.go +++ b/go/extractor/toolchain/toolchain.go @@ -16,7 +16,15 @@ func IsInstalled() bool { return err == nil } +// The default Go version that is available on a system and a set of all versions +// that we know are installed on the system. var goVersion = "" +var goVersions = map[string]struct{}{} + +// Adds an entry to the set of installed Go versions for the normalised `version` number. +func addGoVersion(version string) { + goVersions[semver.Canonical(version)] = struct{}{} +} // Returns the current Go version as returned by 'go version', e.g. go1.14.4 func GetEnvGoVersion() string { @@ -34,10 +42,57 @@ func GetEnvGoVersion() string { } goVersion = parseGoVersion(string(out)) + addGoVersion(goVersion) } return goVersion } +// Determines whether, to our knowledge, `version` is available on the current system. +func HasGoVersion(version string) bool { + _, found := goVersions[semver.Canonical(version)] + return found +} + +// Attempts to install the Go toolchain `version`. +func InstallVersion(workingDir string, version string) bool { + // No need to install it if we know that it is already installed. + if HasGoVersion(version) { + return true + } + + // Construct a command to invoke `go version` with `GOTOOLCHAIN=go1.N.0` to give + // Go a valid toolchain version to download the toolchain we need; subsequent commands + // should then work even with an invalid version that's still in `go.mod` + toolchainArg := "GOTOOLCHAIN=go" + semver.Canonical(version) + versionCmd := Version() + versionCmd.Dir = workingDir + versionCmd.Env = append(os.Environ(), toolchainArg) + + log.Printf( + "Trying to install Go %s using its canonical representation in `%s`.", + version, + workingDir, + ) + + // Run the command. If something goes wrong, report it to the log and signal failure + // to the caller. + if versionErr := versionCmd.Run(); versionErr != nil { + log.Printf( + "Failed to invoke `%s go version` in %s: %s\n", + toolchainArg, + versionCmd.Dir, + versionErr.Error(), + ) + + return false + } + + // Add the version to the set of versions that we know are installed and signal + // success to the caller. + addGoVersion(version) + return true +} + // Returns the current Go version in semver format, e.g. v1.14.4 func GetEnvGoSemVer() string { goVersion := GetEnvGoVersion() From c74d6348f9c35952fe0769b46f5770070a7f3c66 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 20 Mar 2024 13:30:10 +0000 Subject: [PATCH 05/12] Go: Run `go` with a valid toolchain version if we have found an invalid one --- go/extractor/project/project.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/go/extractor/project/project.go b/go/extractor/project/project.go index 580be07eceb6..7deb2d2ad94e 100644 --- a/go/extractor/project/project.go +++ b/go/extractor/project/project.go @@ -212,6 +212,16 @@ func LoadGoModules(emitDiagnostics bool, goModFilePaths []string) []*GoModule { if modFile.Toolchain == nil && modFile.Go != nil && !toolchainVersionRe.Match([]byte(modFile.Go.Version)) && semver.Compare("v"+modFile.Go.Version, "v1.21.0") >= 0 { diagnostics.EmitInvalidToolchainVersion(goModFilePath, modFile.Go.Version) + + modPath := filepath.Dir(goModFilePath) + + log.Printf( + "`%s` is not a valid toolchain version, trying to install it explicitly using the canonical representation in `%s`.", + modFile.Go.Version, + modPath, + ) + + toolchain.InstallVersion(modPath, modFile.Go.Version) } } From 86bf4fbbc08951b14662113d2012d95e33e1c89a Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 27 Mar 2024 13:49:40 +0000 Subject: [PATCH 06/12] Go: Make diagnostic names static --- go/extractor/diagnostics/diagnostics.go | 6 +++--- .../invalid-toolchain-version/diagnostics.expected | 4 ++-- .../go/two-go-mods-one-failure/diagnostics.expected | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go/extractor/diagnostics/diagnostics.go b/go/extractor/diagnostics/diagnostics.go index 197d838a1215..385c611aac81 100644 --- a/go/extractor/diagnostics/diagnostics.go +++ b/go/extractor/diagnostics/diagnostics.go @@ -497,7 +497,7 @@ func EmitNewerSystemGoRequired(requiredVersion string) { func EmitExtractionFailedForProjects(path []string) { emitDiagnostic( "go/autobuilder/extraction-failed-for-project", - fmt.Sprintf("Unable to extract %d Go projects", len(path)), + "Unable to extract some Go projects", fmt.Sprintf( "The following %d Go project%s could not be extracted successfully:\n\n`%s`\n", len(path), @@ -512,9 +512,9 @@ func EmitExtractionFailedForProjects(path []string) { func EmitInvalidToolchainVersion(goModPath string, version string) { emitDiagnostic( "go/autobuilder/invalid-go-toolchain-version", - fmt.Sprintf("`%s` is not a valid Go toolchain version", version), + "Invalid Go toolchain version", strings.Join([]string{ - "As of Go 1.21, toolchain versions [must use the 1.N.P syntax](https://tip.golang.org/doc/toolchain#version).", + "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"), diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/invalid-toolchain-version/diagnostics.expected b/go/ql/integration-tests/all-platforms/go/diagnostics/invalid-toolchain-version/diagnostics.expected index e506cc1e2300..2e5d732e53e7 100644 --- a/go/ql/integration-tests/all-platforms/go/diagnostics/invalid-toolchain-version/diagnostics.expected +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/invalid-toolchain-version/diagnostics.expected @@ -2,12 +2,12 @@ "location": { "file": "go.mod" }, - "markdownMessage": "As of Go 1.21, toolchain versions [must use the 1.N.P syntax](https://tip.golang.org/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.", + "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": "`1.21` is not a valid Go toolchain version" + "name": "Invalid Go toolchain version" }, "visibility": { "cliSummaryTable": true, diff --git a/go/ql/integration-tests/all-platforms/go/two-go-mods-one-failure/diagnostics.expected b/go/ql/integration-tests/all-platforms/go/two-go-mods-one-failure/diagnostics.expected index 02805a60c998..c37938d5c7c3 100644 --- a/go/ql/integration-tests/all-platforms/go/two-go-mods-one-failure/diagnostics.expected +++ b/go/ql/integration-tests/all-platforms/go/two-go-mods-one-failure/diagnostics.expected @@ -18,7 +18,7 @@ "source": { "extractorName": "go", "id": "go/autobuilder/extraction-failed-for-project", - "name": "Unable to extract 1 Go projects" + "name": "Unable to extract some Go projects" }, "visibility": { "cliSummaryTable": true, From ab255d70b52e57851eeab255c6355af3d1237cd8 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 27 Mar 2024 15:15:20 +0000 Subject: [PATCH 07/12] Go: Fix `semver`-related logic bugs --- go/extractor/toolchain/toolchain.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/go/extractor/toolchain/toolchain.go b/go/extractor/toolchain/toolchain.go index a91bf64ba7d4..2cc6b5b4d543 100644 --- a/go/extractor/toolchain/toolchain.go +++ b/go/extractor/toolchain/toolchain.go @@ -23,7 +23,7 @@ var goVersions = map[string]struct{}{} // Adds an entry to the set of installed Go versions for the normalised `version` number. func addGoVersion(version string) { - goVersions[semver.Canonical(version)] = struct{}{} + goVersions[semver.Canonical("v"+version)] = struct{}{} } // Returns the current Go version as returned by 'go version', e.g. go1.14.4 @@ -42,14 +42,14 @@ func GetEnvGoVersion() string { } goVersion = parseGoVersion(string(out)) - addGoVersion(goVersion) + addGoVersion(goVersion[2:]) } return goVersion } // Determines whether, to our knowledge, `version` is available on the current system. func HasGoVersion(version string) bool { - _, found := goVersions[semver.Canonical(version)] + _, found := goVersions[semver.Canonical("v"+version)] return found } @@ -63,7 +63,7 @@ func InstallVersion(workingDir string, version string) bool { // Construct a command to invoke `go version` with `GOTOOLCHAIN=go1.N.0` to give // Go a valid toolchain version to download the toolchain we need; subsequent commands // should then work even with an invalid version that's still in `go.mod` - toolchainArg := "GOTOOLCHAIN=go" + semver.Canonical(version) + toolchainArg := "GOTOOLCHAIN=go" + semver.Canonical("v" + version)[1:] versionCmd := Version() versionCmd.Dir = workingDir versionCmd.Env = append(os.Environ(), toolchainArg) From 6ea99825be6fa14925c5f394e288c565f585d526 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 27 Mar 2024 15:15:40 +0000 Subject: [PATCH 08/12] Go: Add unit test to sanity check `HasGoVersion` --- go/extractor/toolchain/toolchain_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/go/extractor/toolchain/toolchain_test.go b/go/extractor/toolchain/toolchain_test.go index 66d16f97964f..18ca7a6601ba 100644 --- a/go/extractor/toolchain/toolchain_test.go +++ b/go/extractor/toolchain/toolchain_test.go @@ -14,3 +14,9 @@ func TestParseGoVersion(t *testing.T) { } } } + +func TestHasGoVersion(t *testing.T) { + if HasGoVersion("1.21") { + t.Error("Exepected HasGoVersion(\"1.21\" to be false, but got true)") + } +} From 6b1d1d427c227b64cf9418c0dbc8238707727f3b Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 27 Mar 2024 15:16:32 +0000 Subject: [PATCH 09/12] Go: Add integration test for incorrect version format logic --- .../go/go-version-bump/diagnostics.expected | 31 +++++++++++++++++++ .../go/go-version-bump/src/go.mod | 3 ++ .../go/go-version-bump/src/main.go | 3 ++ .../all-platforms/go/go-version-bump/test.py | 18 +++++++++++ 4 files changed, 55 insertions(+) create mode 100644 go/ql/integration-tests/all-platforms/go/go-version-bump/diagnostics.expected create mode 100644 go/ql/integration-tests/all-platforms/go/go-version-bump/src/go.mod create mode 100644 go/ql/integration-tests/all-platforms/go/go-version-bump/src/main.go create mode 100644 go/ql/integration-tests/all-platforms/go/go-version-bump/test.py diff --git a/go/ql/integration-tests/all-platforms/go/go-version-bump/diagnostics.expected b/go/ql/integration-tests/all-platforms/go/go-version-bump/diagnostics.expected new file mode 100644 index 000000000000..2e5d732e53e7 --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/go-version-bump/diagnostics.expected @@ -0,0 +1,31 @@ +{ + "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 + } +} diff --git a/go/ql/integration-tests/all-platforms/go/go-version-bump/src/go.mod b/go/ql/integration-tests/all-platforms/go/go-version-bump/src/go.mod new file mode 100644 index 000000000000..18793f7e295d --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/go-version-bump/src/go.mod @@ -0,0 +1,3 @@ +go 1.21 + +module test diff --git a/go/ql/integration-tests/all-platforms/go/go-version-bump/src/main.go b/go/ql/integration-tests/all-platforms/go/go-version-bump/src/main.go new file mode 100644 index 000000000000..38dd16da61ac --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/go-version-bump/src/main.go @@ -0,0 +1,3 @@ +package main + +func main() {} diff --git a/go/ql/integration-tests/all-platforms/go/go-version-bump/test.py b/go/ql/integration-tests/all-platforms/go/go-version-bump/test.py new file mode 100644 index 000000000000..43c7d1b38e88 --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/go-version-bump/test.py @@ -0,0 +1,18 @@ +import os +import subprocess + +from create_database_utils import * +from diagnostics_test_utils import * + +# Set up a GOPATH relative to this test's root directory; +# we set os.environ instead of using extra_env because we +# need it to be set for the call to "go clean -modcache" later +goPath = os.path.join(os.path.abspath(os.getcwd()), ".go") +os.environ['GOPATH'] = goPath +run_codeql_database_create([], lang="go", source="src") + +check_diagnostics() + +# Clean up the temporary GOPATH to prevent Bazel failures next +# time the tests are run; see https://github.com/golang/go/issues/27161 +subprocess.call(["go", "clean", "-modcache"]) From 45b41bb506c9303e9c30146d2a55c59017720395 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 27 Mar 2024 15:18:24 +0000 Subject: [PATCH 10/12] Go: Mirror stdout/stderr output in `InstallVersion` --- go/extractor/toolchain/toolchain.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/go/extractor/toolchain/toolchain.go b/go/extractor/toolchain/toolchain.go index 2cc6b5b4d543..f0469e0e6787 100644 --- a/go/extractor/toolchain/toolchain.go +++ b/go/extractor/toolchain/toolchain.go @@ -67,6 +67,8 @@ func InstallVersion(workingDir string, version string) bool { versionCmd := Version() versionCmd.Dir = workingDir versionCmd.Env = append(os.Environ(), toolchainArg) + versionCmd.Stdout = os.Stdout + versionCmd.Stderr = os.Stderr log.Printf( "Trying to install Go %s using its canonical representation in `%s`.", From 977ac71b26d103a5d8ea319275298170616ff709 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 28 Mar 2024 11:15:30 +0000 Subject: [PATCH 11/12] Update toolchain_test.go Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com> --- go/extractor/toolchain/toolchain_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/extractor/toolchain/toolchain_test.go b/go/extractor/toolchain/toolchain_test.go index 18ca7a6601ba..05b52af5d525 100644 --- a/go/extractor/toolchain/toolchain_test.go +++ b/go/extractor/toolchain/toolchain_test.go @@ -17,6 +17,6 @@ func TestParseGoVersion(t *testing.T) { func TestHasGoVersion(t *testing.T) { if HasGoVersion("1.21") { - t.Error("Exepected HasGoVersion(\"1.21\" to be false, but got true)") + t.Error("Exepected HasGoVersion(\"1.21\") to be false, but got true") } } From f6c22d466fc05c7e09e94b648e873d1645a9f000 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 28 Mar 2024 13:32:02 +0000 Subject: [PATCH 12/12] Update toolchain_test.go Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com> --- go/extractor/toolchain/toolchain_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/extractor/toolchain/toolchain_test.go b/go/extractor/toolchain/toolchain_test.go index 05b52af5d525..e0f70a283e67 100644 --- a/go/extractor/toolchain/toolchain_test.go +++ b/go/extractor/toolchain/toolchain_test.go @@ -17,6 +17,6 @@ func TestParseGoVersion(t *testing.T) { func TestHasGoVersion(t *testing.T) { if HasGoVersion("1.21") { - t.Error("Exepected HasGoVersion(\"1.21\") to be false, but got true") + t.Error("Expected HasGoVersion(\"1.21\") to be false, but got true") } }