mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-11-06 01:07:35 +00:00
## 1. internal/kernelupgrade:抽包(避免两份实现漂移)
原来 641 行全在 cmd/homed-upgrade 的 main 包里。内核侧的 kernel_update
工具要复用同一套逻辑,而 main 包不可被 import —— 照抄一份的后果是
"CLI 能升级、agent 调用却把机器搞坏"。
导出:ReadBinVersion / CompareVersions / ParseSemver / CmpSemver /
ProbePluginCompat / ExtractPkg / FindFile / DoUpgrade / WaitHealthy 等。
CLI 变薄壳(只留 flag 解析与 fail 输出)。
★ 顺带修一个真实 bug(判据抓到):ParseSemver 原来只挡 len<2,
于是 "1.4" 漏过去、缺失的 patch 被零值填成 1.4.0 —— 会让
「1.4 → 1.4.0」被判成完全相同(进而说"无需升级"),而两者内容未必相同。
现在要求恰好三段。
## 2. scripts/migrate-plugins-to-org.sh:插件迁成独立仓库
为什么迁:插件散在 SDK 仓 example/ 下有三个问题 ——
① 插件版本与 SDK 版本绑死(一次 SDK 发版把所有插件都带上)
② 插件作者不能单独为自己的插件发版
③ plugin_update 需要"仓库地址 → 拉源码 → 编译",而 example/ 是
别人的仓库,不是插件自己的仓库
脚本纪律:
· 默认 --dry-run,不碰 GitHub
· 产物不入库(dist/build/rawfile/node_modules/*.hmap 全排除)——
实测源码 3MB、产物 1.9G,后者进了仓库就再也删不干净
· 幂等:仓库已存在(422)则跳过创建,重跑安全
· 自动给 plg.json 补 repo 字段,使 plugin_update 能定位仓库
· 用 tar 管道而非 rsync:后者在最小化系统里常常没有(本机实测就没有)
执行结果:26 个插件全部迁移(25 Go + 1 Lua),仓库名与插件名同名。
114 lines
4.3 KiB
Go
114 lines
4.3 KiB
Go
package main
|
||
|
||
import (
|
||
"strings"
|
||
"testing"
|
||
|
||
"github.com/JianFeeeee/HologramAgent/internal/kernelupgrade"
|
||
)
|
||
|
||
// ── 版本比较的判据 ────────────────────────────────────────────
|
||
//
|
||
// 这些是 OTA 敢不敢按 -apply 的依据。判错一次就可能把新版换成旧版,
|
||
// 或让"内容其实没变"被当成升级成功。
|
||
|
||
func TestCompareVersions(t *testing.T) {
|
||
cases := []struct {
|
||
name string
|
||
cur *kernelupgrade.BinVersion
|
||
nv *kernelupgrade.BinVersion
|
||
wantSub string // 结论文案必须包含的片段
|
||
}{
|
||
{
|
||
name: "正常升级",
|
||
cur: &kernelupgrade.BinVersion{Version: "1.3.0", Commit: "aaa"},
|
||
nv: &kernelupgrade.BinVersion{Version: "1.4.0", Commit: "bbb"},
|
||
wantSub: "可升级",
|
||
},
|
||
{
|
||
name: "降级必须显式警告",
|
||
cur: &kernelupgrade.BinVersion{Version: "1.4.0", Commit: "aaa"},
|
||
nv: &kernelupgrade.BinVersion{Version: "1.3.0", Commit: "bbb"},
|
||
wantSub: "降级",
|
||
},
|
||
{
|
||
name: "同版本同 commit = 无需升级",
|
||
cur: &kernelupgrade.BinVersion{Version: "1.4.0", Commit: "aaa"},
|
||
nv: &kernelupgrade.BinVersion{Version: "1.4.0", Commit: "aaa"},
|
||
wantSub: "完全相同",
|
||
},
|
||
{
|
||
// ★ 这条最容易被忽略:版本号没变但内容变了(同版本重发)。
|
||
// 不报出来会让用户以为"升级了其实没升"或反之。
|
||
name: "同版本不同 commit 必须点明",
|
||
cur: &kernelupgrade.BinVersion{Version: "1.4.0", Commit: "aaa"},
|
||
nv: &kernelupgrade.BinVersion{Version: "1.4.0", Commit: "bbb"},
|
||
wantSub: "同版本重发",
|
||
},
|
||
{
|
||
// 非标准形态(1.4.0dev):走字符串回退,不能说"降级"
|
||
name: "非标准版本号走字符串比较",
|
||
cur: &kernelupgrade.BinVersion{Version: "1.4.0", Commit: "aaa"},
|
||
nv: &kernelupgrade.BinVersion{Version: "1.4.0dev", Commit: "bbb"},
|
||
wantSub: "commit 不同",
|
||
},
|
||
}
|
||
for _, c := range cases {
|
||
got := kernelupgrade.CompareVersions(c.cur, c.nv)
|
||
if !strings.Contains(got, c.wantSub) {
|
||
t.Errorf("%s: 结论应含 %q,实际 %q", c.name, c.wantSub, got)
|
||
}
|
||
}
|
||
}
|
||
|
||
// 判据:读不到当前版本时**不能**阻断(第一次升级必然撞到)。
|
||
//
|
||
// 这是实测踩到的:线上内核是加 --version 之前的版本,第一次探测必然失败。
|
||
// 若此时直接退出,所有用户第一次升级都要人工介入。
|
||
func TestCompareVersions_UnknownCurrentDoesNotBlock(t *testing.T) {
|
||
got := kernelupgrade.CompareVersions(nil, &kernelupgrade.BinVersion{Version: "1.4.0", Commit: "bbb"})
|
||
if strings.Contains(got, "❌") {
|
||
t.Errorf("当前版本未知不应判失败,实际: %s", got)
|
||
}
|
||
if !strings.Contains(got, "跳过比较") {
|
||
t.Errorf("应说明跳过比较,实际: %s", got)
|
||
}
|
||
}
|
||
|
||
// ── 版本解析 ─────────────────────────────────────────────────
|
||
|
||
func TestParseSemver(t *testing.T) {
|
||
// 只测**可观察行为**(返回 nil 与否),不探私有字段 ——
|
||
// 跨包断言内部字段会把重构锁死,而"解析对不对"最终要由
|
||
// CompareVersions 的行为体现(上面那组用例已覆盖)。
|
||
if kernelupgrade.ParseSemver("1.4.0") == nil {
|
||
t.Error("1.4.0 应能解析")
|
||
}
|
||
// dev 后缀不算正式语义版本(否则 1.4.0dev 会被当成 1.4.0 比大小)
|
||
if v := kernelupgrade.ParseSemver("1.4.0dev"); v != nil {
|
||
t.Errorf("1.4.0dev 应回退字符串比较,实际解析成 %+v", v)
|
||
}
|
||
// 不完整串同样不算
|
||
for _, bad := range []string{"", "1", "1.4", "v1.4.0", "1.4.x"} {
|
||
if v := kernelupgrade.ParseSemver(bad); v != nil {
|
||
t.Errorf("%q 不应被解析成语义版本,实际 %+v", bad, v)
|
||
}
|
||
}
|
||
}
|
||
|
||
// ── waiter 兜底解析 ──────────────────────────────────────────
|
||
|
||
func TestFirstSemverLike(t *testing.T) {
|
||
// waiter 的真实输出形态
|
||
line := "waiter 1.4.0 (commit 98850e1, built 2026-10-17T09:20:25Z)"
|
||
if got := kernelupgrade.FirstSemverLike(line); got != "1.4.0" {
|
||
t.Errorf("应从 waiter 输出取到 1.4.0,实际 %q", got)
|
||
}
|
||
// 不能把日期当版本号
|
||
if got := kernelupgrade.FirstSemverLike("built 2026-10-17"); got != "" {
|
||
t.Errorf("日期不应被识别为版本号,实际 %q", got)
|
||
}
|
||
}
|
||
|
||
|