From e6f6f7a69c6492e53690147c39cf61381f39e686 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 27 Aug 2026 15:01:24 +0000 Subject: [PATCH 1/6] Initial plan From fa16417d4fa78074ae8f9e02652ec5c3bd0671bc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 27 Aug 2026 15:06:36 +0000 Subject: [PATCH 2/6] Request project Go version above supported range Co-authored-by: jketema <93738568+jketema@users.noreply.github.com> --- go/extractor/autobuilder/build-environment.go | 58 +++++++++++-------- .../autobuilder/build-environment_test.go | 12 ++-- .../build_environment.expected | 4 +- 3 files changed, 45 insertions(+), 29 deletions(-) diff --git a/go/extractor/autobuilder/build-environment.go b/go/extractor/autobuilder/build-environment.go index bd7fc0adabe1..d8eece1adf2c 100644 --- a/go/extractor/autobuilder/build-environment.go +++ b/go/extractor/autobuilder/build-environment.go @@ -83,54 +83,63 @@ func getVersionWhenGoModVersionNotFound(v versionInfo) (msg string, version util func getVersionWhenGoModVersionTooHigh(v versionInfo) (msg string, version util.SemVer) { if v.goEnvVersion == nil { // The version in the `go.mod` file is above the supported range. There is no Go version - // installed. We install the maximum supported version as a best effort. + // installed. We request the version required by the project. msg = "The version of Go found in the `go.mod` file (" + v.goModVersion.String() + ") is above the supported range (" + minGoVersion.String() + "-" + maxGoVersion.String() + - "). No version of Go installed. Requesting the maximum supported version of Go (" + - maxGoVersion.String() + ")." - version = maxGoVersion + "). No version of Go installed. Requesting the version required by the project (" + + v.goModVersion.String() + ")." + version = v.goModVersion diagnostics.EmitGoModVersionTooHighAndNoGoEnv(msg) - } else if aboveSupportedRange(v.goEnvVersion) { + } else if !v.goModVersion.IsNewerThan(v.goEnvVersion) { // The version in the `go.mod` file is above the supported range. The version of Go that - // is installed is above the supported range. We do not install a version of Go. + // is installed is high enough for the project. We do not install a version of Go. msg = "The version of Go found in the `go.mod` file (" + v.goModVersion.String() + ") is above the supported range (" + minGoVersion.String() + "-" + maxGoVersion.String() + "). The version of Go installed in the environment (" + v.goEnvVersion.String() + - ") is above the supported range (" + minGoVersion.String() + "-" + maxGoVersion.String() + - "). Not requesting any version of Go." + ") is high enough for the version required by the project. Not requesting any version of Go." version = nil diagnostics.EmitGoModVersionTooHighAndEnvVersionTooHigh(msg) + } else if aboveSupportedRange(v.goEnvVersion) { + // The installed version is above the supported range, but lower than the version required + // by the project. We request the version required by the project. + msg = "The version of Go found in the `go.mod` file (" + v.goModVersion.String() + + ") is above the supported range (" + minGoVersion.String() + "-" + maxGoVersion.String() + + "). The version of Go installed in the environment (" + v.goEnvVersion.String() + + ") is lower than the version required by the project. Requesting the version required by the project (" + + v.goModVersion.String() + ")." + version = v.goModVersion + diagnostics.EmitGoModVersionTooHighAndEnvVersionTooHigh(msg) } else if belowSupportedRange(v.goEnvVersion) { // The version in the `go.mod` file is above the supported range. The version of Go that - // is installed is below the supported range. We install the maximum supported version as - // a best effort. + // is installed is below the supported range. We request the version required by the project. msg = "The version of Go found in the `go.mod` file (" + v.goModVersion.String() + ") is above the supported range (" + minGoVersion.String() + "-" + maxGoVersion.String() + "). The version of Go installed in the environment (" + v.goEnvVersion.String() + ") is below the supported range (" + minGoVersion.String() + "-" + maxGoVersion.String() + - "). Requesting the maximum supported version of Go (" + maxGoVersion.String() + ")." - version = maxGoVersion + "). Requesting the version required by the project (" + v.goModVersion.String() + ")." + version = v.goModVersion diagnostics.EmitGoModVersionTooHighAndEnvVersionTooLow(msg) } else if maxGoVersion.IsNewerThan(v.goEnvVersion) { // The version in the `go.mod` file is above the supported range. The version of Go that - // is installed is supported and below the maximum supported version. We install the - // maximum supported version as a best effort. + // is installed is supported and below the maximum supported version. We request the version + // required by the project. msg = "The version of Go found in the `go.mod` file (" + v.goModVersion.String() + ") is above the supported range (" + minGoVersion.String() + "-" + maxGoVersion.String() + "). The version of Go installed in the environment (" + v.goEnvVersion.String() + ") is below the maximum supported version (" + maxGoVersion.String() + - "). Requesting the maximum supported version of Go (" + maxGoVersion.String() + ")." - version = maxGoVersion + "). Requesting the version required by the project (" + v.goModVersion.String() + ")." + version = v.goModVersion diagnostics.EmitGoModVersionTooHighAndEnvVersionBelowMax(msg) } else { // The version in the `go.mod` file is above the supported range. The version of Go that - // is installed is the maximum supported version. We do not install a version of Go. + // is installed is the maximum supported version. We request the version required by the + // project. msg = "The version of Go found in the `go.mod` file (" + v.goModVersion.String() + ") is above the supported range (" + minGoVersion.String() + "-" + maxGoVersion.String() + "). The version of Go installed in the environment (" + v.goEnvVersion.String() + ") is the maximum supported version (" + maxGoVersion.String() + - "). Not requesting any version of Go." - version = nil + "). Requesting the version required by the project (" + v.goModVersion.String() + ")." + version = v.goModVersion diagnostics.EmitGoModVersionTooHighAndEnvVersionMax(msg) } @@ -218,16 +227,17 @@ func getVersionWhenGoModVersionSupported(v versionInfo) (msg string, version uti // 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. -// We never return a version of Go that is outside of the supported range. +// If the version required by the project is above the supported range, we return that version when +// it is newer than the installed version. // // +-----------------------+-----------------------+-----------------------+-----------------------------------------------------+------------------------------------------------+ // | Found in go.mod > | *None* | *Below min supported* | *In supported range* | *Above max supported | // | Installed \/ | | | | | // |-----------------------|-----------------------|-----------------------|-----------------------------------------------------|------------------------------------------------| -// | *None* | Install max supported | Install min supported | Install version from go.mod | Install max supported | -// | *Below min supported* | Install max supported | Install min supported | Install version from go.mod | Install max supported | -// | *In supported range* | No action | No action | Install version from go.mod if newer than installed | Install max supported if newer than installed | -// | *Above max supported* | Install max supported | Install min supported | Install version from go.mod | No action | +// | *None* | Install max supported | Install min supported | Install version from go.mod | Install version from go.mod | +// | *Below min supported* | Install max supported | Install min supported | Install version from go.mod | Install version from go.mod | +// | *In supported range* | No action | No action | Install version from go.mod if newer than installed | Install version from go.mod | +// | *Above max supported* | Install max supported | Install min supported | Install version from go.mod | Install version from go.mod if newer than installed | // +-----------------------+-----------------------+-----------------------+-----------------------------------------------------+------------------------------------------------+ func getVersionToInstall(v versionInfo) (msg string, version util.SemVer) { if v.goModVersion == nil { diff --git a/go/extractor/autobuilder/build-environment_test.go b/go/extractor/autobuilder/build-environment_test.go index 382e3aa2914a..1b300aeb94eb 100644 --- a/go/extractor/autobuilder/build-environment_test.go +++ b/go/extractor/autobuilder/build-environment_test.go @@ -20,11 +20,15 @@ func TestGetVersionToInstall(t *testing.T) { {"", "1.20.3"}: "", // getVersionWhenGoModVersionTooHigh() - {"9999.0", ""}: maxGoVersion.String(), + {"1.28", ""}: "1.28", + {"1.28", "1.1"}: "1.28", + {"1.28", "1.20"}: "1.28", + {"1.28", maxGoVersion.String()}: "1.28", + {"1.29", "1.28"}: "1.29", + {"1.28", "1.28"}: "", + {"1.28", "1.29"}: "", {"9999.0", "9999.0.1"}: "", - {"9999.0", "1.1"}: maxGoVersion.String(), - {"9999.0", minGoVersion.String()}: maxGoVersion.String(), - {"9999.0", maxGoVersion.String()}: "", + {"9999.0", minGoVersion.String()}: "9999.0", // getVersionWhenGoModVersionTooLow() {"0.0", ""}: minGoVersion.String(), diff --git a/go/ql/integration-tests/diagnostics/newer-go-version-needed/build_environment.expected b/go/ql/integration-tests/diagnostics/newer-go-version-needed/build_environment.expected index 0b225ce00857..294a2a379277 100644 --- a/go/ql/integration-tests/diagnostics/newer-go-version-needed/build_environment.expected +++ b/go/ql/integration-tests/diagnostics/newer-go-version-needed/build_environment.expected @@ -1,5 +1,7 @@ { "configuration" : { - "go" : { } + "go" : { + "version" : "1.999.0" + } } } From 0ba61a1f9204538649405748d1aeffa9819edfad Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 27 Aug 2026 15:10:44 +0000 Subject: [PATCH 3/6] Apply remaining changes Co-authored-by: jketema <93738568+jketema@users.noreply.github.com> --- .../semmle/go/dependencies/sweb/go.mod | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/go/ql/test/library-tests/semmle/go/dependencies/sweb/go.mod b/go/ql/test/library-tests/semmle/go/dependencies/sweb/go.mod index 096134411f9b..876fde8baa2b 100644 --- a/go/ql/test/library-tests/semmle/go/dependencies/sweb/go.mod +++ b/go/ql/test/library-tests/semmle/go/dependencies/sweb/go.mod @@ -35,29 +35,3 @@ replace google.golang.org/appengine => github.com/golang/appengine v1.6.1 replace golang.org/x/mobile => github.com/golang/mobile v0.0.0-20190607214518-6fa95d984e88 replace golang.org/x/image => github.com/golang/image v0.0.0-20190622003408-7e034cad6442 - -require ( - github.com/Joker/jade v1.0.0 // indirect - github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398 // indirect - github.com/aymerick/raymond v2.0.2+incompatible // indirect - github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 // indirect - github.com/fatih/structs v1.1.0 // indirect - github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4 // indirect - github.com/iris-contrib/blackfriday v2.0.0+incompatible // indirect - github.com/iris-contrib/formBinder v0.0.0-20190104093907-fbd5963f41e1 // indirect - github.com/iris-contrib/go.uuid v2.0.0+incompatible // indirect - github.com/json-iterator/go v1.1.6 // indirect - github.com/kataras/golog v0.0.0-20190624001437-99c81de45f40 // indirect - github.com/kataras/iris v11.1.1+incompatible - github.com/kataras/pio v0.0.0-20190103105442-ea782b38602d // indirect - github.com/klauspost/compress v1.7.2 // indirect - github.com/klauspost/cpuid v1.2.1 // indirect - github.com/microcosm-cc/bluemonday v1.0.2 // indirect - github.com/mitchellh/go-homedir v1.1.0 - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.1 // indirect - github.com/ryanuber/columnize v2.1.0+incompatible // indirect - github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect - github.com/spf13/cobra v0.0.5 - github.com/spf13/viper v1.4.0 -) From 226709cbcd6797c931cd8d0c6504218e4e951e4e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 27 Aug 2026 15:30:23 +0000 Subject: [PATCH 4/6] Harden Go resolver version tests Co-authored-by: jketema <93738568+jketema@users.noreply.github.com> --- .../autobuilder/build-environment_test.go | 29 +++++++++++++------ .../semmle/go/dependencies/sweb/go.mod | 26 +++++++++++++++++ 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/go/extractor/autobuilder/build-environment_test.go b/go/extractor/autobuilder/build-environment_test.go index 1b300aeb94eb..eaf4c039adb0 100644 --- a/go/extractor/autobuilder/build-environment_test.go +++ b/go/extractor/autobuilder/build-environment_test.go @@ -1,16 +1,29 @@ package autobuilder import ( + "fmt" "testing" "github.com/github/codeql-go/extractor/util" ) +func addMinorVersions(t *testing.T, version util.SemVer, count int) string { + t.Helper() + + var major, minor int + if _, err := fmt.Sscanf(version.StandardSemVer(), "%d.%d", &major, &minor); err != nil { + t.Fatalf("Unable to parse Go version %q: %s", version, err) + } + return fmt.Sprintf("%d.%d", major, minor+count) +} + func TestGetVersionToInstall(t *testing.T) { type inputVersions struct { modVersion string envVersion string } + versionAboveMax := addMinorVersions(t, maxGoVersion, 1) + versionTwoAboveMax := addMinorVersions(t, maxGoVersion, 2) tests := map[inputVersions]string{ // getVersionWhenGoModVersionNotFound() {"", ""}: maxGoVersion.String(), @@ -20,15 +33,13 @@ func TestGetVersionToInstall(t *testing.T) { {"", "1.20.3"}: "", // getVersionWhenGoModVersionTooHigh() - {"1.28", ""}: "1.28", - {"1.28", "1.1"}: "1.28", - {"1.28", "1.20"}: "1.28", - {"1.28", maxGoVersion.String()}: "1.28", - {"1.29", "1.28"}: "1.29", - {"1.28", "1.28"}: "", - {"1.28", "1.29"}: "", - {"9999.0", "9999.0.1"}: "", - {"9999.0", minGoVersion.String()}: "9999.0", + {versionAboveMax, ""}: versionAboveMax, + {versionAboveMax, "1.1"}: versionAboveMax, + {versionAboveMax, minGoVersion.String()}: versionAboveMax, + {versionAboveMax, maxGoVersion.String()}: versionAboveMax, + {versionTwoAboveMax, versionAboveMax}: versionTwoAboveMax, + {versionAboveMax, versionAboveMax}: "", + {versionAboveMax, versionTwoAboveMax}: "", // getVersionWhenGoModVersionTooLow() {"0.0", ""}: minGoVersion.String(), diff --git a/go/ql/test/library-tests/semmle/go/dependencies/sweb/go.mod b/go/ql/test/library-tests/semmle/go/dependencies/sweb/go.mod index 876fde8baa2b..096134411f9b 100644 --- a/go/ql/test/library-tests/semmle/go/dependencies/sweb/go.mod +++ b/go/ql/test/library-tests/semmle/go/dependencies/sweb/go.mod @@ -35,3 +35,29 @@ replace google.golang.org/appengine => github.com/golang/appengine v1.6.1 replace golang.org/x/mobile => github.com/golang/mobile v0.0.0-20190607214518-6fa95d984e88 replace golang.org/x/image => github.com/golang/image v0.0.0-20190622003408-7e034cad6442 + +require ( + github.com/Joker/jade v1.0.0 // indirect + github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398 // indirect + github.com/aymerick/raymond v2.0.2+incompatible // indirect + github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4 // indirect + github.com/iris-contrib/blackfriday v2.0.0+incompatible // indirect + github.com/iris-contrib/formBinder v0.0.0-20190104093907-fbd5963f41e1 // indirect + github.com/iris-contrib/go.uuid v2.0.0+incompatible // indirect + github.com/json-iterator/go v1.1.6 // indirect + github.com/kataras/golog v0.0.0-20190624001437-99c81de45f40 // indirect + github.com/kataras/iris v11.1.1+incompatible + github.com/kataras/pio v0.0.0-20190103105442-ea782b38602d // indirect + github.com/klauspost/compress v1.7.2 // indirect + github.com/klauspost/cpuid v1.2.1 // indirect + github.com/microcosm-cc/bluemonday v1.0.2 // indirect + github.com/mitchellh/go-homedir v1.1.0 + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/ryanuber/columnize v2.1.0+incompatible // indirect + github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect + github.com/spf13/cobra v0.0.5 + github.com/spf13/viper v1.4.0 +) From 45b5c1eb65f0364ca291263af65b91fb55de30ab Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 27 Aug 2026 15:37:44 +0000 Subject: [PATCH 5/6] Simplify above-range Go tests Co-authored-by: jketema <93738568+jketema@users.noreply.github.com> --- .../autobuilder/build-environment_test.go | 27 +++++-------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/go/extractor/autobuilder/build-environment_test.go b/go/extractor/autobuilder/build-environment_test.go index eaf4c039adb0..eb2ef0465379 100644 --- a/go/extractor/autobuilder/build-environment_test.go +++ b/go/extractor/autobuilder/build-environment_test.go @@ -1,29 +1,16 @@ package autobuilder import ( - "fmt" "testing" "github.com/github/codeql-go/extractor/util" ) -func addMinorVersions(t *testing.T, version util.SemVer, count int) string { - t.Helper() - - var major, minor int - if _, err := fmt.Sscanf(version.StandardSemVer(), "%d.%d", &major, &minor); err != nil { - t.Fatalf("Unable to parse Go version %q: %s", version, err) - } - return fmt.Sprintf("%d.%d", major, minor+count) -} - func TestGetVersionToInstall(t *testing.T) { type inputVersions struct { modVersion string envVersion string } - versionAboveMax := addMinorVersions(t, maxGoVersion, 1) - versionTwoAboveMax := addMinorVersions(t, maxGoVersion, 2) tests := map[inputVersions]string{ // getVersionWhenGoModVersionNotFound() {"", ""}: maxGoVersion.String(), @@ -33,13 +20,13 @@ func TestGetVersionToInstall(t *testing.T) { {"", "1.20.3"}: "", // getVersionWhenGoModVersionTooHigh() - {versionAboveMax, ""}: versionAboveMax, - {versionAboveMax, "1.1"}: versionAboveMax, - {versionAboveMax, minGoVersion.String()}: versionAboveMax, - {versionAboveMax, maxGoVersion.String()}: versionAboveMax, - {versionTwoAboveMax, versionAboveMax}: versionTwoAboveMax, - {versionAboveMax, versionAboveMax}: "", - {versionAboveMax, versionTwoAboveMax}: "", + {"9999.0", ""}: "9999.0", + {"9999.0", "1.1"}: "9999.0", + {"9999.0", minGoVersion.String()}: "9999.0", + {"9999.0", maxGoVersion.String()}: "9999.0", + {"9999.1", "9999.0"}: "9999.1", + {"9999.0", "9999.0"}: "", + {"9999.0", "9999.1"}: "", // getVersionWhenGoModVersionTooLow() {"0.0", ""}: minGoVersion.String(), From 9e29065b06ca05f175f113226b7bbdabd0c26d6f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 27 Aug 2026 16:05:56 +0000 Subject: [PATCH 6/6] Restore Go patch-version test Co-authored-by: jketema <93738568+jketema@users.noreply.github.com> --- go/extractor/autobuilder/build-environment_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/go/extractor/autobuilder/build-environment_test.go b/go/extractor/autobuilder/build-environment_test.go index eb2ef0465379..5cd42994c057 100644 --- a/go/extractor/autobuilder/build-environment_test.go +++ b/go/extractor/autobuilder/build-environment_test.go @@ -26,6 +26,7 @@ func TestGetVersionToInstall(t *testing.T) { {"9999.0", maxGoVersion.String()}: "9999.0", {"9999.1", "9999.0"}: "9999.1", {"9999.0", "9999.0"}: "", + {"9999.0", "9999.0.1"}: "", {"9999.0", "9999.1"}: "", // getVersionWhenGoModVersionTooLow()