refactor(deploy): package-linux.sh/spec 产物与安装布局改名,并补结构判据

package-linux.sh(只动包名/安装路径,不动 SDK module 路径):
  - 产物名 hologramagent-{variant}_*.deb / hologramagent-*.rpm /
    hologramagent_*.tar.gz
  - 安装路径 /usr/lib/hologram/{sdk,models,onnxruntime,setup.sh}、
    /usr/share/doc/hologramagent/(DEP-5 惯例按包名)
  - GUI:build/hologram-gui-linux-<arch>、/usr/bin/hologram-gui、
    /usr/lib/hologram-gui、hologram-gui.desktop
  - 单元从 deploy/hologramagent.service 取,装成 hologramagent.service
  - staging /var/lib/hologram

**故意没动** prepare_gomod 里那段 replace 的匹配串
(github.com/JianFeeeee/homeagentsdk):那是批 3 的 module 改名,
匹配串先改而 module 未改,sed 会整段不匹配且**不报错**,继续用旧路径编
—— 正是清单第四节第 2 条点名的静默失效。等批 3 一起改才安全。

spec:homeagent.spec → hologramagent.spec(git mv),包名/unit/datadir/
changelog 同步;%{_varlibdir} = /var/lib/hologram。

packaging_test.go:第 171 行的 toolchain 关键字跟着改;**第 99-106 行那两处
module 路径断言一行未动**(批 1 的地盘)。另新增四条结构判据,把本批
「日志全绿但包内容还是旧路径」这一类钉住:
  · TestPackagingUsesRenamedInstallPaths   —— 脚本里不许残留旧路径,且新值必须真出现
  · TestDebMaintainerScriptsUseRenamedService —— postinst/prerm 的 SERVICE_NAME
  · TestDebControlFilesUseRenamedPackage   —— 四个 control 的 Package 与 SDK 路径
  · TestSystemdUnitUsesRenamedPaths        —— 单元指令行(注释除外)+ 旧单元已删

判据形态仍沿用本文件的原则:断言的是「某个必需处置存在」,不是接线/顺序。
端到端(真装再看内核)由发版流程做。
This commit is contained in:
JianFeeeee
2026-10-21 13:21:06 +08:00
parent 503579ae18
commit 79688386b1
3 changed files with 218 additions and 77 deletions

View File

