feat: sdk install downloads from Release archive instead of git clone

- Replace git clone --branch with HTTP download from GitCode archive URL
- No git dependency needed for SDK installation
- Extracts tar.gz archive in-memory, strips top-level directory
- Fallback for 'latest' still uses git ls-remote (lightweight)
This commit is contained in:
2026-07-20 11:50:55 +08:00
parent 1bdec9507d
commit 95dad649a8

View File

@ -1,7 +1,11 @@
package main package main
import ( import (
"archive/tar"
"compress/gzip"
"fmt" "fmt"
"io"
"net/http"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
@ -33,6 +37,7 @@ func sdkVersionDir(version string) string {
} }
const sdkRepoURL = "https://gitcode.com/JianFeeeee/homeagent-sdk.git" const sdkRepoURL = "https://gitcode.com/JianFeeeee/homeagent-sdk.git"
const sdkDownloadURL = "https://gitcode.com/JianFeeeee/homeagent-sdk/-/archive/%s/homeagent-sdk-%s.tar.gz"
func cmdSDK(args []string) { func cmdSDK(args []string) {
if len(args) < 1 { if len(args) < 1 {
@ -125,7 +130,7 @@ func cmdSDKList() {
} }
} }
// cmdSDKInstall downloads and installs an SDK version. // cmdSDKInstall downloads and installs an SDK version from Release archive.
func cmdSDKInstall(version string) { func cmdSDKInstall(version string) {
store := sdkStore() store := sdkStore()
if err := os.MkdirAll(store, 0755); err != nil { if err := os.MkdirAll(store, 0755); err != nil {
@ -149,24 +154,91 @@ func cmdSDKInstall(version string) {
return return
} }
fmt.Printf("Downloading SDK version %s...\n", version) url := fmt.Sprintf(sdkDownloadURL, version, version)
fmt.Printf("Downloading SDK %s from Release archive...\n", version)
tmpDir, err := os.MkdirTemp("", "homeagent-sdk-*") tmpFile, err := os.CreateTemp("", "homeagent-sdk-*.tar.gz")
if err != nil {
fmt.Printf("error: create temp file: %v\n", err)
os.Exit(1)
}
tmpPath := tmpFile.Name()
defer os.Remove(tmpPath)
resp, err := http.Get(url)
if err != nil {
fmt.Printf("error: download SDK %s: %v\n", version, err)
os.Exit(1)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
fmt.Printf("error: download SDK %s: HTTP %d\n", version, resp.StatusCode)
os.Exit(1)
}
if _, err := io.Copy(tmpFile, resp.Body); err != nil {
fmt.Printf("error: save SDK archive: %v\n", err)
os.Exit(1)
}
tmpFile.Close()
// Extract to temp dir, then rename to dest
tmpDir, err := os.MkdirTemp("", "homeagent-sdk-extract-*")
if err != nil { if err != nil {
fmt.Printf("error: create temp dir: %v\n", err) fmt.Printf("error: create temp dir: %v\n", err)
os.Exit(1) os.Exit(1)
} }
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
cloneArgs := []string{"clone", "--depth", "1", "--branch", version, sdkRepoURL, tmpDir} gzr, err := gzip.NewReader(openFile(tmpPath))
cmd := exec.Command("git", cloneArgs...) if err != nil {
cmd.Stdout = os.Stdout fmt.Printf("error: read archive: %v\n", err)
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
fmt.Printf("error: failed to clone SDK version %s: %v\n", version, err)
fmt.Println("Make sure git is installed and the version tag exists.")
os.Exit(1) os.Exit(1)
} }
defer gzr.Close()
tr := tar.NewReader(gzr)
for {
header, err := tr.Next()
if err == io.EOF {
break
}
if err != nil {
fmt.Printf("error: extract archive: %v\n", err)
os.Exit(1)
}
// Strip top-level directory from archive path
parts := strings.SplitN(header.Name, "/", 2)
if len(parts) < 2 {
continue
}
relPath := parts[1]
if relPath == "" {
continue
}
target := filepath.Join(tmpDir, relPath)
switch header.Typeflag {
case tar.TypeDir:
os.MkdirAll(target, os.FileMode(header.Mode))
case tar.TypeReg:
os.MkdirAll(filepath.Dir(target), 0755)
f, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY, os.FileMode(header.Mode))
if err != nil {
fmt.Printf("error: create file %s: %v\n", target, err)
os.Exit(1)
}
if _, err := io.Copy(f, tr); err != nil {
f.Close()
fmt.Printf("error: write file %s: %v\n", target, err)
os.Exit(1)
}
f.Close()
}
}
gzr.Close()
if err := os.Rename(tmpDir, dest); err != nil { if err := os.Rename(tmpDir, dest); err != nil {
fmt.Printf("error: move SDK to store: %v\n", err) fmt.Printf("error: move SDK to store: %v\n", err)
@ -181,6 +253,14 @@ func cmdSDKInstall(version string) {
} }
} }
func openFile(path string) *os.File {
f, err := os.Open(path)
if err != nil {
panic(err)
}
return f
}
// cmdSDKUse switches the active SDK version. // cmdSDKUse switches the active SDK version.
func cmdSDKUse(version string) { func cmdSDKUse(version string) {
store := sdkStore() store := sdkStore()