mirror of
https://gitcode.com/JianFeeeee/homeagent-sdk.git
synced 2026-09-20 08:58:03 +00:00
此前项目里没有任何「我要哪版 SDK」的声明:go.mod 的 require 是个 Go 模块版本, 而工具链实际用的是存储里的 current——谁改过 current 就拿谁的版本编,出错时 表现为莫名其妙的编译错误(本轮就踩过:存储里只有陈旧的 v0.8.0,模板项目 首次构建报 undefined: sdk.InjectOptions)。 - `plg.json` 新增 `sdk` 字段:本插件针对的 SDK 版本。`hmapdev init` 生成时写入 **完整版本号**(如 "1.2.0")。 - `hmapdev build` 按声明的版本在本地 SDK 存储里定位:命中则用它并把 go.mod 的 require/replace 同步到该版本;未命中则报**可执行**的错误(列出已装版本 + `hmapdev sdk install vX.Y.Z`),绝不静默退化成 current。 - **区间写法("1.2")被拒绝**并说明规矩:SDK 版本跟随内核中版本、patch 位恒为 .0, 一条内核线只有一个 SDK 版本(写区间会让人误以为同一条线里还能挑不同 SDK)。 - 产物 `plugin.json` 记录实际选中的版本(`sdk`),便于追溯「这个 .hmap 是哪版编的」。 - 显式 `--sdk-path` / `plg.json sdk_path` 优先(本机改 SDK 联调的路径),此路径下也尽力记录版本。 - 存量项目(plg.json 无 sdk 字段)行为不变,向后兼容。 顺带修一处自相矛盾:解析出 1.2.0 之外的版本时,原先只改 replace 而 require 保持旧版本, 一旦有人删掉 replace 就会静默用回旧 SDK 编译(`go list -m` 报的也是假版本)。 验证:单测 10 例(精确命中/带 v 前缀目录/区间写法被拒并说明规矩/未命中给可执行命令/ 空存储给安装指引/非法值拒绝/杂项目录不干扰)+ 反向验证(把版本比较退化成字典序, 「1.2.x 取最新」用例立刻变红,证明判据能发现缺陷)。 E2E:init → plg.json `"sdk": "1.2.0"`;build → 精确解析、go.mod require/replace 一致、 产物 plugin.json 记录 sdk;声明不存在的版本 → 可执行报错;无 sdk 字段 → 照旧构建。
104 lines
3.3 KiB
Go
104 lines
3.3 KiB
Go
package main
|
||
|
||
import (
|
||
"os"
|
||
"path/filepath"
|
||
"strings"
|
||
"testing"
|
||
)
|
||
|
||
// withSDKStore 把 SDK 存储指到临时目录(sdkStore 读 HOME),并造出给定版本目录。
|
||
func withSDKStore(t *testing.T, versions ...string) {
|
||
t.Helper()
|
||
home := t.TempDir()
|
||
t.Setenv("HOME", home)
|
||
store := filepath.Join(home, ".homeagent", sdkDirName)
|
||
if err := os.MkdirAll(store, 0755); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
for _, v := range versions {
|
||
if err := os.MkdirAll(filepath.Join(store, v), 0755); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
}
|
||
}
|
||
|
||
// 项目声明中版本 → 挑该接口线里最新的补丁;声明完整版本 → 精确命中。
|
||
//
|
||
// 为什么允许中版本是关键判据:patch 位只含工具链/打包修复(接口不变),
|
||
// 让项目声明 "1.2" 而不是死钉 "1.2.0",才能既跟得上工具链修复又不跨接口线。
|
||
func TestResolveSDKForProject(t *testing.T) {
|
||
t.Run("区间写法(1.2)被拒并说明版本纪律", func(t *testing.T) {
|
||
// 判据:SDK 的 patch 位恒为 .0 → 一条内核线只有一个 SDK 版本,
|
||
// 区间写法会让人误以为「同一条线里还能挑版本」,所以直接拒。
|
||
withSDKStore(t, "1.2.0")
|
||
_, _, err := ResolveSDKForProject("1.2")
|
||
if err == nil {
|
||
t.Fatal("1.2 这种区间写法应被拒绝")
|
||
}
|
||
for _, want := range []string{"完整版本号", "patch 位恒为 .0"} {
|
||
if !strings.Contains(err.Error(), want) {
|
||
t.Fatalf("拒绝理由里应说清规矩(缺少 %q): %v", want, err)
|
||
}
|
||
}
|
||
})
|
||
|
||
t.Run("完整版本精确命中", func(t *testing.T) {
|
||
withSDKStore(t, "1.2.0", "1.3.0")
|
||
_, ver, err := ResolveSDKForProject("1.2.0")
|
||
if err != nil || ver != "1.2.0" {
|
||
t.Fatalf("精确命中失败: ver=%s err=%v", ver, err)
|
||
}
|
||
})
|
||
|
||
t.Run("存储目录带 v 前缀也能命中", func(t *testing.T) {
|
||
withSDKStore(t, "v1.2.0")
|
||
dir, ver, err := ResolveSDKForProject("1.2.0")
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
if ver != "1.2.0" || !strings.HasSuffix(dir, "v1.2.0") {
|
||
t.Fatalf("带 v 前缀的目录名未被识别: dir=%s ver=%s", dir, ver)
|
||
}
|
||
})
|
||
|
||
t.Run("未命中要给出可执行命令与已装清单", func(t *testing.T) {
|
||
withSDKStore(t, "1.2.0")
|
||
_, _, err := ResolveSDKForProject("2.0.0")
|
||
if err == nil {
|
||
t.Fatal("应报错")
|
||
}
|
||
msg := err.Error()
|
||
for _, want := range []string{"sdk=2.0.0", "hmapdev sdk install", "hmapdev sdk list", "1.2.0"} {
|
||
if !strings.Contains(msg, want) {
|
||
t.Fatalf("错误信息缺少 %q(要可执行,不能只说 not found):\n%s", want, msg)
|
||
}
|
||
}
|
||
})
|
||
|
||
t.Run("空存储也能给出安装指引", func(t *testing.T) {
|
||
withSDKStore(t)
|
||
_, _, err := ResolveSDKForProject("1.2.0")
|
||
if err == nil || !strings.Contains(err.Error(), "hmapdev sdk install v1.2.0") {
|
||
t.Fatalf("空存储时应提示装哪个版本: %v", err)
|
||
}
|
||
})
|
||
|
||
t.Run("非法声明直接拒绝", func(t *testing.T) {
|
||
withSDKStore(t, "1.2.0")
|
||
for _, bad := range []string{"abc", "1", "1.2", "1.2.3.4", "-1.2.0"} {
|
||
if _, _, err := ResolveSDKForProject(bad); err == nil {
|
||
t.Fatalf("非法版本 %q 应被拒绝(宁可报错也不许当通配符)", bad)
|
||
}
|
||
}
|
||
})
|
||
|
||
t.Run("非版本目录不参与匹配", func(t *testing.T) {
|
||
withSDKStore(t, "1.2.0", "backup-old", ".hidden", "current")
|
||
_, ver, err := ResolveSDKForProject("1.2.0")
|
||
if err != nil || ver != "1.2.0" {
|
||
t.Fatalf("杂项目录不应干扰: ver=%s err=%v", ver, err)
|
||
}
|
||
})
|
||
}
|