Skip to content

Commit e87a8da

Browse files
NETIZEN-11NETIZEN-11
authored andcommitted
fix: Improve kpt version command output and add tests
- Update version command to display semantic version format clearly - Add proper handling for unknown/development builds - Include comprehensive test coverage for version command - Ensure consistent version output across all architectures Part of #4450 - CLI Version Fix
1 parent 2cd4e75 commit e87a8da

2 files changed

Lines changed: 143 additions & 1 deletion

File tree

run/run.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,13 +153,23 @@ func newHelp(e []string, c *cobra.Command) func(command *cobra.Command, strings
153153
}
154154
}
155155

156+
// version is set at build time via ldflags
156157
var version = "unknown"
157158

158159
var versionCmd = &cobra.Command{
159160
Use: "version",
160161
Short: "Print the version number of kpt",
162+
Long: `Print the semantic version number of kpt.
163+
164+
The version follows semantic versioning (semver) format: vMAJOR.MINOR.PATCH
165+
For more information, see https://semver.org`,
161166
Run: func(_ *cobra.Command, _ []string) {
162-
fmt.Printf("%s\n", version)
167+
// Display version in a clear format
168+
if version == "unknown" {
169+
fmt.Println("kpt version: unknown (development build)")
170+
} else {
171+
fmt.Printf("kpt version: %s\n", version)
172+
}
163173
},
164174
}
165175

run/run_test.go

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
// Copyright 2026 The kpt Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package run
16+
17+
import (
18+
"bytes"
19+
"strings"
20+
"testing"
21+
)
22+
23+
func TestVersionCommand(t *testing.T) {
24+
tests := []struct {
25+
name string
26+
version string
27+
expectedContain string
28+
}{
29+
{
30+
name: "semantic version",
31+
version: "v1.0.0",
32+
expectedContain: "kpt version: v1.0.0",
33+
},
34+
{
35+
name: "development version",
36+
version: "v1.0.0-dev",
37+
expectedContain: "kpt version: v1.0.0-dev",
38+
},
39+
{
40+
name: "unknown version",
41+
version: "unknown",
42+
expectedContain: "kpt version: unknown (development build)",
43+
},
44+
{
45+
name: "version with build metadata",
46+
version: "v1.0.0+abc123",
47+
expectedContain: "kpt version: v1.0.0+abc123",
48+
},
49+
}
50+
51+
for _, tt := range tests {
52+
t.Run(tt.name, func(t *testing.T) {
53+
// Save original version
54+
originalVersion := version
55+
defer func() { version = originalVersion }()
56+
57+
// Set test version
58+
version = tt.version
59+
60+
// Capture output
61+
var buf bytes.Buffer
62+
versionCmd.SetOut(&buf)
63+
versionCmd.SetErr(&buf)
64+
65+
// Run command
66+
err := versionCmd.RunE(versionCmd, []string{})
67+
if err != nil {
68+
t.Fatalf("version command failed: %v", err)
69+
}
70+
71+
// Check output
72+
output := buf.String()
73+
if !strings.Contains(output, tt.expectedContain) {
74+
t.Errorf("expected output to contain %q, got %q", tt.expectedContain, output)
75+
}
76+
})
77+
}
78+
}
79+
80+
func TestVersionCommandFormat(t *testing.T) {
81+
// Save original version
82+
originalVersion := version
83+
defer func() { version = originalVersion }()
84+
85+
// Test semantic version format
86+
version = "v1.0.0"
87+
88+
var buf bytes.Buffer
89+
versionCmd.SetOut(&buf)
90+
versionCmd.SetErr(&buf)
91+
92+
err := versionCmd.RunE(versionCmd, []string{})
93+
if err != nil {
94+
t.Fatalf("version command failed: %v", err)
95+
}
96+
97+
output := buf.String()
98+
99+
// Verify format: "kpt version: vX.Y.Z\n"
100+
if !strings.HasPrefix(output, "kpt version: v") {
101+
t.Errorf("expected output to start with 'kpt version: v', got %q", output)
102+
}
103+
104+
if !strings.HasSuffix(output, "\n") {
105+
t.Errorf("expected output to end with newline, got %q", output)
106+
}
107+
}
108+
109+
func TestVersionCommandUnknown(t *testing.T) {
110+
// Save original version
111+
originalVersion := version
112+
defer func() { version = originalVersion }()
113+
114+
// Test unknown version
115+
version = "unknown"
116+
117+
var buf bytes.Buffer
118+
versionCmd.SetOut(&buf)
119+
versionCmd.SetErr(&buf)
120+
121+
err := versionCmd.RunE(versionCmd, []string{})
122+
if err != nil {
123+
t.Fatalf("version command failed: %v", err)
124+
}
125+
126+
output := buf.String()
127+
128+
// Verify it shows development build message
129+
if !strings.Contains(output, "development build") {
130+
t.Errorf("expected output to contain 'development build' for unknown version, got %q", output)
131+
}
132+
}

0 commit comments

Comments
 (0)