fix(build): run Windows NSIS packaging inside docker; add artifact size gate

The Windows installer has been broken since 1.3.0: electron-builder's NSIS step
needs wine to generate the uninstaller, but the host's wine was amd64-only (no
i386 runtime -> empty syswow64 -> `error c0000135`), so electron-builder silently
wrote a 264 KB installer shell with no payload. No check caught it and the broken
exe shipped. 1.4.0 reproduced the same failure this session.

Two fixes:

1. win-builder image gains node + wine32/wine64 (+ i386 arch). dist-win-docker.sh
   now runs BOTH the core cross-build and `npx electron-builder --win nsis`
   inside docker (USE_SYSTEM_WINE=true -> the image's wine). The wine prefix is
   initialized on first run in the shared cache volume, so syswow64/ntdll.dll
   exists - the exact thing the host lacked. The host needs no mingw/wine/node.

2. packaging/verify-dist.sh: a size-floor gate for GUI artifacts (exe >= 5 MB,
   deb/rpm/nsis.7z >= 10 MB). Wired into `make gui-dist` and `make gui-win-docker`
   and the dist-win-docker script, so a degenerate installer fails the build
   instead of reaching a Release. Verified: it rejects the 264 KB exe and passes
   the healthy artifacts.
This commit is contained in:
JianFeeeee
2026-08-30 10:49:45 +08:00
parent ed05cccb72
commit 3698546d14
2 changed files with 80 additions and 17 deletions

View File

@ -1,11 +1,20 @@
# ModelRouter GUI Windows builder
# Self-sufficient cross-compilation environment for the embedded llmsproxy core.
# Produces llmsproxy.exe (Go, windows/amd64, luajit tag) + lua51.dll (LuaJIT mingw build)
# inside a mounted workspace: cmd/gui/bin/{llmsproxy.exe,lua51.dll}
# Self-sufficient cross-compilation environment for the embedded llmsproxy core
# AND for packaging the Windows NSIS installer.
#
# Produces inside a mounted workspace:
# - llmsproxy.exe (Go, windows/amd64, luajit tag) + lua51.dll
# - ModelRouter Setup <ver>.exe (electron-builder --win nsis; requires wine
# so the uninstaller is generated — set USE_SYSTEM_WINE=true)
#
# Build: docker build -t modelrouter/win-builder cmd/gui/docker/win-builder
# Usage: make gui-win-docker (or cmd/gui/scripts/dist-win-docker.sh)
#
# This image is the SINGLE wine provider for the NSIS step, so a host that has
# no / broken wine (e.g. amd64-only Debian: no syswow64 -> c0000135) can still
# produce a real installer. The NSIS step MUST run inside this image; running it
# on the host was how the 1.3.0 264 KB degenerate exe got shipped.
#
# LuaJIT source is fetched from gitcode.com (CN-reachable mirror) with github
# fallback; pass --build-arg LUAJIT_REPO to override.
@ -13,11 +22,24 @@ FROM golang:1.25
ARG LUAJIT_REPO=https://gitcode.com/openresty/luajit2.git
RUN apt-get update -qq \
# i386 arch is required for wine32 (the NSIS uninstaller step runs a win32 exe
# through wine's wow64 path, which needs the 32-bit runtime under /usr/lib/i386).
RUN dpkg --add-architecture i386 \
&& apt-get update -qq \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y -qq \
gcc-mingw-w64-x86-64 make ca-certificates git \
# NSIS step needs node + the electron-builder toolchain
nodejs npm \
# wine (32+64) for generating the NSIS uninstaller
wine64 wine32:i386 \
&& rm -rf /var/lib/apt/lists/*
# electron-builder resolves the uninstaller via the system wine when
# USE_SYSTEM_WINE=true (or by default on Linux without a toolset). Pin it.
ENV USE_SYSTEM_WINE=true
ENV WINEDEBUG=-all
ENV ELECTRON_BUILDER_CACHE=/workspace/cmd/gui/.cache
# LuaJIT cross-compiled for Windows; keeps lua51.dll and the cgo import lib
# (libluajit-5.1.dll.a -> libluajit-5.1.a in the mingw lib dir).
# NOTE: $LUAJIT_REPO deliberately unquoted in "sh -c" — quoting the ARG would