Skip to content

Commit dc8bc28

Browse files
committed
feat(cli): 'version' subcommand shows installed rune-mcp/runed
1 parent 4fc3608 commit dc8bc28

2 files changed

Lines changed: 84 additions & 0 deletions

File tree

cmd/rune/main_test.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ func TestRunVersion_PrintConstants(t *testing.T) {
1616
manifestURL = "https://example/manifest.json"
1717
defer func() { manifestURL = saved }()
1818

19+
dir := t.TempDir()
20+
t.Setenv("RUNE_HOME", filepath.Join(dir, "rune"))
21+
t.Setenv("RUNED_HOME", filepath.Join(dir, "runed"))
22+
1923
var buf bytes.Buffer
2024
if code := runVersion(&buf); code != 0 {
2125
t.Errorf("exit = %d, want 0", code)
@@ -35,6 +39,10 @@ func TestRunVersion_EmptyManifest(t *testing.T) {
3539
defer func() { manifestURL = saved }()
3640
t.Setenv("RUNE_MANIFEST", "")
3741

42+
dir := t.TempDir()
43+
t.Setenv("RUNE_HOME", filepath.Join(dir, "rune"))
44+
t.Setenv("RUNED_HOME", filepath.Join(dir, "runed"))
45+
3846
var buf bytes.Buffer
3947
_ = runVersion(&buf)
4048
// Match the actual "manifest missing" copy in version.go's empty
@@ -45,6 +53,62 @@ func TestRunVersion_EmptyManifest(t *testing.T) {
4553
}
4654
}
4755

56+
func TestRunVersion_ShowsInstalledVersion(t *testing.T) {
57+
dir := t.TempDir()
58+
t.Setenv("RUNE_HOME", filepath.Join(dir, "rune"))
59+
t.Setenv("RUNED_HOME", filepath.Join(dir, "runed"))
60+
61+
paths, err := bootstrap.Resolve()
62+
if err != nil {
63+
t.Fatalf("Resolve: %v", err)
64+
}
65+
if err := paths.EnsureDirs(); err != nil {
66+
t.Fatalf("EnsureDirs: %v", err)
67+
}
68+
69+
m := &bootstrap.Manifest{Version: 1, RuneMCPVersion: "v0.1.1", RunedVersion: "v0.1.3"}
70+
arts := map[string]bootstrap.InstalledArtifact{
71+
bootstrap.StepRuneMCP: {Path: paths.RuneMCPBinary, SHA256: "aaa"},
72+
bootstrap.StepRuned: {Path: paths.RunedBinary, SHA256: "bbb"},
73+
}
74+
75+
if err := bootstrap.WriteInstalledManifest(paths, "https://example/manifest.json", m, arts); err != nil {
76+
t.Fatalf("WriteInstalledManifest: %v", err)
77+
}
78+
79+
var buf bytes.Buffer
80+
if code := runVersion(&buf); code != 0 {
81+
t.Errorf("exit = %d, want 0", code)
82+
}
83+
84+
out := buf.String()
85+
if !strings.Contains(out, "v0.1.1") {
86+
t.Errorf("missing installed rune-mcp version: %q", out)
87+
}
88+
if !strings.Contains(out, "v0.1.3") {
89+
t.Errorf("missing installed runed version: %q", out)
90+
}
91+
}
92+
93+
func TestRunVersion_NoInstalledManifest(t *testing.T) {
94+
dir := t.TempDir()
95+
t.Setenv("RUNE_HOME", filepath.Join(dir, "rune"))
96+
t.Setenv("RUNED_HOME", filepath.Join(dir, "runed"))
97+
98+
var buf bytes.Buffer
99+
if code := runVersion(&buf); code != 0 {
100+
t.Errorf("exit = %d, want 0", code)
101+
}
102+
103+
out := buf.String()
104+
if !strings.Contains(out, "rune ") {
105+
t.Errorf("CLI version line must be printed: %q", out)
106+
}
107+
if strings.Contains(out, "rune-mcp:") || strings.Contains(out, "runed:") {
108+
t.Errorf("should not print installed versions when installed.json is absent: %q", out)
109+
}
110+
}
111+
48112
func TestRenderVerifyText_HappyPath(t *testing.T) {
49113
r := &bootstrap.InstallChecks{
50114
OK: true,
@@ -196,6 +260,9 @@ func TestRunVersion_CheckManifestEnv(t *testing.T) {
196260
defer func() { manifestURL = saved }()
197261

198262
t.Setenv("RUNE_MANIFEST", "https://example.invalid/m.json")
263+
dir := t.TempDir()
264+
t.Setenv("RUNE_HOME", filepath.Join(dir, "rune"))
265+
t.Setenv("RUNED_HOME", filepath.Join(dir, "runed"))
199266

200267
var buf bytes.Buffer
201268
if code := runVersion(&buf); code != 0 {

cmd/rune/version.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"fmt"
55
"io"
66
"os"
7+
8+
"github.com/CryptoLabInc/rune-cli/internal/bootstrap"
79
)
810

911
func runVersion(w io.Writer) int {
@@ -19,5 +21,20 @@ func runVersion(w io.Writer) int {
1921
fmt.Fprintln(w, "manifest missing: supply --manifest-url or RUNE_MANIFEST")
2022
}
2123

24+
// Show latest installed rune-mcp/runed (skip if not installed yet)
25+
if paths, err := bootstrap.Resolve(); err == nil {
26+
if rec, rerr := bootstrap.ReadInstalledManifest(paths); rerr == nil && rec != nil {
27+
if rec.RuneMCPVersion != "" {
28+
fmt.Fprintf(w, "rune-mcp: %s\n", rec.RuneMCPVersion)
29+
}
30+
if rec.RunedVersion != "" {
31+
fmt.Fprintf(w, "runed: %s\n", rec.RunedVersion)
32+
}
33+
if rec.InstalledAt != "" {
34+
fmt.Fprintf(w, "installed: %s\n", rec.InstalledAt)
35+
}
36+
}
37+
}
38+
2239
return 0
2340
}

0 commit comments

Comments
 (0)