#!/usr/bin/env bash # One-shot Windows release build for the GUI — ENTIRELY inside docker. # # 1) cross-compile the embedded core in docker (llmsproxy.exe + lua51.dll) # 2) electron-builder NSIS packaging ALSO inside docker (wine for the # uninstaller step lives in the image — see Dockerfile). This is the fix # for the 1.3.0/1.4.0 broken installers: the host had amd64-only wine # (no syswow64 -> c0000135), which made electron-builder silently emit a # 264 KB degenerate exe without its 86 MB payload. # # Outputs: cmd/build/gui-dist/"ModelRouter Setup .exe" # cmd/build/gui-dist/modelrouter-gui--x64.nsis.7z # # Needs: docker (any machine; no host mingw/wine/node required) set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)" IMAGE="${WIN_BUILDER_IMAGE:-modelrouter/win-builder}" PROXY="${GOPROXY:-https://goproxy.cn,direct}" CACHE_VOL="modelrouter-eb-cache" command -v docker >/dev/null || { echo "docker required"; exit 1; } if ! docker image inspect "$IMAGE" >/dev/null 2>&1; then echo "[dist-win-docker] building image $IMAGE (first run, ~5-10 min)..." docker build -t "$IMAGE" "$ROOT/cmd/gui/docker/win-builder" fi docker volume create "$CACHE_VOL" >/dev/null 2>&1 || true # 1) embedded core + 2) NSIS packaging — both inside the image so wine and node # are the image's, never the host's. electron-builder downloads electron + nsis # toolchains into ~/.cache on first run; the mounted volume keeps that warm so # subsequent builds are incremental instead of re-fetching ~400 MB. echo "[dist-win-docker] cross-compiling core + electron-builder NSIS in docker ..." docker run --rm \ -v "$ROOT":/workspace \ -v "$CACHE_VOL":/root/.cache \ -e GOPROXY="$PROXY" \ -w /workspace \ "$IMAGE" bash -c ' set -euo pipefail cp /opt/luajit2/src/lua51.dll /workspace/cmd/gui/bin/lua51.dll GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc \ go build -buildvcs=false -tags luajit -trimpath \ -o /workspace/cmd/gui/bin/llmsproxy.exe ./cmd/llmsproxy echo " -> core built" # wine needs one prefix initialization so its wow64 runtime (syswow64/ntdll) # exists — the exact thing that was missing on the broken host. Use a shared # prefix in the cache volume so it is initialized only on the first run. export WINEPREFIX=/root/.cache/wineprefix if [ ! -f "$WINEPREFIX/drive_c/windows/syswow64/ntdll.dll" ]; then echo " -> initializing wine prefix (first run)" WINEDEBUG=-all wineboot -i || true fi cd /workspace/cmd/gui # node_modules ships in the repo (host npm install already ran); reuse it. npx electron-builder --win nsis ' echo "[dist-win-docker] verifying artifacts ..." "$ROOT/packaging/verify-dist.sh" "$ROOT/cmd/build/gui-dist" echo "[dist-win-docker] done"