From 9ddd3c11285d20663aaf2a2c9fb450ce955c0223 Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Mon, 19 Jan 2026 08:57:29 -0800 Subject: [PATCH] Remove last remnants of ".go-version" file Before Go 1.21 we relied on third-party and custom tooling to manage which version of Go we were using for development, testing, and release builds. However, modern Go toolchains have built-in support for selecting an appropriate toolchain based on metadata in the go.mod file, and so we had previously removed most uses of the .go-version file and were maintaining it just as a remnant of the old state of things. This replaces our last remaining use of the ".go-version" file with a small tool that extracts the Go version from the go.mod file, and then removes the ".go-version" file completely. The "go" and "toolchain" directives in go.mod are now our single source of truth about which version of Go we're currently using for OpenTofu. (It may be possible to rework the Dockerfile for the consul backend to handle Go version selection in a different way so that we'd no longer need even this "selected-go-version" tool, but that's beyond the scope of this commit which aims to leave it unmodified to make sure the effective testing behavior for that backend is unchanged for now.) Signed-off-by: Martin Atkins --- .go-version | 1 - Makefile | 2 +- contributing/DEVELOPING.md | 2 +- docs/unicode.md | 2 +- go.mod | 1 + .../selected-go-version.go | 68 +++++++++++++++++++ 6 files changed, 72 insertions(+), 4 deletions(-) delete mode 100644 .go-version create mode 100644 tools/selected-go-version/selected-go-version.go diff --git a/.go-version b/.go-version deleted file mode 100644 index 198ec23ccf..0000000000 --- a/.go-version +++ /dev/null @@ -1 +0,0 @@ -1.25.6 diff --git a/Makefile b/Makefile index 35537ed8e5..36ee2117ad 100644 --- a/Makefile +++ b/Makefile @@ -167,7 +167,7 @@ define infoTestConsul endef -GO_VER := `cat $(PWD)/.go-version` +GO_VER := `go tool github.com/opentofu/opentofu/tools/selected-go-version` test-consul: ## Runs tests using in docker container using Consul as the backend. @ $(info $(infoTestConsul)) diff --git a/contributing/DEVELOPING.md b/contributing/DEVELOPING.md index fe8be52bba..cd5359fe21 100644 --- a/contributing/DEVELOPING.md +++ b/contributing/DEVELOPING.md @@ -15,7 +15,7 @@ Eager to get started on coding? Here's the short version: ### Setting up your development environment -You can develop OpenTofu on any platform you like. However, we recommend either a Linux (including WSL on Windows) or a macOS build environment. You will need [Go](https://golang.org/) and [Git](https://git-scm.com/) installed, and we recommend an IDE to help you with code completion and code quality warnings. (We recommend installing the Go version documented in the [.go-version](../.go-version) file.) +You can develop OpenTofu on any platform you like. However, we recommend either a Linux (including WSL on Windows) or a macOS build environment. You will need [Go](https://golang.org/) and [Git](https://git-scm.com/) installed, and we recommend an IDE to help you with code completion and code quality warnings. We recommend installing the latest available version of Go, and then letting the Go toolchain select suitable language and tool versions automatically based on directives in OpenTofu's `go.mod` file. Alternatively, if you use Visual Studio Code or Goland/IntelliJ and have Docker or Podman installed, you can also use a [devcontainer](../.devcontainer.json). In Visual Studio Code, you can install the [Remote Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers), then reopen the project to get a prompt about activating the devcontainer. In Goland/Intellij, open the `.devcontainers.json` file and click the purple cube icon that appears next to the line numbers to activate the dev container. At this point, you can proceed as if you were [building natively](#building-opentofu) on Linux. diff --git a/docs/unicode.md b/docs/unicode.md index ff26b6eeda..1660d4c6c7 100644 --- a/docs/unicode.md +++ b/docs/unicode.md @@ -31,7 +31,7 @@ Unicode version for each Go version. The specific Unicode version for a particular Go version is available in [`unicode.Version`](https://pkg.go.dev/unicode#Version). -We adopt a new version of Go by editing the `.go-version` file in the root +We adopt a new version of Go by editing the `go.mod` file in the root of this repository. Although it's typically possible to build OpenTofu with other versions of Go, that file documents the version we intend to use for official releases and thus the primary version we use for development and diff --git a/go.mod b/go.mod index 0334b913fe..855deb0e78 100644 --- a/go.mod +++ b/go.mod @@ -328,6 +328,7 @@ tool ( github.com/opentofu/opentofu/tools/find-dep-upgrades github.com/opentofu/opentofu/tools/loggraphdiff github.com/opentofu/opentofu/tools/protobuf-compile + github.com/opentofu/opentofu/tools/selected-go-version go.uber.org/mock/mockgen golang.org/x/tools/cmd/stringer google.golang.org/grpc/cmd/protoc-gen-go-grpc diff --git a/tools/selected-go-version/selected-go-version.go b/tools/selected-go-version/selected-go-version.go new file mode 100644 index 0000000000..ee9f5758e0 --- /dev/null +++ b/tools/selected-go-version/selected-go-version.go @@ -0,0 +1,68 @@ +// Copyright (c) The OpenTofu Authors +// SPDX-License-Identifier: MPL-2.0 +// Copyright (c) 2023 HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// selected-go-version determines which version of Go is currently selected +// in the go.mod file. +// +// Note that running this requires that there already be some reasonable +// Go toolchain version (Go 1.21 or newer) installed on the system. The modern +// Go toolchain is able to manage its own versions automatically so it shouldn't +// typically matter which toolchain is used to run this command, and this +// command should only be used in situations where something other than the +// Go toolchain itself needs to make a decision about what to use, such as +// when building container images for testing purposes. +package main + +import ( + "encoding/json" + "fmt" + "os" + "os/exec" + "strings" +) + +func main() { + // Despite the name of this command, this is just printing a JSON + // representation of the go.mod file and not actually editing it. + cmd := exec.Command("go", "mod", "edit", "-json") + raw, err := cmd.Output() + if err != nil { + fmt.Fprintf(os.Stderr, "failed to get Go module metadata: %s\n", err) + os.Exit(1) + } + + var meta GoModJSON + err = json.Unmarshal(raw, &meta) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to parse Go module metadata from JSON: %s\n", err) + os.Exit(1) + } + + // If the Toolchain field is present then we prefer to use that because + // that matches what would be used when running "go" commands directly, + // but we do need to trim of the "go" prefix to make it consistent with + // how the "Go" field is formatted. + // + // Toolchain is described in https://go.dev/doc/toolchain . + if toolchain, ok := strings.CutPrefix(meta.Toolchain, "go"); ok { + // Note that this doesn't do any special handling of "custom toolchains" + // because the OpenTofu project does not currently use those. If we + // do decide to use custom toolchains in future then we'll need to + // decide what that means for this program: should it return the base + // version of the custom toolchain, or the full custom toolchain name? + fmt.Println(toolchain) + return + } + + // Otherwise we use the "Go" field, since that's the only one present + // when the toolchain directive isn't specified, and "go mod tidy" will + // automatically remove the toolchain directive if the go directive matches. + fmt.Println(meta.Go) +} + +type GoModJSON struct { + Go string `json:"Go"` + Toolchain string `json:"Toolchain"` +}