Skip to content

Commit b306807

Browse files
authored
Merge pull request github#13040 from owen-mc/go/identify-environment-change-logic
Go: change logic in `go-autobuilder --identify-environment`
2 parents 082e6a1 + 9334cfb commit b306807

File tree

3 files changed

+282
-83
lines changed

3 files changed

+282
-83
lines changed

go/extractor/cli/go-autobuilder/go-autobuilder.go

Lines changed: 167 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -719,82 +719,192 @@ func installDependenciesAndBuild() {
719719
const minGoVersion = "1.11"
720720
const maxGoVersion = "1.20"
721721

722+
// Check if `version` is lower than `minGoVersion`. Note that for this comparison we ignore the
723+
// patch part of the version, so 1.20.1 and 1.20 are considered equal.
724+
func belowSupportedRange(version string) bool {
725+
return semver.Compare(semver.MajorMinor("v"+version), "v"+minGoVersion) < 0
726+
}
727+
728+
// Check if `version` is higher than `maxGoVersion`. Note that for this comparison we ignore the
729+
// patch part of the version, so 1.20.1 and 1.20 are considered equal.
730+
func aboveSupportedRange(version string) bool {
731+
return semver.Compare(semver.MajorMinor("v"+version), "v"+maxGoVersion) > 0
732+
}
733+
722734
// Check if `version` is lower than `minGoVersion` or higher than `maxGoVersion`. Note that for
723735
// this comparison we ignore the patch part of the version, so 1.20.1 and 1.20 are considered
724736
// equal.
725737
func outsideSupportedRange(version string) bool {
726-
short := semver.MajorMinor("v" + version)
727-
return semver.Compare(short, "v"+minGoVersion) < 0 || semver.Compare(short, "v"+maxGoVersion) > 0
738+
return belowSupportedRange(version) || aboveSupportedRange(version)
728739
}
729740

730-
// Check if `v.goModVersion` or `v.goEnvVersion` are outside of the supported range. If so, emit
731-
// a diagnostic and return an empty version to indicate that we should not attempt to install a
732-
// different version of Go.
733-
func checkForUnsupportedVersions(v versionInfo) (msg, version string) {
734-
if v.goModVersionFound && outsideSupportedRange(v.goModVersion) {
735-
msg = "The version of Go found in the `go.mod` file (" + v.goModVersion +
736-
") is outside of the supported range (" + minGoVersion + "-" + maxGoVersion +
737-
"). Writing an environment file not specifying any version of Go."
738-
version = ""
739-
diagnostics.EmitUnsupportedVersionGoMod(msg)
740-
} else if v.goEnvVersionFound && outsideSupportedRange(v.goEnvVersion) {
741-
msg = "The version of Go installed in the environment (" + v.goEnvVersion +
742-
") is outside of the supported range (" + minGoVersion + "-" + maxGoVersion +
743-
"). Writing an environment file not specifying any version of Go."
741+
// Assuming `v.goModVersionFound` is false, emit a diagnostic and return the version to install,
742+
// or the empty string if we should not attempt to install a version of Go.
743+
func getVersionWhenGoModVersionNotFound(v versionInfo) (msg, version string) {
744+
if !v.goEnvVersionFound {
745+
// There is no Go version installed in the environment. We have no indication which version
746+
// was intended to be used to build this project. Go versions are generally backwards
747+
// compatible, so we install the maximum supported version.
748+
msg = "No version of Go installed and no `go.mod` file found. Writing an environment " +
749+
"file specifying the maximum supported version of Go (" + maxGoVersion + ")."
750+
version = maxGoVersion
751+
diagnostics.EmitNoGoModAndNoGoEnv(msg)
752+
} else if outsideSupportedRange(v.goEnvVersion) {
753+
// The Go version installed in the environment is not supported. We have no indication
754+
// which version was intended to be used to build this project. Go versions are generally
755+
// backwards compatible, so we install the maximum supported version.
756+
msg = "No `go.mod` file found. The version of Go installed in the environment (" +
757+
v.goEnvVersion + ") is outside of the supported range (" + minGoVersion + "-" +
758+
maxGoVersion + "). Requesting the maximum supported version of Go (" + maxGoVersion +
759+
")."
760+
version = maxGoVersion
761+
diagnostics.EmitNoGoModAndGoEnvUnsupported(msg)
762+
} else {
763+
// The version of Go that is installed is supported. We have no indication which version
764+
// was intended to be used to build this project. We assume that the installed version is
765+
// suitable and do not install a version of Go.
766+
msg = "No `go.mod` file found. Version " + v.goEnvVersion + " installed in the " +
767+
"environment is supported. Not requesting any version of Go."
744768
version = ""
745-
diagnostics.EmitUnsupportedVersionEnvironment(msg)
769+
diagnostics.EmitNoGoModAndGoEnvSupported(msg)
746770
}
747771

748772
return msg, version
749773
}
750774

751-
// Check if either `v.goEnvVersionFound` or `v.goModVersionFound` are false. If so, emit
752-
// a diagnostic and return the version to install, or the empty string if we should not attempt to
753-
// install a version of Go. We assume that `checkForUnsupportedVersions` has already been
754-
// called, so any versions that are found are within the supported range.
755-
func checkForVersionsNotFound(v versionInfo) (msg, version string) {
756-
if !v.goEnvVersionFound && !v.goModVersionFound {
757-
msg = "No version of Go installed and no `go.mod` file found. Writing an environment " +
758-
"file specifying the maximum supported version of Go (" + maxGoVersion + ")."
775+
// Assuming `v.goModVersion` is above the supported range, emit a diagnostic and return the
776+
// version to install, or the empty string if we should not attempt to install a version of Go.
777+
func getVersionWhenGoModVersionTooHigh(v versionInfo) (msg, version string) {
778+
if !v.goEnvVersionFound {
779+
// The version in the `go.mod` file is above the supported range. There is no Go version
780+
// installed. We install the maximum supported version as a best effort.
781+
msg = "The version of Go found in the `go.mod` file (" + v.goModVersion +
782+
") is above the supported range (" + minGoVersion + "-" + maxGoVersion +
783+
"). No version of Go installed. Requesting the maximum supported version of Go (" +
784+
maxGoVersion + ")."
759785
version = maxGoVersion
760-
diagnostics.EmitNoGoModAndNoGoEnv(msg)
786+
diagnostics.EmitGoModVersionTooHighAndNoGoEnv(msg)
787+
} else if aboveSupportedRange(v.goEnvVersion) {
788+
// The version in the `go.mod` file is above the supported range. The version of Go that
789+
// is installed is above the supported range. We do not install a version of Go.
790+
msg = "The version of Go found in the `go.mod` file (" + v.goModVersion +
791+
") is above the supported range (" + minGoVersion + "-" + maxGoVersion +
792+
"). The version of Go installed in the environment (" + v.goEnvVersion +
793+
") is above the supported range (" + minGoVersion + "-" + maxGoVersion +
794+
"). Not requesting any version of Go."
795+
version = ""
796+
diagnostics.EmitGoModVersionTooHighAndEnvVersionTooHigh(msg)
797+
} else if belowSupportedRange(v.goEnvVersion) {
798+
// The version in the `go.mod` file is above the supported range. The version of Go that
799+
// is installed is below the supported range. We install the maximum supported version as
800+
// a best effort.
801+
msg = "The version of Go found in the `go.mod` file (" + v.goModVersion +
802+
") is above the supported range (" + minGoVersion + "-" + maxGoVersion +
803+
"). The version of Go installed in the environment (" + v.goEnvVersion +
804+
") is below the supported range (" + minGoVersion + "-" + maxGoVersion +
805+
"). Requesting the maximum supported version of Go (" + maxGoVersion + ")."
806+
version = maxGoVersion
807+
diagnostics.EmitGoModVersionTooHighAndEnvVersionTooLow(msg)
808+
} else if semver.Compare("v"+maxGoVersion, "v"+v.goEnvVersion) > 0 {
809+
// The version in the `go.mod` file is above the supported range. The version of Go that
810+
// is installed is supported and below the maximum supported version. We install the
811+
// maximum supported version as a best effort.
812+
msg = "The version of Go found in the `go.mod` file (" + v.goModVersion +
813+
") is above the supported range (" + minGoVersion + "-" + maxGoVersion +
814+
"). The version of Go installed in the environment (" + v.goEnvVersion +
815+
") is below the maximum supported version (" + maxGoVersion +
816+
"). Requesting the maximum supported version of Go (" + maxGoVersion + ")."
817+
version = maxGoVersion
818+
diagnostics.EmitGoModVersionTooHighAndEnvVersionBelowMax(msg)
819+
} else {
820+
// The version in the `go.mod` file is above the supported range. The version of Go that
821+
// is installed is the maximum supported version. We do not install a version of Go.
822+
msg = "The version of Go found in the `go.mod` file (" + v.goModVersion +
823+
") is above the supported range (" + minGoVersion + "-" + maxGoVersion +
824+
"). The version of Go installed in the environment (" + v.goEnvVersion +
825+
") is the maximum supported version (" + maxGoVersion +
826+
"). Not requesting any version of Go."
827+
version = ""
828+
diagnostics.EmitGoModVersionTooHighAndEnvVersionMax(msg)
761829
}
762830

763-
if !v.goEnvVersionFound && v.goModVersionFound {
764-
msg = "No version of Go installed. Writing an environment file specifying the version " +
765-
"of Go found in the `go.mod` file (" + v.goModVersion + ")."
766-
version = v.goModVersion
767-
diagnostics.EmitNoGoEnv(msg)
768-
}
831+
return msg, version
832+
}
769833

770-
if v.goEnvVersionFound && !v.goModVersionFound {
771-
msg = "No `go.mod` file found. Version " + v.goEnvVersion + " installed in the " +
772-
"environment. Writing an environment file not specifying any version of Go."
834+
// Assuming `v.goModVersion` is below the supported range, emit a diagnostic and return the
835+
// version to install, or the empty string if we should not attempt to install a version of Go.
836+
func getVersionWhenGoModVersionTooLow(v versionInfo) (msg, version string) {
837+
if !v.goEnvVersionFound {
838+
// There is no Go version installed. The version in the `go.mod` file is below the
839+
// supported range. Go versions are generally backwards compatible, so we install the
840+
// minimum supported version.
841+
msg = "The version of Go found in the `go.mod` file (" + v.goModVersion +
842+
") is below the supported range (" + minGoVersion + "-" + maxGoVersion +
843+
"). No version of Go installed. Requesting the minimum supported version of Go (" +
844+
minGoVersion + ")."
845+
version = minGoVersion
846+
diagnostics.EmitGoModVersionTooLowAndNoGoEnv(msg)
847+
} else if outsideSupportedRange(v.goEnvVersion) {
848+
// The version of Go that is installed is outside of the supported range. The version
849+
// in the `go.mod` file is below the supported range. Go versions are generally
850+
// backwards compatible, so we install the minimum supported version.
851+
msg = "The version of Go found in the `go.mod` file (" + v.goModVersion +
852+
") is below the supported range (" + minGoVersion + "-" + maxGoVersion +
853+
"). The version of Go installed in the environment (" + v.goEnvVersion +
854+
") is outside of the supported range (" + minGoVersion + "-" + maxGoVersion + "). " +
855+
"Requesting the minimum supported version of Go (" + minGoVersion + ")."
856+
version = minGoVersion
857+
diagnostics.EmitGoModVersionTooLowAndEnvVersionUnsupported(msg)
858+
} else {
859+
// The version of Go that is installed is supported. The version in the `go.mod` file is
860+
// below the supported range. We do not install a version of Go.
861+
msg = "The version of Go installed in the environment (" + v.goEnvVersion +
862+
") is supported and is high enough for the version found in the `go.mod` file (" +
863+
v.goModVersion + "). Not requesting any version of Go."
773864
version = ""
774-
diagnostics.EmitNoGoMod(msg)
865+
diagnostics.EmitGoModVersionTooLowAndEnvVersionSupported(msg)
775866
}
776867

777868
return msg, version
778869
}
779870

780-
// Compare `v.goModVersion` and `v.goEnvVersion`. emit a diagnostic and return the version to
781-
// install, or the empty string if we should not attempt to install a version of Go. We assume that
782-
// `checkForUnsupportedVersions` and `checkForVersionsNotFound` have already been called, so both
783-
// versions are found and are within the supported range.
784-
func compareVersions(v versionInfo) (msg, version string) {
785-
if semver.Compare("v"+v.goModVersion, "v"+v.goEnvVersion) > 0 {
871+
// Assuming `v.goModVersion` is in the supported range, emit a diagnostic and return the version
872+
// to install, or the empty string if we should not attempt to install a version of Go.
873+
func getVersionWhenGoModVersionSupported(v versionInfo) (msg, version string) {
874+
if !v.goEnvVersionFound {
875+
// There is no Go version installed. The version in the `go.mod` file is supported.
876+
// We install the version from the `go.mod` file.
877+
msg = "No version of Go installed. Requesting the version of Go found in the `go.mod` " +
878+
"file (" + v.goModVersion + ")."
879+
version = v.goModVersion
880+
diagnostics.EmitGoModVersionSupportedAndNoGoEnv(msg)
881+
} else if outsideSupportedRange(v.goEnvVersion) {
882+
// The version of Go that is installed is outside of the supported range. The version in
883+
// the `go.mod` file is supported. We install the version from the `go.mod` file.
884+
msg = "The version of Go installed in the environment (" + v.goEnvVersion +
885+
") is outside of the supported range (" + minGoVersion + "-" + maxGoVersion + "). " +
886+
"Requesting the version of Go from the `go.mod` file (" +
887+
v.goModVersion + ")."
888+
version = v.goModVersion
889+
diagnostics.EmitGoModVersionSupportedAndGoEnvUnsupported(msg)
890+
} else if semver.Compare("v"+v.goModVersion, "v"+v.goEnvVersion) > 0 {
891+
// The version of Go that is installed is supported. The version in the `go.mod` file is
892+
// supported and is higher than the version that is installed. We install the version from
893+
// the `go.mod` file.
786894
msg = "The version of Go installed in the environment (" + v.goEnvVersion +
787895
") is lower than the version found in the `go.mod` file (" + v.goModVersion +
788-
"). Writing an environment file specifying the version of Go from the `go.mod` " +
789-
"file (" + v.goModVersion + ")."
896+
"). Requesting the version of Go from the `go.mod` file (" + v.goModVersion + ")."
790897
version = v.goModVersion
791-
diagnostics.EmitVersionGoModHigherVersionEnvironment(msg)
898+
diagnostics.EmitGoModVersionSupportedHigherGoEnv(msg)
792899
} else {
900+
// The version of Go that is installed is supported. The version in the `go.mod` file is
901+
// supported and is lower than or equal to the version that is installed. We do not install
902+
// a version of Go.
793903
msg = "The version of Go installed in the environment (" + v.goEnvVersion +
794-
") is high enough for the version found in the `go.mod` file (" + v.goModVersion +
795-
"). Writing an environment file not specifying any version of Go."
904+
") is supported and is high enough for the version found in the `go.mod` file (" +
905+
v.goModVersion + "). Not requesting any version of Go."
796906
version = ""
797-
diagnostics.EmitVersionGoModNotHigherVersionEnvironment(msg)
907+
diagnostics.EmitGoModVersionSupportedLowerEqualGoEnv(msg)
798908
}
799909

800910
return msg, version
@@ -803,18 +913,19 @@ func compareVersions(v versionInfo) (msg, version string) {
803913
// Check the versions of Go found in the environment and in the `go.mod` file, and return a
804914
// version to install. If the version is the empty string then no installation is required.
805915
func getVersionToInstall(v versionInfo) (msg, version string) {
806-
msg, version = checkForUnsupportedVersions(v)
807-
if msg != "" {
808-
return msg, version
916+
if !v.goModVersionFound {
917+
return getVersionWhenGoModVersionNotFound(v)
809918
}
810919

811-
msg, version = checkForVersionsNotFound(v)
812-
if msg != "" {
813-
return msg, version
920+
if aboveSupportedRange(v.goModVersion) {
921+
return getVersionWhenGoModVersionTooHigh(v)
814922
}
815923

816-
msg, version = compareVersions(v)
817-
return msg, version
924+
if belowSupportedRange(v.goModVersion) {
925+
return getVersionWhenGoModVersionTooLow(v)
926+
}
927+
928+
return getVersionWhenGoModVersionSupported(v)
818929
}
819930

820931
// Write an environment file to the current directory. If `version` is the empty string then

go/extractor/cli/go-autobuilder/go-autobuilder_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,13 @@ func TestGetVersionToInstall(t *testing.T) {
4949
{"9999.0", true, "1.1", true}: "",
5050
{"9999.0", true, "", false}: "",
5151
// Go installation found with version below minGoVersion
52-
{"1.20", true, "1.2.2", true}: "",
53-
{"1.11", true, "1.2.2", true}: "",
54-
{"", false, "1.2.2", true}: "",
52+
{"1.20", true, "1.2.2", true}: "1.20",
53+
{"1.11", true, "1.2.2", true}: "1.11",
54+
{"", false, "1.2.2", true}: maxGoVersion,
5555
// Go installation found with version above maxGoVersion
56-
{"1.20", true, "9999.0.1", true}: "",
57-
{"1.11", true, "9999.0.1", true}: "",
58-
{"", false, "9999.0.1", true}: "",
56+
{"1.20", true, "9999.0.1", true}: "1.20",
57+
{"1.11", true, "9999.0.1", true}: "1.11",
58+
{"", false, "9999.0.1", true}: maxGoVersion,
5959

6060
// checkForVersionsNotFound()
6161

0 commit comments

Comments
 (0)