Skip to content

Conversation

@vitorfloriano
Copy link
Contributor

What:

This PR changes the version resolution logic so that go build and go install properly populates all the fields in the version subcommand, resulting in a similar output to when the binary is built using make build and goreleaser build:

$ go build
$ ./kubebuilder version
Version: version.Version{KubeBuilderVersion:"v4.10.2", KubernetesVendor:"1.35.0", GitCommit:"854bec426d012fca0ff70ecaee084b3ffd79e84c", BuildDate:"2025-12-27T21:48:51Z", GoOs:"linux", GoArch:"amd64"}

$ go install
$ kubebuilder version
Version: version.Version{KubeBuilderVersion:"v4.10.2", KubernetesVendor:"1.35.0", GitCommit:"854bec426d012fca0ff70ecaee084b3ffd79e84c", BuildDate:"2025-12-27T21:48:51Z", GoOs:"linux", GoArch:"amd64"}

$ make build
go build --trimpath -o bin/kubebuilder
$ ./bin/kubebuilder version
Version: version.Version{KubeBuilderVersion:"v4.10.2", KubernetesVendor:"1.35.0", GitCommit:"854bec426d012fca0ff70ecaee084b3ffd79e84c", BuildDate:"2025-12-27T21:48:51Z", GoOs:"linux", GoArch:"amd64"}

$ goreleaser build --config=./build/.goreleaser.yml
$ ./dist/kubebuilder_linux_amd64_v1/kubebuilder version
Version: version.Version{KubeBuilderVersion:"v4.10.2", KubernetesVendor:"1.35.0", GitCommit:"79a734c0c8d65919fff833e62d71fa760cae5ffe", BuildDate:"2025-12-27T22:11:22Z", GoOs:"linux", GoArch:"amd64"}

Also, the cliVersion field in the PROJECT file is correctly populated:

~/operator$ kubebuilder init
INFO Writing kustomize manifests for you to edit...
INFO Writing scaffold for you to edit...
INFO Get controller runtime
INFO Update dependencies
Next: define a resource with:
$ kubebuilder create api
~/operator$ cat PROJECT
# Code generated by tool. DO NOT EDIT.
# This file is used to track the info used to scaffold your project
# and allow the plugins properly work.
# More info: https://book.kubebuilder.io/reference/project-config.html
cliVersion: v4.10.2
domain: my.domain
layout:
- go.kubebuilder.io/v4
projectName: operator
repo: e.com/example
version: "3"

How:

All the information we need in the version output is already "stamped" in the go binary by default. We now use debug.ReadBuildInfo to extract that info and populate the fields in the version subcommand output, instead of injecting the build info using ldflags during build process.

Also, now that the build info is extracted in the build process, not injected, the Makefile and .goreleaser.yml files do not need to store, update and inject the ldflags.

The KubernetesVendor version is being extracted from the k8s.io/apimachinery module in the dependency list that is also stamped in the binary, making it not necessary to parse that info from the go.mod files in testdata. When we bump the apimachinery version, we will consequentially update the KubernetesVendor version.

And...

We also added dist/ to .gitignore to avoid dirty builds when using goreleaser build.

Closing notes

Now that go build and go install have a similar behavior to make build and goreleaser build, we can encourage the use of those installation methods as well.

Fixes #5302

@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: vitorfloriano
Once this PR has been reviewed and has the lgtm label, please assign varshaprasad96 for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Dec 27, 2025
@k8s-ci-robot k8s-ci-robot added the size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. label Dec 27, 2025
@vitorfloriano vitorfloriano force-pushed the fix-version-resolution branch 3 times, most recently from 626c690 to aeb0918 Compare December 28, 2025 19:11
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR modernizes the version resolution logic by extracting build information from Go's built-in debug.ReadBuildInfo() instead of injecting it via ldflags during the build process. This enables go build and go install to produce binaries with complete version information equivalent to those built with make build and goreleaser build.

