Files
arcrun-collector/cmd/arcrun-app/build-win.sh
T
Leo 4d3a6a09a6 v0.18.9:collector 併進同一支執行檔——磁碟上不再攤出第二支 exe
leo 08-06 裁決:「不要兩支,寫成一支檔案」。

## 為什麼
v0.18.7-8 的「單一 exe」其實是**一支包著另一支**:collector.exe 被 go:embed
進 Arcrun.exe,執行時攤到 ~/.arcrun-rag/bin/ 再跑。
那正是防毒軟體眼中的 dropper 特徵 —— 封測者實撞
`Trojan:Win32/Sabsik.FL.A!ml`,檔案當場被隔離、自動刪除。

⚠️ 誠實界定:`!ml` 結尾=**機器學習判定**,Sabsik 是最常見的通用誤判家族,
   主因是「未簽章+下載次數少」,**不是**特別指向 dropper 行為。
   所以本次改動**不保證**解除誤判——真正的解是上架 MS Store(微軟簽章)。
   但「執行時把第二支 PE 寫到磁碟再執行」本來就該拿掉,這是對的方向且順手變小。

## 怎麼做
- `collector/` 39 個檔 `package main` → `package collector`,`main()` → 匯出的 `Run(args) int`
- 新增 `collector/cmd/collector/`(薄殼 CLI,讓單獨跑 collector 這條路仍可用)
- App 直接 import 該套件;`main()` 第一件事就判 `--collector`,是的話走 `collector.Run` 不碰 GUI
- `supervisor` 加 `ArgPrefix`,App 把 `BinPath` 指向 `os.Executable()` 自己
- 刪掉 `bundled_collector_{windows,other}.go`(embed + 攤檔那套)
- 三支打包腳本不再編/複製第二支;版本注入同時打到兩個 package
- build-win.sh 的機械閘改成**直接問它**:`--collector --version` 回得出版本才放行
  (舊閘是比大小,只能證明「有 embed」,證明不了「分派是對的」)

## 驗(真機實跑)
· `.app/Contents/MacOS/` 只有 **一個** 執行檔(原本兩個)
· 跑起來兩個行程是**同一個 exe**:
    …/MacOS/arcrun-app
    …/MacOS/arcrun-app --collector direct --config …
· `~/.arcrun-rag/bin` **不存在**(沒有任何東西被攤出來)
· 端到端:丟檔進看守資料夾 → collector.log `"status":"ingested","http_status":200`
· `lsappinfo` 仍是 `type="UIElement"`、`Version="0.18.9"`
· collector 39 檔測試全過;app 測試過;go vet 全綠;mac + windows 交叉編譯皆過
· 單檔 26MB → 22MB(不再夾帶第二份完整程式)
2026-08-06 16:00:47 +08:00

