Skip to content

Commit d6f65d8

Browse files
authored
Add actual version printing for toolhive (#132)
Signed-off-by: Juan Antonio Osorio <ozz@stacklok.com>
1 parent a8b15e1 commit d6f65d8

File tree

6 files changed

+164
-21
lines changed

6 files changed

+164
-21
lines changed

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@ go.work
2929
/coverage/
3030

3131
.roo/
32-
thv
32+
^thv$
3333

34-
kconfig.yaml
34+
kconfig.yaml

.goreleaser.yaml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,9 @@ builds:
1212
- -tags=netgo
1313
ldflags:
1414
- "-s -w"
15-
- "-X main.Version={{ .Env.VERSION }}"
16-
- "-X main.Commit={{ .Env.COMMIT }}"
17-
- "-X main.CommitDate={{ .Env.COMMIT_DATE }}"
18-
- "-X main.TreeState={{ .Env.TREE_STATE }}"
19-
# - "-X github.com/stacklok/toolhive/---/cli.CLIVersion={{ .Env.VERSION }}"
15+
- "-X github.com/stacklok/toolhive/cmd/thv.Version={{ .Version }}"
16+
- "-X github.com/stacklok/toolhive/cmd/thv.Commit={{ .Commit }}"
17+
- "-X github.com/stacklok/toolhive/cmd/thv.BuildDate={{ .Date }}"
2018
goos:
2119
- linux
2220
# - windows

Taskfile.yml

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,28 @@ tasks:
2828

2929
build:
3030
desc: Build the binary
31+
vars:
32+
VERSION:
33+
sh: git describe --tags --always --dirty || echo "dev"
34+
COMMIT:
35+
sh: git rev-parse --short HEAD || echo "unknown"
36+
BUILD_DATE:
37+
sh: date -u +"%Y-%m-%dT%H:%M:%SZ"
3138
cmds:
3239
- mkdir -p bin
33-
- go build -o bin/thv ./cmd/thv
40+
- go build -ldflags "-s -w -X github.com/stacklok/toolhive/cmd/thv.Version={{.VERSION}} -X github.com/stacklok/toolhive/cmd/thv.Commit={{.COMMIT}} -X github.com/stacklok/toolhive/cmd/thv.BuildDate={{.BUILD_DATE}}" -o bin/thv ./cmd/thv
3441

3542
install:
3643
desc: Install the thv binary to GOPATH/bin
44+
vars:
45+
VERSION:
46+
sh: git describe --tags --always --dirty || echo "dev"
47+
COMMIT:
48+
sh: git rev-parse --short HEAD || echo "unknown"
49+
BUILD_DATE:
50+
sh: date -u +"%Y-%m-%dT%H:%M:%SZ"
3751
cmds:
38-
- go install -v ./cmd/thv
52+
- go install -ldflags "-s -w -X github.com/stacklok/toolhive/cmd/thv.Version={{.VERSION}} -X github.com/stacklok/toolhive/cmd/thv.Commit={{.COMMIT}} -X github.com/stacklok/toolhive/cmd/thv.BuildDate={{.BUILD_DATE}}" -v ./cmd/thv
3953

4054
all:
4155
desc: Run linting, tests, and build

cmd/thv/list.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ var (
3232

3333
// Constants for list command
3434
const (
35-
defaultHost = "localhost"
35+
defaultHost = "localhost"
36+
unknownTransport = "unknown"
3637
)
3738

3839
// ContainerOutput represents container information for JSON output
@@ -126,7 +127,7 @@ func printJSONOutput(containers []rt.ContainerInfo) error {
126127
// Get transport type from labels
127128
transport := labels.GetTransportType(c.Labels)
128129
if transport == "" {
129-
transport = "unknown"
130+
transport = unknownTransport
130131
}
131132

132133
// Get tool type from labels
@@ -242,7 +243,7 @@ func printTextOutput(containers []rt.ContainerInfo) {
242243
// Get transport type from labels
243244
transport := labels.GetTransportType(c.Labels)
244245
if transport == "" {
245-
transport = "unknown"
246+
transport = unknownTransport
246247
}
247248

248249
// Get port from labels

cmd/thv/main.go

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,6 @@ container-based isolation for running MCP servers.`,
2626
},
2727
}
2828

29-
var versionCmd = &cobra.Command{
30-
Use: "version",
31-
Short: "Show the version of ToolHive",
32-
Run: func(_ *cobra.Command, _ []string) {
33-
logger.Log.Info("ToolHive v0.1.0")
34-
},
35-
}
36-
3729
func init() {
3830
// Initialize the logger system
3931
logger.Initialize()
@@ -48,7 +40,7 @@ func init() {
4840
rootCmd.AddCommand(rmCmd)
4941
rootCmd.AddCommand(proxyCmd)
5042
rootCmd.AddCommand(restartCmd)
51-
rootCmd.AddCommand(versionCmd)
43+
rootCmd.AddCommand(newVersionCmd())
5244
rootCmd.AddCommand(newLogsCommand())
5345
rootCmd.AddCommand(newSecretCommand())
5446
}

cmd/thv/version.go

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// Package main provides the entry point for the toolhive command-line application.
2+
// This file contains the implementation of the 'version' command.
3+
package main
4+
5+
import (
6+
"fmt"
7+
"runtime"
8+
"runtime/debug"
9+
"strings"
10+
"time"
11+
12+
"github.com/spf13/cobra"
13+
)
14+
15+
const (
16+
unknownStr = "unknown"
17+
)
18+
19+
// Version information set by build using -ldflags
20+
var (
21+
// Version is the current version of ToolHive
22+
Version = "dev"
23+
// Commit is the git commit hash of the build
24+
//nolint:goconst // This is a placeholder for the commit hash
25+
Commit = unknownStr
26+
// BuildDate is the date when the binary was built
27+
// nolint:goconst // This is a placeholder for the build date
28+
BuildDate = unknownStr
29+
)
30+
31+
// versionInfo represents the version information
32+
type versionInfo struct {
33+
Version string `json:"version"`
34+
Commit string `json:"commit"`
35+
BuildDate string `json:"build_date"`
36+
GoVersion string `json:"go_version"`
37+
Platform string `json:"platform"`
38+
}
39+
40+
// newVersionCmd creates a new version command
41+
func newVersionCmd() *cobra.Command {
42+
var jsonOutput bool
43+
44+
cmd := &cobra.Command{
45+
Use: "version",
46+
Short: "Show the version of ToolHive",
47+
Long: `Display detailed version information about ToolHive, including version number, git commit, build date, and Go version.`,
48+
Run: func(_ *cobra.Command, _ []string) {
49+
info := getVersionInfo()
50+
51+
if jsonOutput {
52+
printJSONVersionInfo(info)
53+
} else {
54+
printVersionInfo(info)
55+
}
56+
},
57+
}
58+
59+
cmd.Flags().BoolVar(&jsonOutput, "json", false, "Output version information as JSON")
60+
61+
return cmd
62+
}
63+
64+
// getVersionInfo returns the version information
65+
func getVersionInfo() versionInfo {
66+
// If version is still "dev", try to get it from build info
67+
ver := Version
68+
commit := Commit
69+
buildDate := BuildDate
70+
71+
if ver == "dev" {
72+
if info, ok := debug.ReadBuildInfo(); ok {
73+
// Try to get version from build info
74+
for _, setting := range info.Settings {
75+
switch setting.Key {
76+
case "vcs.revision":
77+
if commit == unknownStr {
78+
commit = setting.Value
79+
}
80+
case "vcs.time":
81+
if buildDate == unknownStr {
82+
buildDate = setting.Value
83+
}
84+
}
85+
}
86+
}
87+
}
88+
89+
// Format the build date if it's a timestamp
90+
if buildDate != unknownStr {
91+
if t, err := time.Parse(time.RFC3339, buildDate); err == nil {
92+
buildDate = t.Format("2006-01-02 15:04:05 MST")
93+
}
94+
}
95+
96+
return versionInfo{
97+
Version: ver,
98+
Commit: commit,
99+
BuildDate: buildDate,
100+
GoVersion: runtime.Version(),
101+
Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH),
102+
}
103+
}
104+
105+
// printVersionInfo prints the version information
106+
func printVersionInfo(info versionInfo) {
107+
fmt.Printf("ToolHive %s", info.Version)
108+
fmt.Printf("Commit: %s", info.Commit)
109+
fmt.Printf("Built: %s", info.BuildDate)
110+
fmt.Printf("Go version: %s", info.GoVersion)
111+
fmt.Printf("Platform: %s", info.Platform)
112+
}
113+
114+
// printJSONVersionInfo prints the version information as JSON
115+
func printJSONVersionInfo(info versionInfo) {
116+
// Simple JSON formatting without importing encoding/json
117+
jsonStr := fmt.Sprintf(`{
118+
"version": "%s",
119+
"commit": "%s",
120+
"build_date": "%s",
121+
"go_version": "%s",
122+
"platform": "%s"
123+
}`,
124+
escapeJSON(info.Version),
125+
escapeJSON(info.Commit),
126+
escapeJSON(info.BuildDate),
127+
escapeJSON(info.GoVersion),
128+
escapeJSON(info.Platform))
129+
130+
fmt.Printf("%s", jsonStr)
131+
}
132+
133+
// escapeJSON escapes special characters in JSON strings
134+
func escapeJSON(s string) string {
135+
s = strings.ReplaceAll(s, `\`, `\\`)
136+
s = strings.ReplaceAll(s, `"`, `\"`)
137+
return s
138+
}

0 commit comments

Comments
 (0)