diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 36990a7a9..ed5c2929c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -237,8 +237,8 @@ docs](https://helm.sh/docs/developers/). Use the Makefile targets (`make test`, `make test-unit`, `make test-coverage`) rather than invoking `go test ./...` directly. The Makefile passes the `helmtest` build tag, which is required: it selects -`internal/test/test_mode_on.go` (setting `const testMode = true`), enabling -`test.IsTestMode()` so production code paths in `internal/version` and +`internal/testmode/mode_on.go` (setting `const testMode = true`), enabling +`testmode.IsTestMode()` so production code paths in `internal/version` and `pkg/chart/common` substitute stable values instead of reading build info. Test binaries have no module info, so without this tag those code paths panic during package init. @@ -246,7 +246,7 @@ panic during package init. If you run tests outside the Makefile (IDE test runners, `go test` directly, custom CI), pass `-tags helmtest`. The tag is omitted from release builds so the `testing` package and its dependencies stay out of shipped binaries, and -branches gated on `test.IsTestMode()` are dead-code-eliminated by the compiler. +branches gated on `testmode.IsTestMode()` are dead-code-eliminated by the compiler. ## Pull Requests diff --git a/Makefile b/Makefile index 28d627877..bf78d5511 100644 --- a/Makefile +++ b/Makefile @@ -89,12 +89,14 @@ endif test: test-style test: test-unit -# The `helmtest` build tag activates internal/version/version_helmtest.go, -# which seeds testing-version sentinels so test binaries don't panic reading -# missing module info. Applied to all test invocations. -TESTFLAGS += -tags helmtest - .PHONY: test-unit +# The `helmtest` build tag selects internal/testmode/mode_on.go, flipping +# testmode.IsTestMode() to true so production code paths in internal/version +# and pkg/chart/common substitute stable values instead of reading missing +# module info. Attached to test-unit (not the file-level TESTFLAGS) so the +# tag is guaranteed regardless of any target-specific TESTFLAGS overrides +# in upstream targets (e.g. gen-test-golden). +test-unit: TESTFLAGS += -tags helmtest test-unit: @echo @echo "==> Running unit tests <==" diff --git a/internal/test/test.go b/internal/test/test.go index e3c5b9c68..202e015ab 100644 --- a/internal/test/test.go +++ b/internal/test/test.go @@ -27,15 +27,6 @@ import ( // UpdateGolden writes out the golden files with the latest values, rather than failing the test. var updateGolden = flag.Bool("update", false, "update golden files") -// IsTestMode reports whether the binary was built with -tags helmtest. -// General-purpose signal that the binary was built for tests; consult it -// from production code paths that need to behave differently under test. -// Backed by a compile-time const (see test_mode_on.go / test_mode_off.go) -// so branches gated on it dead-code-eliminate in release builds. -func IsTestMode() bool { - return testMode -} - // TestingT describes a testing object compatible with the critical functions from the testing.T type type TestingT interface { Fatal(...any) diff --git a/internal/test/test_mode_off.go b/internal/testmode/mode_off.go similarity index 97% rename from internal/test/test_mode_off.go rename to internal/testmode/mode_off.go index 62534ed12..ea3e52560 100644 --- a/internal/test/test_mode_off.go +++ b/internal/testmode/mode_off.go @@ -16,6 +16,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -package test +package testmode const testMode = false diff --git a/internal/test/test_mode_on.go b/internal/testmode/mode_on.go similarity index 97% rename from internal/test/test_mode_on.go rename to internal/testmode/mode_on.go index 8a2978699..045d6e2c1 100644 --- a/internal/test/test_mode_on.go +++ b/internal/testmode/mode_on.go @@ -16,6 +16,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -package test +package testmode const testMode = true diff --git a/internal/testmode/testmode.go b/internal/testmode/testmode.go new file mode 100644 index 000000000..a2be02709 --- /dev/null +++ b/internal/testmode/testmode.go @@ -0,0 +1,31 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package testmode exposes a compile-time test-mode signal that production +// code paths may consult when they need to behave differently in a `go +// test` binary. The package has no imports and no init side effects, so it +// can be safely linked from release builds: branches gated on IsTestMode() +// are dead-code-eliminated by the compiler. +package testmode + +// IsTestMode reports whether the binary was built with -tags helmtest. +// General-purpose signal that the binary was built for tests; consult it +// from production code paths that need to behave differently under test. +// Backed by a compile-time const (see mode_on.go / mode_off.go) so branches +// gated on it dead-code-eliminate in release builds. +func IsTestMode() bool { + return testMode +} diff --git a/internal/version/version.go b/internal/version/version.go index 1259e8437..332b2b652 100644 --- a/internal/version/version.go +++ b/internal/version/version.go @@ -24,7 +24,7 @@ import ( "github.com/Masterminds/semver/v3" - "helm.sh/helm/v4/internal/test" + "helm.sh/helm/v4/internal/testmode" ) var ( @@ -88,7 +88,7 @@ func Get() BuildInfo { // Test builds don't include debug info / module info // (And even if they did, we probably want a stable version during tests anyway) // Return a default value for test builds - if test.IsTestMode() { + if testmode.IsTestMode() { return fmt.Sprintf("v%d.%d", KubeVersionMajorTesting, KubeVersionMinorTesting) } @@ -119,7 +119,7 @@ func Get() BuildInfo { } // HACK(bacongobbler): strip out GoVersion during a test run for consistent test output - if test.IsTestMode() { + if testmode.IsTestMode() { v.GoVersion = "" } return v diff --git a/pkg/chart/common/capabilities.go b/pkg/chart/common/capabilities.go index e88f8ad99..acc288b98 100644 --- a/pkg/chart/common/capabilities.go +++ b/pkg/chart/common/capabilities.go @@ -28,7 +28,7 @@ import ( apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" k8sversion "k8s.io/apimachinery/pkg/util/version" - "helm.sh/helm/v4/internal/test" + "helm.sh/helm/v4/internal/testmode" helmversion "helm.sh/helm/v4/internal/version" ) @@ -141,7 +141,7 @@ func makeDefaultCapabilities() (*Capabilities, error) { // Test builds don't include debug info / module info // (And even if they did, we probably want stable capabilities for tests anyway) // Return a default value for test builds - if test.IsTestMode() { + if testmode.IsTestMode() { return newCapabilities(helmversion.KubeVersionMajorTesting, helmversion.KubeVersionMinorTesting) }