Key Changes:

  • Replaced manual version injection via ldflags with automatic extraction from Go's embedded build metadata
  • Refactored version logic into a dedicated internal/version package with comprehensive unit tests
  • Removed build-time K8s version parsing from testdata go.mod files; now extracted from binary's dependency list
  • Added KUBEBUILDER_TEST_VERSION environment variable to ensure consistent version output in test environments

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
internal/version/version.go New package that implements version resolution using debug.ReadBuildInfo() to extract version, commit, build date, and Kubernetes vendor version from embedded build metadata
internal/version/version_test.go Comprehensive unit tests for the version resolution helper functions
cmd/cmd.go Updated to use the new version package instead of the old version variables
cmd/version.go Removed - replaced by internal/version/version.go with simpler, more maintainable implementation
cmd/version_test.go Removed - complex git-based pseudo-version tests no longer needed with new approach
Makefile Simplified build target by removing ldflags and K8s version extraction logic; now uses go build --trimpath
build/.goreleaser.yml Removed ldflags and KUBERNETES_VERSION environment variable configuration
test/common.sh Added KUBEBUILDER_TEST_VERSION environment variable to force consistent "(devel)" version in tests
.gitignore Added **/dist to ignore goreleaser build output directories

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 41 to 64
func New() Version {
v := Version{
KubeBuilderVersion: develVersion,
KubernetesVendor: unknown,
GitCommit: unknown,
BuildDate: unknown,
GoOs: runtime.GOOS,
GoArch: runtime.GOARCH,
}

if info, ok := debug.ReadBuildInfo(); ok {
v.KubeBuilderVersion = resolveMainVersion(info.Main)
v.KubernetesVendor = resolveKubernetesVendor(info.Deps)
v.applyVCSMetadata(info.Settings)
}

if develVersion := os.Getenv("KUBEBUILDER_TEST_VERSION"); develVersion != "" {
v.KubeBuilderVersion = develVersion
v.GitCommit = "test-commit"
v.BuildDate = "2025-01-01T00:00:00Z"
}

return v
}
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing test coverage for the New() function which integrates all the version resolution logic including the environment variable override behavior. Consider adding tests that verify: 1) the overall version resolution when build info is available, 2) the environment variable override behavior with KUBEBUILDER_TEST_VERSION, and 3) fallback behavior when build info is not available. This would ensure the integration between all the helper functions works correctly.

Copilot uses AI. Check for mistakes.
Comment on lines +66 to +70
// GetKubeBuilderVersion returns only the CLI version string.
// Used for the cliVersion field in scaffolded PROJECT files.
func (v Version) GetKubeBuilderVersion() string {
return strings.TrimPrefix(v.KubeBuilderVersion, "v")
}
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing test coverage for the GetKubeBuilderVersion() function. Consider adding tests to verify that it correctly strips the "v" prefix from version strings like "v4.10.4" -> "4.10.4", and handles edge cases like versions without a prefix (e.g., "(devel)" should remain "(devel)").

Copilot uses AI. Check for mistakes.
The go install and go build installation methods now set all the available fields in the version subcommand output.

The version resolution logic has been changed to extract build info from the binary itself, rather than
inject the info using ldflags at build time.

Assisted by: Google/Gemini 3 Pro
@camilamacedo86
Copy link
Member

Hi @vitorfloriano

ASAP controller-runtime new version support k8s 1.35 be release we should bump and release kb as well
So, I am just think if we should change it for the next release or the other one. I need to look with more love ;-)

@vitorfloriano
Copy link
Contributor Author

@camilamacedo86 No problem. This one is very delicate and we need to review it with care.

If we manage to merge this one we can then encourage users to install Kubebuilder using go install (since that's safer for Go-based tools). It would also make it more convenient for users (and maintainers) to test different versions of Kubebuilder.

We could also simplify some scripts that currently use that git clone + make build + mv bin + chmod +x combo.

Anyway, take your time! Thanks!

@k8s-ci-robot
Copy link
Contributor

@vitorfloriano: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
pull-kubebuilder-e2e-k8s-1-35-0 e77b072 link true /test pull-kubebuilder-e2e-k8s-1-35-0

Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@Shrushti72
Copy link

Hey there, I'm a new contributor to open source project, is this issue still pending? can i work with this and solve?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: go build methods results in incomplete version subcommand ouput

4 participants