Skip to content

Commit 17fd632

Browse files
committed
feat(bootstrap): support install subset of artifacts
1 parent 430262f commit 17fd632

1 file changed

Lines changed: 43 additions & 25 deletions

File tree

internal/bootstrap/install.go

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ import (
66
"net"
77
"os"
88
"path/filepath"
9+
"slices"
910
"time"
1011
)
1112

1213
type InstallOptions struct {
1314
ManifestURL string
14-
Force bool // `rune install --force` to force re-download
15+
Force bool // `rune install --force` to force re-download
16+
Target []string // empty = all; StepRuneMCP | StepRuned
1517
Progress ProgressFunc
1618
Log func(format string, args ...any)
1719
}
@@ -66,16 +68,22 @@ func Install(ctx context.Context, opts InstallOptions) (*Result, error) {
6668
Installed: map[string]ArtifactInfo{},
6769
}
6870

71+
// Total step count
72+
total := 3 // all steps
73+
if len(opts.Target) > 0 {
74+
total = 1 + len(opts.Target) // manifest + num artifacts
75+
}
76+
6977
// Fetch manifest
70-
logf("[1/3] manifest: fetching from %s", opts.ManifestURL)
78+
logf("[1/%d] manifest: fetching from %s", total, opts.ManifestURL)
7179
manifest, err := FetchManifest(ctx, opts.ManifestURL)
7280
if err != nil {
7381
r.Failed[StepManifest] = err.Error()
7482
r.Status = "partial"
7583
return r, err
7684
}
7785
r.Completed = append(r.Completed, StepManifest)
78-
logf("[1/3] manifest: ok (rune-mcp %s, runed %s)", manifest.RuneMCPVersion, manifest.RunedVersion)
86+
logf("[1/%d] manifest: ok (rune-mcp %s, runed %s)", total, manifest.RuneMCPVersion, manifest.RunedVersion)
7987

8088
artifacts, err := manifest.ArtifactsForCurrentPlatform()
8189
if err != nil {
@@ -95,19 +103,26 @@ func Install(ctx context.Context, opts InstallOptions) (*Result, error) {
95103
{StepRuneMCP, artifacts.RuneMCP, paths.RuneMCPBinary},
96104
}
97105

106+
// Filter install target
107+
if len(opts.Target) > 0 {
108+
installs = slices.DeleteFunc(installs, func(in install) bool {
109+
return !slices.Contains(opts.Target, in.step)
110+
})
111+
}
112+
98113
for i, in := range installs {
99-
stepNum := i + 2 // starting from [2/3]
114+
stepNum := i + 2 // step 1: manifest
100115
if !opts.Force {
101116
if fileExists(in.dest) {
102-
logf("[%d/3] %s: skipped (already at %s)", stepNum, in.step, in.dest)
117+
logf("[%d/%d] %s: skipped (already at %s)", stepNum, total, in.step, in.dest)
103118
r.Completed = append(r.Completed, in.step)
104119
r.Skipped = append(r.Skipped, in.step)
105120

106121
continue
107122
}
108123
}
109124

110-
logf("[%d/3] %s (%d bytes): downloading...", stepNum, in.step, in.spec.Size)
125+
logf("[%d/%d] %s (%d bytes): downloading...", stepNum, total, in.step, in.spec.Size)
111126
if err := installArtifact(ctx, paths, in.spec, in.dest, opts.Progress); err != nil {
112127
r.Failed[in.step] = err.Error()
113128
r.Status = "partial"
@@ -118,29 +133,32 @@ func Install(ctx context.Context, opts InstallOptions) (*Result, error) {
118133
if info, statErr := os.Stat(in.dest); statErr == nil {
119134
r.Installed[filepath.Base(in.dest)] = ArtifactInfo{Path: in.dest, Size: info.Size()}
120135
}
121-
logf("[%d/3] %s: installed at %s", stepNum, in.step, in.dest)
122-
}
136+
logf("[%d/%d] %s: installed at %s", stepNum, total, in.step, in.dest)
137+
}
138+
139+
// Record install audit is only available with full `rune install` (no not allow partial record)
140+
if len(opts.Target) == 0 {
141+
auditArtifacts := make(map[string]InstalledArtifact, len(installs))
142+
for _, in := range installs {
143+
entry := InstalledArtifact{
144+
URL: in.spec.URL,
145+
SHA256: in.spec.SHA256,
146+
Path: in.dest,
147+
Size: in.spec.Size,
148+
}
123149

124-
// Record install audit
125-
auditArtifacts := make(map[string]InstalledArtifact, len(installs))
126-
for _, in := range installs {
127-
entry := InstalledArtifact{
128-
URL: in.spec.URL,
129-
SHA256: in.spec.SHA256,
130-
Path: in.dest,
131-
Size: in.spec.Size,
132-
}
150+
if info, statErr := os.Stat(in.dest); statErr == nil {
151+
entry.Size = info.Size()
152+
}
133153

134-
if info, statErr := os.Stat(in.dest); statErr == nil {
135-
entry.Size = info.Size()
154+
auditArtifacts[in.step] = entry
136155
}
137156

138-
auditArtifacts[in.step] = entry
139-
}
140-
if err := WriteInstalledManifest(paths, opts.ManifestURL, manifest, auditArtifacts); err != nil {
141-
logf("warning: installed.json write failed: %v", err) // not fatal error
142-
} else {
143-
logf("audit: installed.json updated at %s", paths.InstalledManifest)
157+
if err := WriteInstalledManifest(paths, opts.ManifestURL, manifest, auditArtifacts); err != nil {
158+
logf("warning: installed.json write failed: %v", err) // not fatal error
159+
} else {
160+
logf("audit: installed.json updated at %s", paths.InstalledManifest)
161+
}
144162
}
145163

146164
// Probe socket

0 commit comments

Comments
 (0)