@ -1,27 +1,27 @@
# HomeAgent RPM Spec # HologramAgent RPM Spec
# Build: rpmbuild -ba homeagent.spec # Build: rpmbuild -ba hologramagent.spec
# #
# Define variant at build time: # Define variant at build time:
# rpmbuild -ba --define "variant full" homeagent.spec # rpmbuild -ba --define "variant full" hologramagent.spec
# rpmbuild -ba --define "variant server" homeagent.spec # rpmbuild -ba --define "variant server" hologramagent.spec
# rpmbuild -ba --define "variant client" homeagent.spec # rpmbuild -ba --define "variant client" hologramagent.spec
%define _prefix /usr %define _prefix /usr
%define _bindir %{_prefix}/bin %define _bindir %{_prefix}/bin
%define _unitdir %{_prefix}/lib/systemd/system %define _unitdir %{_prefix}/lib/systemd/system
%define _datadir %{_prefix}/share/homeagent %define _datadir %{_prefix}/share/hologramagent
%define _varlibdir /var/lib/homeagent %define _varlibdir /var/lib/hologram
%if %{undefined variant} %if %{undefined variant}
%define variant full %define variant full
%endif %endif
Name: homeagent-%{variant} Name: hologramagent-%{variant}
Version: %{_version} Version: %{_version}
Release: 1%{?dist} Release: 1%{?dist}
Summary: HomeAgent - Personal AI Home Assistant Summary: HologramAgent - Personal AI Home Assistant
License: Proprietary License: Proprietary
URL: https://github.com/trueagent/HomeAgent URL: https://github.com/trueagent/HologramAgent
Group: System Environment/Daemons Group: System Environment/Daemons
BuildArch: %{_arch} BuildArch: %{_arch}
@ -36,19 +36,19 @@ Requires: libX11, libxcb, libdrm, mesa-libGL, nss, nspr, atk, at-spi2-atk, cairo
%endif %endif
%description %description
HomeAgent is a personal AI home assistant that integrates large language HologramAgent is a personal AI home assistant that integrates large language
models with system automation. models with system automation.
%if "%{variant}" == "full" %if "%{variant}" == "full"
This package includes the full suite: homed (daemon), waiter (CLI), This package includes the full suite: homed (daemon), waiter (CLI),
and homeagent-gui (desktop GUI). and hologram-gui (desktop GUI).
%else %else
%if "%{variant}" == "server" %if "%{variant}" == "server"
This package includes the server components: homed (daemon) and waiter (CLI). This package includes the server components: homed (daemon) and waiter (CLI).
%else %else
%if "%{variant}" == "client" %if "%{variant}" == "client"
This package includes the client components: waiter (CLI) and This package includes the client components: waiter (CLI) and
homeagent-gui (desktop GUI). Connects to a remote HomeAgent server. hologram-gui (desktop GUI). Connects to a remote HologramAgent server.
%endif %endif
%endif %endif
%endif %endif
@ -60,7 +60,7 @@ mkdir -p %{buildroot}%{_varlibdir}
%if "%{variant}" == "full" || "%{variant}" == "server" %if "%{variant}" == "full" || "%{variant}" == "server"
install -m 755 %{_sourcedir}/homed %{buildroot}%{_bindir}/homed install -m 755 %{_sourcedir}/homed %{buildroot}%{_bindir}/homed
install -m 644 %{_sourcedir}/homeagent.service %{buildroot}%{_unitdir}/homeagent.service install -m 644 %{_sourcedir}/hologramagent.service %{buildroot}%{_unitdir}/hologramagent.service
%endif %endif
# waiter 三个变体都要:server 也含 CLI(对齐 deb 的 stage_variant # waiter 三个变体都要:server 也含 CLI(对齐 deb 的 stage_variant
@ -68,8 +68,8 @@ install -m 644 %{_sourcedir}/homeagent.service %{buildroot}%{_unitdir}/homeagent
install -m 755 %{_sourcedir}/waiter %{buildroot}%{_bindir}/waiter install -m 755 %{_sourcedir}/waiter %{buildroot}%{_bindir}/waiter
%if "%{variant}" == "full" || "%{variant}" == "client" %if "%{variant}" == "full" || "%{variant}" == "client"
mkdir -p %{buildroot}%{_datadir}/homeagent-gui mkdir -p %{buildroot}%{_datadir}/hologram-gui
cp -r %{_sourcedir}/homeagent-gui-linux-*/* %{buildroot}%{_datadir}/homeagent-gui/ cp -r %{_sourcedir}/hologram-gui-linux-*/* %{buildroot}%{_datadir}/hologram-gui/
%endif %endif
%files %files
@ -77,33 +77,33 @@ cp -r %{_sourcedir}/homeagent-gui-linux-*/* %{buildroot}%{_datadir}/homeagent-gu
%if "%{variant}" == "full" || "%{variant}" == "server" %if "%{variant}" == "full" || "%{variant}" == "server"
%{_bindir}/homed %{_bindir}/homed
%{_unitdir}/homeagent.service %{_unitdir}/hologramagent.service
%dir %{_varlibdir} %dir %{_varlibdir}
%endif %endif
%{_bindir}/waiter %{_bindir}/waiter
%if "%{variant}" == "full" || "%{variant}" == "client" %if "%{variant}" == "full" || "%{variant}" == "client"
%dir %{_datadir}/homeagent-gui %dir %{_datadir}/hologram-gui
%{_datadir}/homeagent-gui/* %{_datadir}/hologram-gui/*
%endif %endif
%post %post
%if "%{variant}" == "full" || "%{variant}" == "server" %if "%{variant}" == "full" || "%{variant}" == "server"
mkdir -p %{_varlibdir} mkdir -p %{_varlibdir}
%systemd_post homeagent.service %systemd_post hologramagent.service
%endif %endif
%preun %preun
%if "%{variant}" == "full" || "%{variant}" == "server" %if "%{variant}" == "full" || "%{variant}" == "server"
%systemd_preun homeagent.service %systemd_preun hologramagent.service
%endif %endif
%postun %postun
%if "%{variant}" == "full" || "%{variant}" == "server" %if "%{variant}" == "full" || "%{variant}" == "server"
%systemd_postun_with_restart homeagent.service %systemd_postun_with_restart hologramagent.service
%endif %endif
%changelog %changelog
* Mon Jul 20 2026 HomeAgent Team <team@homeagent.ai> - %{version}-1 * Mon Jul 20 2026 HologramAgent Team <team@hologramagent.ai> - %{version}-1
- Initial Linux packaging - Initial Linux packaging

View File

@ -86,7 +86,7 @@ case "$ARCH" in
*) echo "Unknown arch: $ARCH (use amd64 or arm64)"; exit 1 ;; *) echo "Unknown arch: $ARCH (use amd64 or arm64)"; exit 1 ;;
esac esac
echo "=== HomeAgent Linux Packager ===" echo "=== HologramAgent Linux Packager ==="
echo "Version: $VERSION" echo "Version: $VERSION"
[ "$PKG_VERSION" = "$VERSION" ] || echo "Package: $PKG_VERSION (normalized for deb/rpm)" [ "$PKG_VERSION" = "$VERSION" ] || echo "Package: $PKG_VERSION (normalized for deb/rpm)"
echo "Arch: $ARCH" echo "Arch: $ARCH"
@ -198,7 +198,7 @@ build_go() {
# 一道强制校验:架构不符就删掉目录并跳过 GUI,宁可不发也不发坏包。 # 一道强制校验:架构不符就删掉目录并跳过 GUI,宁可不发也不发坏包。
build_gui() { build_gui() {
local gui_dir="$PROJECT_ROOT/cmd/gui" local gui_dir="$PROJECT_ROOT/cmd/gui"
local gui_out="$BUILD_DIR/homeagent-gui-linux-${TAR_ARCH}" local gui_out="$BUILD_DIR/hologram-gui-linux-${TAR_ARCH}"
if [ -d "$gui_out" ]; then if [ -d "$gui_out" ]; then
echo ">>> GUI already built at $gui_out (delete to rebuild)" echo ">>> GUI already built at $gui_out (delete to rebuild)"
@ -343,11 +343,11 @@ print(m.group(1) if m else '')
fi fi
# create desktop entry and symlink # create desktop entry and symlink
cat > "$gui_out/resources/app/homeagent-gui.desktop" << DESKTOP cat > "$gui_out/resources/app/hologram-gui.desktop" << DESKTOP
[Desktop Entry] [Desktop Entry]
Name=HomeAgent Name=HologramAgent
Comment=HomeAgent Desktop GUI Comment=HologramAgent Desktop GUI
Exec=$gui_out/homeagent-gui Exec=$gui_out/hologram-gui
Terminal=false Terminal=false
Type=Application Type=Application
Categories=Utility; Categories=Utility;
@ -355,12 +355,12 @@ Icon=$gui_out/resources/app/icon.svg
DESKTOP DESKTOP
# create launcher script # create launcher script
cat > "$gui_out/homeagent-gui" << 'LAUNCHER' cat > "$gui_out/hologram-gui" << 'LAUNCHER'
#!/bin/sh #!/bin/sh
DIR="$(cd "$(dirname "$0")" && pwd)" DIR="$(cd "$(dirname "$0")" && pwd)"
exec "$DIR/electron" "$DIR/resources/app" "$@" exec "$DIR/electron" "$DIR/resources/app" "$@"
LAUNCHER LAUNCHER
chmod +x "$gui_out/homeagent-gui" chmod +x "$gui_out/hologram-gui"
chmod +x "$gui_out/electron" chmod +x "$gui_out/electron"
# 最后一道强制校验:electron 二进制的实际架构必须匹配目标架构。 # 最后一道强制校验:electron 二进制的实际架构必须匹配目标架构。
@ -398,7 +398,7 @@ stage_variant() {
mkdir -p "$staging/usr/bin" mkdir -p "$staging/usr/bin"
mkdir -p "$staging/etc/systemd/system" mkdir -p "$staging/etc/systemd/system"
mkdir -p "$staging/var/lib/homeagent" mkdir -p "$staging/var/lib/hologram"
local initconfig_bin="$BUILD_DIR/initconfig_$suffix" local initconfig_bin="$BUILD_DIR/initconfig_$suffix"
@ -457,7 +457,7 @@ stage_variant() {
stage_sdk() { stage_sdk() {
local staging="$1" local staging="$1"
local sdk_src="$PROJECT_ROOT/third_party/homeagent-sdk" local sdk_src="$PROJECT_ROOT/third_party/homeagent-sdk"
local sdk_dst="$staging/usr/lib/homeagent/sdk" local sdk_dst="$staging/usr/lib/hologram/sdk"
[ -d "$sdk_src" ] || { echo "ERROR: 找不到 SDK 源码 $sdk_src" >&2; return 1; } [ -d "$sdk_src" ] || { echo "ERROR: 找不到 SDK 源码 $sdk_src" >&2; return 1; }
mkdir -p "$sdk_dst" mkdir -p "$sdk_dst"
for item in go.mod go.sum LICENSE README.md sdk meta tools skills; do for item in go.mod go.sum LICENSE README.md sdk meta tools skills; do
@ -475,7 +475,7 @@ stage_variant() {
cp "$BUILD_DIR/homed_$suffix" "$staging/usr/bin/homed" cp "$BUILD_DIR/homed_$suffix" "$staging/usr/bin/homed"
cp "$BUILD_DIR/waiter_$suffix" "$staging/usr/bin/waiter" cp "$BUILD_DIR/waiter_$suffix" "$staging/usr/bin/waiter"
stage_depgraph "$staging" stage_depgraph "$staging"
cp "$PROJECT_ROOT/deploy/homeagent.service" "$staging/etc/systemd/system/homeagent.service" cp "$PROJECT_ROOT/deploy/hologramagent.service" "$staging/etc/systemd/system/hologramagent.service"
[ -f "$initconfig_bin" ] && cp "$initconfig_bin" "$staging/usr/bin/initconfig" [ -f "$initconfig_bin" ] && cp "$initconfig_bin" "$staging/usr/bin/initconfig"
stage_setup "$staging" stage_setup "$staging"
stage_license "$staging" stage_license "$staging"
@ -486,7 +486,7 @@ stage_variant() {
cp "$BUILD_DIR/homed_$suffix" "$staging/usr/bin/homed" cp "$BUILD_DIR/homed_$suffix" "$staging/usr/bin/homed"
cp "$BUILD_DIR/waiter_$suffix" "$staging/usr/bin/waiter" cp "$BUILD_DIR/waiter_$suffix" "$staging/usr/bin/waiter"
stage_depgraph "$staging" stage_depgraph "$staging"
cp "$PROJECT_ROOT/deploy/homeagent.service" "$staging/etc/systemd/system/homeagent.service" cp "$PROJECT_ROOT/deploy/hologramagent.service" "$staging/etc/systemd/system/hologramagent.service"
[ -f "$initconfig_bin" ] && cp "$initconfig_bin" "$staging/usr/bin/initconfig" [ -f "$initconfig_bin" ] && cp "$initconfig_bin" "$staging/usr/bin/initconfig"
stage_setup "$staging" stage_setup "$staging"
stage_license "$staging" stage_license "$staging"
@ -499,7 +499,7 @@ stage_variant() {
stage_depgraph "$staging" stage_depgraph "$staging"
stage_hmapdev "$staging" stage_hmapdev "$staging"
stage_sdk "$staging" stage_sdk "$staging"
cp "$PROJECT_ROOT/deploy/homeagent.service" "$staging/etc/systemd/system/homeagent.service" cp "$PROJECT_ROOT/deploy/hologramagent.service" "$staging/etc/systemd/system/hologramagent.service"
[ -f "$initconfig_bin" ] && cp "$initconfig_bin" "$staging/usr/bin/initconfig" [ -f "$initconfig_bin" ] && cp "$initconfig_bin" "$staging/usr/bin/initconfig"
stage_setup "$staging" stage_setup "$staging"
stage_license "$staging" stage_license "$staging"
@ -520,15 +520,15 @@ stage_variant() {
stage_gui() { stage_gui() {
local staging="$1" local staging="$1"
local gui_src="$BUILD_DIR/homeagent-gui-linux-${TAR_ARCH}" local gui_src="$BUILD_DIR/hologram-gui-linux-${TAR_ARCH}"
if [ -d "$gui_src" ]; then if [ -d "$gui_src" ]; then
mkdir -p "$staging/usr/lib/homeagent-gui" mkdir -p "$staging/usr/lib/hologram-gui"
cp -r "$gui_src"/* "$staging/usr/lib/homeagent-gui/" cp -r "$gui_src"/* "$staging/usr/lib/hologram-gui/"
cat > "$staging/usr/bin/homeagent-gui" << 'SCRIPT' cat > "$staging/usr/bin/hologram-gui" << 'SCRIPT'
#!/bin/sh #!/bin/sh
exec /usr/lib/homeagent-gui/homeagent-gui "$@" exec /usr/lib/hologram-gui/hologram-gui "$@"
SCRIPT SCRIPT
chmod 755 "$staging/usr/bin/homeagent-gui" chmod 755 "$staging/usr/bin/hologram-gui"
else else
echo " WARNING: GUI not built, skipping GUI staging" echo " WARNING: GUI not built, skipping GUI staging"
fi fi
@ -538,30 +538,30 @@ stage_setup() {
local staging="$1" local staging="$1"
local setup_src="$PROJECT_ROOT/deploy/packaging/linux/setup.sh" local setup_src="$PROJECT_ROOT/deploy/packaging/linux/setup.sh"
if [ -f "$setup_src" ]; then if [ -f "$setup_src" ]; then
mkdir -p "$staging/usr/lib/homeagent" mkdir -p "$staging/usr/lib/hologram"
cp "$setup_src" "$staging/usr/lib/homeagent/setup.sh" cp "$setup_src" "$staging/usr/lib/hologram/setup.sh"
chmod 755 "$staging/usr/lib/homeagent/setup.sh" chmod 755 "$staging/usr/lib/hologram/setup.sh"
fi fi
} }
# 项目自身的许可:**所有变体**都要带(client 也分发 waiter 与 GUI)。 # 项目自身的许可:**所有变体**都要带(client 也分发 waiter 与 GUI)。
# #
# deb 按 Debian 惯例给 /usr/share/doc/homeagent/copyright(DEP-5 机器可读格式), # deb 按 Debian 惯例给 /usr/share/doc/hologramagent/copyright(DEP-5 机器可读格式),
# 同时把 LICENSE 全文放进去;rpm 的许可走 fpm 的 --license 元数据。 # 同时把 LICENSE 全文放进去;rpm 的许可走 fpm 的 --license 元数据。
# 与 stage_multimodal_assets 的 licenses/ 分工:那里放**第三方**(模型/运行库)的 # 与 stage_multimodal_assets 的 licenses/ 分工:那里放**第三方**(模型/运行库)的
# 许可全文,这里放本项目自己的。 # 许可全文,这里放本项目自己的。
stage_license() { stage_license() {
local staging="$1" local staging="$1"
local docdir="$staging/usr/share/doc/homeagent" local docdir="$staging/usr/share/doc/hologramagent"
mkdir -p "$docdir" mkdir -p "$docdir"
cp "$PROJECT_ROOT/LICENSE" "$docdir/LICENSE" cp "$PROJECT_ROOT/LICENSE" "$docdir/LICENSE"
cat > "$docdir/copyright" <<'EOF' cat > "$docdir/copyright" <<'EOF'
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: HomeAgent Upstream-Name: HologramAgent
Source: https://github.com/JianFeeeee/HomeAgent Source: https://github.com/JianFeeeee/HologramAgent
Files: * Files: *
Copyright: HomeAgent contributors Copyright: HologramAgent contributors
License: AGPL-3.0-only License: AGPL-3.0-only
This program is free software: you can redistribute it and/or modify it under This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free the terms of the GNU Affero General Public License as published by the Free
@ -579,18 +579,18 @@ License: AGPL-3.0-only
clause (§13 Remote Network Interaction) — offering modified versions of this clause (§13 Remote Network Interaction) — offering modified versions of this
software to users over a network also requires offering them the source. software to users over a network also requires offering them the source.
. .
Full text: /usr/share/doc/homeagent/LICENSE Full text: /usr/share/doc/hologramagent/LICENSE
Files: usr/lib/homeagent/models/chinese-clip-vit-b16-onnx/* Files: usr/lib/hologram/models/chinese-clip-vit-b16-onnx/*
Copyright: OFA-Sys / Chinese-CLIP authors Copyright: OFA-Sys / Chinese-CLIP authors
License: Apache-2.0 License: Apache-2.0
Full text: /usr/share/doc/homeagent/licenses/Chinese-CLIP-Apache-2.0.txt Full text: /usr/share/doc/hologramagent/licenses/Chinese-CLIP-Apache-2.0.txt
Comment: pre-trained model artifacts; NOT covered by this package's AGPL grant Comment: pre-trained model artifacts; NOT covered by this package's AGPL grant
Files: usr/lib/homeagent/onnxruntime/* Files: usr/lib/hologram/onnxruntime/*
Copyright: Microsoft Corporation Copyright: Microsoft Corporation
License: MIT License: MIT
Full text: /usr/share/doc/homeagent/licenses/ONNX-Runtime-MIT.txt Full text: /usr/share/doc/hologramagent/licenses/ONNX-Runtime-MIT.txt
Comment: license texts and third-party notices under licenses/ONNX-Runtime-* Comment: license texts and third-party notices under licenses/ONNX-Runtime-*
EOF EOF
chmod 644 "$docdir/LICENSE" "$docdir/copyright" chmod 644 "$docdir/LICENSE" "$docdir/copyright"
@ -600,9 +600,9 @@ EOF
# 只要打 server/full 包,两者缺一就失败。client 包不运行 homed,故不携带。 # 只要打 server/full 包,两者缺一就失败。client 包不运行 homed,故不携带。
stage_multimodal_assets() { stage_multimodal_assets() {
local staging="$1" local staging="$1"
local model_dst="$staging/usr/lib/homeagent/models/chinese-clip-vit-b16-onnx" local model_dst="$staging/usr/lib/hologram/models/chinese-clip-vit-b16-onnx"
local ort_dst="$staging/usr/lib/homeagent/onnxruntime" local ort_dst="$staging/usr/lib/hologram/onnxruntime"
local licenses="$staging/usr/share/doc/homeagent/licenses" local licenses="$staging/usr/share/doc/hologramagent/licenses"
if [ ! -d "$CHINESECLIP_BUNDLE_DIR" ]; then if [ ! -d "$CHINESECLIP_BUNDLE_DIR" ]; then
echo "ERROR: Chinese-CLIP 产物目录不存在:$CHINESECLIP_BUNDLE_DIR" >&2 echo "ERROR: Chinese-CLIP 产物目录不存在:$CHINESECLIP_BUNDLE_DIR" >&2
@ -672,7 +672,7 @@ build_deb() {
local deb_dir="${DIST_DIR}/deb" local deb_dir="${DIST_DIR}/deb"
mkdir -p "$deb_dir" mkdir -p "$deb_dir"
local pkg_name="homeagent-${variant}_${PKG_VERSION}_${DEB_ARCH}.deb" local pkg_name="hologramagent-${variant}_${PKG_VERSION}_${DEB_ARCH}.deb"
local deb_root local deb_root
deb_root="$(mktemp -d "$STAGE_TMP/deb.XXXXXX")" deb_root="$(mktemp -d "$STAGE_TMP/deb.XXXXXX")"
@ -711,13 +711,13 @@ build_tar() {
local tar_dir="${DIST_DIR}/tar" local tar_dir="${DIST_DIR}/tar"
mkdir -p "$tar_dir" mkdir -p "$tar_dir"
local archive_name="homeagent_${PKG_VERSION}_linux_${TAR_ARCH}.tar.gz" local archive_name="hologramagent_${PKG_VERSION}_linux_${TAR_ARCH}.tar.gz"
local archive_dir="homeagent-${PKG_VERSION}-linux-${TAR_ARCH}" local archive_dir="hologramagent-${PKG_VERSION}-linux-${TAR_ARCH}"
# build combined staging # build combined staging
local staging local staging
staging="$(mktemp -d "$STAGE_TMP/tar.XXXXXX")" staging="$(mktemp -d "$STAGE_TMP/tar.XXXXXX")"
mkdir -p "$staging/usr/bin" "$staging/usr/lib/homeagent" "$staging/etc/systemd/system" mkdir -p "$staging/usr/bin" "$staging/usr/lib/hologram" "$staging/etc/systemd/system"
# copy all available binaries # copy all available binaries
for bin in homed waiter initconfig; do for bin in homed waiter initconfig; do
@ -727,21 +727,21 @@ build_tar() {
# setup script # setup script
local setup_src="$PROJECT_ROOT/deploy/packaging/linux/setup.sh" local setup_src="$PROJECT_ROOT/deploy/packaging/linux/setup.sh"
[ -f "$setup_src" ] && cp "$setup_src" "$staging/usr/lib/homeagent/setup.sh" [ -f "$setup_src" ] && cp "$setup_src" "$staging/usr/lib/hologram/setup.sh"
cp "$PROJECT_ROOT/deploy/homeagent.service" "$staging/etc/systemd/system/homeagent.service" cp "$PROJECT_ROOT/deploy/hologramagent.service" "$staging/etc/systemd/system/hologramagent.service"
stage_license "$staging" stage_license "$staging"
stage_multimodal_assets "$staging" stage_multimodal_assets "$staging"
# GUI if available # GUI if available
local gui_src="$BUILD_DIR/homeagent-gui-linux-${TAR_ARCH}" local gui_src="$BUILD_DIR/hologram-gui-linux-${TAR_ARCH}"
if [ -d "$gui_src" ]; then if [ -d "$gui_src" ]; then
mkdir -p "$staging/usr/lib/homeagent-gui" mkdir -p "$staging/usr/lib/hologram-gui"
cp -r "$gui_src"/* "$staging/usr/lib/homeagent-gui/" cp -r "$gui_src"/* "$staging/usr/lib/hologram-gui/"
cat > "$staging/usr/bin/homeagent-gui" << 'SCRIPT' cat > "$staging/usr/bin/hologram-gui" << 'SCRIPT'
#!/bin/sh #!/bin/sh
exec /usr/lib/homeagent-gui/homeagent-gui "$@" exec /usr/lib/hologram-gui/hologram-gui "$@"
SCRIPT SCRIPT
chmod 755 "$staging/usr/bin/homeagent-gui" chmod 755 "$staging/usr/bin/hologram-gui"
fi fi
chmod 755 "$staging/usr/bin/"* 2>/dev/null || true chmod 755 "$staging/usr/bin/"* 2>/dev/null || true
@ -759,7 +759,7 @@ build_rpm() {
local rpm_dir="${DIST_DIR}/rpm" local rpm_dir="${DIST_DIR}/rpm"
mkdir -p "$rpm_dir" mkdir -p "$rpm_dir"
local pkg_name="homeagent-${variant}-${PKG_VERSION}-1.${RPM_ARCH}.rpm" local pkg_name="hologramagent-${variant}-${PKG_VERSION}-1.${RPM_ARCH}.rpm"
# find fpm # find fpm
local fpm_bin="$(command -v fpm 2>/dev/null || true)" local fpm_bin="$(command -v fpm 2>/dev/null || true)"
@ -770,7 +770,7 @@ build_rpm() {
if [ -z "$fpm_bin" ]; then if [ -z "$fpm_bin" ]; then
echo " SKIP .rpm: fpm not installed. Install it with: gem install fpm" echo " SKIP .rpm: fpm not installed. Install it with: gem install fpm"
echo " Alternatively, build RPM on Fedora/RHEL using:" echo " Alternatively, build RPM on Fedora/RHEL using:"
echo " rpmbuild -ba deploy/packaging/linux/homeagent.spec" echo " rpmbuild -ba deploy/packaging/linux/hologramagent.spec"
return return
fi fi
@ -804,12 +804,12 @@ build_rpm() {
echo ">>> Building .rpm via fpm: $pkg_name" echo ">>> Building .rpm via fpm: $pkg_name"
"$fpm_bin" -s dir -t rpm \ "$fpm_bin" -s dir -t rpm \
-n "homeagent-${variant}" \ -n "hologramagent-${variant}" \
-v "$VERSION" \ -v "$VERSION" \
--iteration 1 \ --iteration 1 \
-a "$RPM_ARCH" \ -a "$RPM_ARCH" \
--description "HomeAgent ${variant^} package" \ --description "HologramAgent ${variant^} package" \
--url "https://github.com/trueagent/HomeAgent" \ --url "https://github.com/trueagent/HologramAgent" \
--license "AGPL-3.0-only" \ --license "AGPL-3.0-only" \
-C "$staging" \ -C "$staging" \
-p "$rpm_dir/$pkg_name" \ -p "$rpm_dir/$pkg_name" \
@ -874,7 +874,7 @@ main() {
# 只列**本批**产物:dist/ 会跨多次构建累积,用 find 全目录会让清单/SHA256SUMS # 只列**本批**产物:dist/ 会跨多次构建累积,用 find 全目录会让清单/SHA256SUMS
# 带上历史版本的文件名——用户下载那种清单后 `sha256sum -c` 必然报缺失。 # 带上历史版本的文件名——用户下载那种清单后 `sha256sum -c` 必然报缺失。
# (v1.2.2 构建时就出现过:清单里混进了 1.2.0/1.2.1 的包名。)按本批版本号过滤。 # (v1.2.2 构建时就出现过:清单里混进了 1.2.0/1.2.1 的包名。)按本批版本号过滤。
mapfile -t release_files < <(find "$DIST_DIR" -type f \( -name "*${PKG_VERSION}*.deb" -o -name "homeagent_${PKG_VERSION}_*.tar.gz" -o -name "*${PKG_VERSION}*.rpm" \) 2>/dev/null | sort) mapfile -t release_files < <(find "$DIST_DIR" -type f \( -name "*${PKG_VERSION}*.deb" -o -name "hologramagent_${PKG_VERSION}_*.tar.gz" -o -name "*${PKG_VERSION}*.rpm" \) 2>/dev/null | sort)
for f in "${release_files[@]}"; do for f in "${release_files[@]}"; do
echo " $(du -h "$f" | cut -f1) $f" echo " $(du -h "$f" | cut -f1) $f"
done done

View File

@ -168,9 +168,150 @@ func TestToolchainVariantHasControlFile(t *testing.T) {
t.Fatal("★ 缺 control-toolchain —— toolchain 变体打不出来") t.Fatal("★ 缺 control-toolchain —— toolchain 变体打不出来")
} }
c := string(b) c := string(b)
for _, kw := range []string{"homeagent-toolchain", "hmapdev", "SDK", "depgraph"} { for _, kw := range []string{"hologramagent-toolchain", "hmapdev", "SDK", "depgraph"} {
if !strings.Contains(c, kw) { if !strings.Contains(c, kw) {
t.Errorf("control-toolchain 的描述里应提到 %s(让 apt show 能说清装了什么)", kw) t.Errorf("control-toolchain 的描述里应提到 %s(让 apt show 能说清装了什么)", kw)
} }
} }
} }
// ★★★ 判据:打包产物里的**安装路径与单元名**必须已随品牌改名(批 2)。
//
// 这条守的是"改一半就静默失效"那一类:包能打出来、退出码 0,但内容里
// 还写着旧路径 —— 装上去之后 systemd 找不到单元、数据目录对不上、
// ONNX 运行库指向空目录,而且没有任何一步报错。
//
// 只扫**产物布局相关**的旧串,不扫 module 路径(那是批 1 的地盘,
// 见 TestPackagingLdflagsUseCurrentModulePath)。
func TestPackagingUsesRenamedInstallPaths(t *testing.T) {
src := readOrSkip(t, pkgLinux)
// 安装路径 / 单元文件:一个都不许留旧值。
for _, stale := range []string{
"/var/lib/homeagent",
"/usr/lib/homeagent",
"/usr/share/doc/homeagent",
"deploy/homeagent.service",
"/etc/systemd/system/homeagent.service",
"/usr/bin/homeagent-gui",
"/usr/lib/homeagent-gui",
`pkg_name="homeagent-`,
} {
if strings.Contains(src, stale) {
t.Errorf("★ package-linux.sh 仍含旧安装路径/包名 %q —— "+
"打出的包会装到旧位置(日志全绿,装完路径对不上)", stale)
}
}
// 新值必须真的出现(否则上面的"无旧值"可能只是整段被删了)。
for _, want := range []string{
"/var/lib/hologram",
"/usr/lib/hologram",
"/usr/share/doc/hologramagent",
"deploy/hologramagent.service",
"/etc/systemd/system/hologramagent.service",
"/usr/bin/hologram-gui",
"/usr/lib/hologram-gui",
`pkg_name="hologramagent-`,
} {
if !strings.Contains(src, want) {
t.Errorf("★ package-linux.sh 缺少 %q —— 改名没落到位", want)
}
}
}
// ★★★ 判据:deb 的 postinst / prerm 必须操作**新**单元名。
//
// postinst 的 SERVICE_NAME 若还是旧名,装完 systemctl enable 找不到单元:
// 它带 `|| true`,所以一声不响地什么也没启用 —— 装完不会开机自启。
func TestDebMaintainerScriptsUseRenamedService(t *testing.T) {
for _, p := range []string{
"../../deploy/packaging/linux/deb/postinst",
"../../deploy/packaging/linux/deb/prerm",
} {
b, err := os.ReadFile(p)
if err != nil {
t.Skipf("读不到 %s: %v", p, err)
}
s := string(b)
if !strings.Contains(s, `SERVICE_NAME="hologramagent"`) {
t.Errorf("★ %s 的 SERVICE_NAME 不是 hologramagent —— "+
"systemctl enable/stop 会作用在不存在的单元上(|| true 吞掉失败)", p)
}
if strings.Contains(s, `SERVICE_NAME="homeagent"`) {
t.Errorf("★ %s 仍用旧 SERVICE_NAME=homeagent", p)
}
if strings.Contains(s, "/var/lib/homeagent") || strings.Contains(s, "/usr/lib/homeagent") {
t.Errorf("★ %s 仍含旧安装路径", p)
}
}
}
// ★★★ 判据:四个 deb control 的包名与 SDK 安装路径必须已改。
//
// `dpkg-deb -f <pkg> Package` 的输出就是这里的 Package 字段;
// 旧名会让 apt 认为是另一个包(升级路径直接断成"装了第二个包")。
func TestDebControlFilesUseRenamedPackage(t *testing.T) {
for _, variant := range []string{"client", "server", "full", "toolchain"} {
p := "../../deploy/packaging/linux/deb/control-" + variant
b, err := os.ReadFile(p)
if err != nil {
t.Fatalf("读不到 %s: %v", p, err)
}
s := string(b)
want := "Package: hologramagent-" + variant + "\n"
if !strings.Contains(s, want) {
t.Errorf("★ %s 缺少 %q", p, strings.TrimSpace(want))
}
if strings.Contains(s, "Package: homeagent-") {
t.Errorf("★ %s 的 Package 仍是旧的 homeagent-*", p)
}
if strings.Contains(s, "/usr/lib/homeagent") {
t.Errorf("★ %s 的 SDK 安装路径仍是 /usr/lib/homeagent", p)
}
}
if b, err := os.ReadFile("../../deploy/packaging/linux/deb/control-toolchain"); err == nil {
if !strings.Contains(string(b), "/usr/lib/hologram/sdk") {
t.Error("★ control-toolchain 没把 SDK 装到 /usr/lib/hologram/sdk")
}
}
}
// ★★★ 判据:systemd 单元文件本身(deploy/hologramagent.service)。
//
// 文件名改了、内容没改是最典型的一半:ExecStart 仍写旧数据目录,
// 于是 StateDirectory / ReadWritePaths 与实际 --data 不一致,
// 内核起得来但写到只读路径上(或反之)—— 取决于 sandbox 设置,难查。
func TestSystemdUnitUsesRenamedPaths(t *testing.T) {
b, err := os.ReadFile("../../deploy/hologramagent.service")
if err != nil {
t.Fatalf("★ 缺 deploy/hologramagent.service: %v", err)
}
s := string(b)
for _, want := range []string{
"--data /var/lib/hologram",
"WorkingDirectory=/var/lib/hologram",
"StateDirectory=hologram",
"ReadWritePaths=/var/lib/hologram",
"ReadOnlyPaths=/etc/hologram",
"ONNXRUNTIME_DIR=/usr/lib/hologram/onnxruntime",
"LoadCredential=homed_security_key:/etc/hologram/security.key",
} {
if !strings.Contains(s, want) {
t.Errorf("★ hologramagent.service 缺 %q", want)
}
}
// 注释里可以留旧路径(升级说明),但**指令行**不能有。
for _, line := range strings.Split(s, "\n") {
trimmed := strings.TrimSpace(line)
if trimmed == "" || strings.HasPrefix(trimmed, "#") {
continue
}
if strings.Contains(trimmed, "/var/lib/homeagent") || strings.Contains(trimmed, "/usr/lib/homeagent") {
t.Errorf("★ hologramagent.service 指令行仍含旧路径: %s", trimmed)
}
}
if _, err := os.Stat("../../deploy/homeagent.service"); err == nil {
t.Error("★ deploy/homeagent.service 仍然存在 —— 旧单元文件没删,两个单元会打架")
}
}