Files
MailUI4Agents/plugins/homeagent-mail-bridge/build.sh
JianFeeeee 4f0a6e6097 fix(homeagent): 构建不许弄脏源码树 —— hmapdev 会重写 plugin.json,构建后还原并出声
实测:`hmapdev build` 会重写受版本管理的 `plugin.json`(只吃掉了文件末尾换行)。
"构建把树弄脏"这件事在 electron 那边刚定过规矩(脏树产物不得自称发布候选),
所以这里同样处理:构建前留快照,构建后若被改写就还原 + 打印一行说明
(不静默还原 —— 下一个人要知道这条工具会动源码)。

验证:`bash build.sh`(HOMEAGENT_SDK_DIR=…/sdk/v1.3.0)产出 build/plugin.bin(9018271 字节),
构建后 `git status plugins/homeagent-mail-bridge/` 只剩我自己改的 build.sh。
2026-09-14 16:41:54 +08:00

113 lines
6.8 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# 构建 homeagent-mail-bridge —— 用**明确指定的** SDK 源码,并记录"这次到底用了哪份代码"。
#
# # 这份脚本被改过一轮因为它的第一版判错了根因pi 2026-09-14 晚逐条反驳)
#
# 第一版的错:把 `go version -m <内核>` 里的
# dep ... homeagent-sdk v0.9.2 / => ./third_party/homeagent-sdk (devel)
# 当成"内核链的是 0.9.x 血脉",然后按候选根目录**第一个命中就算**去解析 SDK 源码,
# 命中的是 `/root/ha-test/third_party/homeagent-sdk`C-ABI 时代的老 checkout无 plugin.bin 支持)。
# 而本机共有 6+ 份同名 checkout内核自己用的是 1.3.0 那份。两个教训:
#
# ① **不要用"第一个存在的路径"当权威来源** —— 猜根目录会命中不相关的 checkout
# "两条血脉"于是成了脚本的产物,而不是事实;
# ② **不要把模块版本字符串当身份** —— `replace => local (devel)` 时那个版本号
# 只是 require 行的文本残留,不代表实际编译的代码。
#
# 所以现在SDK 源码**只认显式指定**`HOMEAGENT_SDK_DIR`)。
# 不猜、不试探、不"第一个命中"。要指定内核的构建目录就显式传进来。
#
# # 不变量是什么
#
# 不是"版本号相等"(那正是第一版想抛弃的东西),而是 **wire 协议 + 一次真实握手**
# 产物要能被内核 `protocol=2` 认下来。这个脚本能做的是"把身份记清楚 + 把明显不对的挡下来"
# 真握手由内核启动时完成(所以部署后要回看一次日志,见末尾提示)。
set -euo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SDK_MODULE="gitcode.com/JianFeeeee/homeagent-sdk"
KERNEL_BIN="${HOMEAGENT_KERNEL_BIN:-/usr/local/bin/homed}"
die() { echo "构建失败:$*" >&2; exit 1; }
# cron/非登录 shell 里 HOME 可能没设Go 会因此拒绝工作(曾经在这里栽过)
export HOME="${HOME:-/root}"
export GOPATH="${GOPATH:-$HOME/go}"
export GOCACHE="${GOCACHE:-${TMPDIR:-/tmp}/go-build-agentmail}"
mkdir -p "$GOCACHE"
# ── 1. SDK 源码:只认显式指定 ───────────────────────────────────────
[[ -n "${HOMEAGENT_SDK_DIR:-}" ]] || die "必须显式指定 SDK 源码树HOMEAGENT_SDK_DIR=/path/to/homeagent-sdk
为什么不让脚本自己猜:本机有 6+ 份同名 checkout有的是 C-ABI 时代的老代码),
第一版按候选根目录'第一个命中就算',命中了 /root/ha-test 那份老 checkout
于是把'内核链老血脉'这个**错误结论**当成了事实写进注释。猜路径 = 制造事实。"
SDK_DIR="$(cd "$HOMEAGENT_SDK_DIR" && pwd)"
[[ -f "$SDK_DIR/go.mod" ]] || die "$SDK_DIR 不是 Go 模块(没有 go.mod"
# 身份用 **realpath + 内容哈希**,不用版本字符串(版本号可能是 -ldflags 注入的默认值,
# 也可能是注释里的示例 —— 后者我在 electron 侧的判据里刚踩过一次)。
SDK_HASH="$(find "$SDK_DIR" -type f -name '*.go' -print0 2>/dev/null | sort -z | xargs -0 cat 2>/dev/null | sha256sum | cut -c1-16)"
SDK_VER="$(sed 's://.*::' "$SDK_DIR/meta/meta.go" 2>/dev/null | grep -m1 -oE 'Version = "[0-9]+\.[0-9]+\.[0-9]+"' | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' || true)"
echo "[build] SDK 源码:$SDK_DIR"
echo "[build] meta.Version已剥注释= ${SDK_VER:-未知} 内容哈希 = ${SDK_HASH:-未知}"
# 内核签名的**提示**(不是判据):按模块名精确联接,不按"输出里第一个 =>"。
# "两张表各缺一半时必须按 id 联接"—— 读 go version -m 的输出同理。
if [[ -x "$KERNEL_BIN" ]]; then
KERNEL_INFO="$(go version -m "$KERNEL_BIN" 2>/dev/null || true)"
KERNEL_SDK_LINE="$(awk -v m="$SDK_MODULE" '$1=="dep" && $2==m {print NR": "$0}' <<<"$KERNEL_INFO" | head -1)"
if [[ -n "$KERNEL_SDK_LINE" ]]; then
KERNEL_SDK_DEP="$(cut -d' ' -f3 <<<"${KERNEL_SDK_LINE#*: }")"
# 只接受**紧跟在 SDK 那一行之后**的 => 行(按位置配对的唯一正确写法)
KERNEL_SDK_REPL="$(awk -v m="$SDK_MODULE" '
$1=="dep" && $2==m {want=NR+1}
want && NR==want && $1=="=>" {print $2; exit}' <<<"$KERNEL_INFO")"
echo "[build] 内核 $KERNEL_BIN 的 dep 行:$KERNEL_SDK_DEP${KERNEL_SDK_REPL:+(本地替换 $KERNEL_SDK_REPL}"
echo "[build] 注意:这条只是**提示**,不是判据 —— replace 到本地目录时这个版本号只是 require 行的残留,"
echo "[build] 而且它指向的相对路径未必是本机这份源码。要对齐请显式传 HOMEAGENT_SDK_DIR。"
fi
fi
# ── 2. 用临时 modfile 替换,不改动受版本管理的 go.mod ───────────────
cd "$HERE"
TMP_MOD="$(mktemp -d)/go.local.mod"
cp go.mod "$TMP_MOD"
go mod edit -modfile="$TMP_MOD" -replace "$SDK_MODULE=$SDK_DIR"
export GOFLAGS="${GOFLAGS:-} -modfile=$TMP_MOD"
# 注意:这个插件**没有** `func main()`(入口由 hmapdev 生成/包装),
# 所以 `go build ./...` 会报 "function main is undeclared" —— 那是正常的,
# 不能用它来数 API 兼容性错误;真正的编译在 hmapdev 那一步。
# 这条工具会**重写 plugin.json/plg.json**(实测:只把文件末尾的换行吃掉了)。
# 构建不该把源码树弄脏 —— 在 electron 那边我们刚为同一形状定过规矩
# (脏树产物不得自称发布候选)。所以:先记哈希,构建后若被改就还原并出声。
MANIFESTS=(plugin.json plg.json)
SNAP_DIR="$(mktemp -d)"
for f in "${MANIFESTS[@]}"; do [[ -f "$f" ]] && cp "$f" "$SNAP_DIR/$f"; done
hmapdev build || die "hmapdev build 失败(编译错误见上;它才是真正的编译入口)"
for f in "${MANIFESTS[@]}"; do
[[ -f "$SNAP_DIR/$f" ]] || continue
if ! cmp -s "$SNAP_DIR/$f" "$f"; then
cp "$SNAP_DIR/$f" "$f"
echo "[build] 注意hmapdev 改写了 $f(已还原)—— 构建工具不该动受版本管理的源码;"
echo "[build] 否则每次构建都把树弄脏,而'脏树'在别的端已经是'不是发布候选'的判据了。"
fi
done
rm -rf "$SNAP_DIR"
# ── 3. 产物自报身份 ─────────────────────────────────────────────────
BIN="build/plugin.bin"
[[ -f "$BIN" ]] || die "没找到产物 $BIN"
echo "[build] 产物:$BIN$(stat -c%s "$BIN") 字节)"
echo "[build] 本次身份SDK=$SDK_DIR hash=$SDK_HASH version=${SDK_VER:-未知}"
cat > build/BUILD_INFO.txt <<EOF
sdkDir=$SDK_DIR
sdkHash=$SDK_HASH
sdkMetaVersion=${SDK_VER:-unknown}
builtAt=$(date -Iseconds)
EOF
echo "[build] 已写 build/BUILD_INFO.txt —— 部署后请回看内核日志确认握手:"
echo " grep -a 'mail-bridge' /home/newqqagent/log/homed_*.log | tail -5"
echo " (判据不是版本号相等,而是 protocol=2 建链成功、且没有崩溃重启循环)"