116 lines
6.5 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
# build-win.sh — 打包 Arcrun Windows 版(Wailst1962026-08-05
#
# leo 08-05:「Windows 版一定要重編,因為我只有 Mac,我需要人家測試,
# 要做到最完善不要給人家找麻煩」
#
# 🎯 **在 Mac 上就能交叉編譯**,不需要 Windows 機器/Docker。
# 條件只有一個:`brew install mingw-w64`(提供 x86_64-w64-mingw32-gcc)。
# Wails 的 Windows 版要 CGoWebView2 綁定),所以 CGO_ENABLED=1 + mingw。
#
# 與 build-mac.sh 同一個要點:**必須把 collector 同綑進去**。
# daemon 的本體是 `collector direct`(監看/萃卡/上傳),App 只是門面;
# 沒同綑 ⇒ 使用者裝了也不會同步(t194 在 Mac 版就漏過一次)。
#
# ⚠️ 誠實界定(沿用 build-windows.sh 的自陳):
# 本腳本只證明「**編得出來**」,不證明「**跑起來對**」。
# 托盤圖示會不會出現、WebView2 有沒有裝、SmartScreen 攔截行為,
# **只有真的在 Windows 上跑才驗得到**——那一步歸 leo/封測者真機。
set -euo pipefail
cd "$(dirname "$0")"
export PATH="$PATH:$(go env GOPATH)/bin"
# 🔴 2026-08-06:版本號**不再手打、也不再靠 git describe**。
# 舊寫法 `git describe --tags` 在這個 repo 永遠拿不到 v0.18.x(一個 tag 都沒有)
# ⇒ 版本只能靠打包時人工 `VERSION=v0.18.4 ./build-win.sh` 敲 ⇒ manifest 說謊的病根。
# 現在由 daemon-version.py 從 DAEMON_LINE + collector/ 的 commit 數算出來,
# 兩條打包線(win/mac)在同一個 commit 上必得同一個號碼。理由全文見該腳本。
VERSION="${VERSION:-$(./daemon-version.py --stamp)}"
BUILD_TIME="$(date '+%Y%m%d-%H%M')"
echo "🏷 版本:${VERSION}build ${BUILD_TIME}"
# 🔴 2026-08-06 機械閘:這一版的「更新內容」沒寫進 changelog ⇒ 不准打包。
# leo:「給版本號、本版更新內容、打包產品、顯示在前端,這一整串都應該是機械化」。
# 單一真相源=docs-site/.../help/changelog.mdmanifest.notes 與前端全部投影自它。
# 理由與格式見 changelog-section.sh。
./changelog-section.sh "$VERSION" --check
command -v x86_64-w64-mingw32-gcc >/dev/null 2>&1 || {
echo "❌ 缺 mingw-w64Wails Windows 版需要 CGo 交叉編譯器)"
echo " 裝一次就好:brew install mingw-w64"
exit 1
}
echo "⓪ 由 appicon.png 產生 Windows 圖示(icon.icotrayicon.ico"
# 🔴 2026-08-06:不產就會沿用上一次留在磁碟上的檔——而上一次那顆是 `wails init`
# 留下的 Wails 預設「W」圖,leo 封測看到視窗與托盤兩處都是 W。
# 每次 build 都重產 ⇒ 「換了 appicon 卻沒換 Windows」這種漂移不可能再發生。
python3 gen-icons.py
# 🔴 2026-08-06 起**不再單獨編 collector.exe**(leo:「不要兩支,寫成一支檔案」)。
# collector 已改成可被引用的套件(arcrun-rag/collector.Run),直接編進 Arcrun.exe
# 靠 `--collector` 參數換身分。磁碟上永遠只有一個 exe。
# 為什麼要這樣:前一版把 collector.exe embed 進去、執行時攤到磁碟再跑,
# 那是 Windows Defender 眼中的 dropper 特徵(封測者實撞 Trojan:Win32/Sabsik.FL.A!ml)。
# 🔴 同 build-mac.shwails.json 沒 info.productVersion ⇒ exe 內容資訊永遠是 1.0.0。
# Windows 使用者在「內容→詳細資料」看到的版本讀這個欄位;MSIX 送審也會對照。
PLIST_VER="${VERSION#v}"
cp wails.json wails.json.bak
python3 - "$PLIST_VER" <<'PY'
import json, sys
c = json.load(open('wails.json'))
c.setdefault('info', {})
c['info']['productVersion'] = sys.argv[1]
c['info']['productName'] = 'Arcrun'
json.dump(c, open('wails.json', 'w'), indent=2, ensure_ascii=False)
PY
trap 'mv -f wails.json.bak wails.json 2>/dev/null || true' EXIT
echo "② wails buildwindows/amd64CGo 走 mingw"
CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc \
wails build -platform windows/amd64 -clean \
-ldflags "-X main.version=${VERSION} -X main.buildTime=${BUILD_TIME} \
-X arcrun-rag/collector.version=${VERSION} -X arcrun-rag/collector.buildTime=${BUILD_TIME}"
OUT="dist"; mkdir -p "$OUT"
echo "③ 產出**單一執行檔**"
# 🔴 2026-08-06 交付形態改變(leo 封測回報②,圖一標註):
# 「下載還是 ZIP ⇒ 應該是 MSIX 或 EXE」「解開還是 2 個檔 ⇒ 應該只有 1 個檔案」
# 「兩個檔案令人很迷惑,User unfriendly」
#
# 舊做法一=zip 裡放兩支 exe 同層。使用者只要少解一個檔,同步就永遠不會動。
# 舊做法二(v0.18.7-8)=把 collector.exe embed 起來、執行時攤到磁碟再跑。
# ⇒ **Defender 判 dropper**:封測者實撞 `Trojan:Win32/Sabsik.FL.A!ml`,檔案當場被隔離。
# 現在=collector 是套件,直接編進同一個執行檔,`--collector` 換身分。
# **下載下來就是一個檔,雙擊就跑,磁碟上不會多出任何東西。**
#
# 為什麼不出 MSIX:未上架的 MSIX 要使用者先開「開發人員模式」才裝得起來,
# 比 zip 更麻煩。上架 MS Store 後再回頭走 build-msix.sh。
EXE="$(cd "$OUT" && pwd)/Arcrun-win-${VERSION}.exe"
rm -f "$EXE"
cp build/bin/arcrun-app.exe "$EXE"
# 🔴 機械閘:這一顆必須**自己就會當 collector**。
# 過去的閘是比大小(確認 embed 進去了);現在改成**直接問它**——
# 跑 `--collector --version`,回得出版本才算數。編成空殼、或分派寫錯,都會在這裡紅。
# (不能用 wine 跑 .exe,所以驗的是同一份原始碼編出來的原生版;分派邏輯與平台無關。)
PROBE="$(mktemp -d)/probe"
go build -ldflags "-X main.version=${VERSION} -X arcrun-rag/collector.version=${VERSION}" -o "$PROBE" . || { echo "❌ 探針編不出來"; exit 1; }
PROBE_OUT="$("$PROBE" --collector --version 2>&1 | head -1)"
rm -rf "$(dirname "$PROBE")"
if [ -z "$PROBE_OUT" ]; then
echo "❌ 這顆 exe 不會當 collector--collector --version 沒有輸出)"
echo " ⇒ 裝了也不會同步。中止。"
exit 1
fi
echo " ✅ 自帶同步引擎(--collector --version → ${PROBE_OUT}"
SIZE=$(ls -lh "$EXE" | awk '{print $5}')
echo "✅ 完成:${EXE}${SIZE},單一檔案、自帶同步引擎)"
echo
echo "🔬 使用者流程:下載 → 雙擊 Arcrun.exe(不必解壓縮、不必找第二個檔)"
echo " ⚠️ 未簽章 ⇒ SmartScreen 會攔(「更多資訊」→「仍要執行」)。"
echo " 要免除這一步=上 MS Store(見 build-msix.sh)或買 EV 憑證。"