#!/usr/bin/env bash # Build the llmsproxy CORE distribution packages (deb + rpm + tar.gz). # # Unlike the GUI packages (Electron), the core is a single static-ish binary # that server admins install with dpkg/rpm. The systemd unit bakes in the # memory tuning (GOGC=50, MALLOC_ARENA_MAX=2) measured on the production box. # # Requires: go, nfpm (PATH), dpkg-deb/rpmbuild for verification # Outputs: cmd/build/dist/llmsproxy__amd64.deb # cmd/build/dist/llmsproxy-.x86_64.rpm # cmd/build/dist/llmsproxy--linux-amd64.tar.gz set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$ROOT" VERSION="${1:-$(git describe --tags --dirty 2>/dev/null | sed 's/^v//' || echo 0.1.0)}" DIST="$ROOT/cmd/build/dist" BUILD_BIN="$ROOT/cmd/build/llmsproxy" log() { printf '\033[1;34m[core-dist]\033[0m %s\n' "$*"; } # nfpm is installed via `go install` -> lives in GOPATH/bin, which may not be # on the caller's PATH (non-interactive shells, cron). Resolve it explicitly. NFPM_BIN="$(command -v nfpm || true)" [ -z "$NFPM_BIN" ] && [ -n "$(go env GOPATH)" ] && { [ -x "$(go env GOPATH)/bin/nfpm" ] && NFPM_BIN="$(go env GOPATH)/bin/nfpm" } [ -n "$NFPM_BIN" ] || { echo "[core-dist] nfpm missing. Install: go install github.com/goreleaser/nfpm/v2/cmd/nfpm@v2.41.2" exit 1 } mkdir -p "$DIST" # 1) build the core binary (luajit tag, -s -w like deploy.sh) log "building core binary (luajit, stripped)..." CGO_ENABLED=1 go build -tags luajit -trimpath -ldflags="-s -w" -o "$BUILD_BIN" ./cmd/llmsproxy # 2) sanity gates: binary must contain the expected symbols and not be degenerate. # NOTE under `set -o pipefail`, `strings | grep -q` is BROKEN: grep -q exits # on first hit and closes the pipe, strings gets SIGPIPE -> pipeline returns # 141 -> the check spuriously fails. Stage strings output in a temp file. SYMS_TMP="$(mktemp)" strings "$BUILD_BIN" > "$SYMS_TMP" for sym in ProbeSlots reqRing shrinkStepLocked mergeUsage; do grep -qF "$sym" "$SYMS_TMP" || { echo "[core-dist] FATAL: binary missing expected symbol '$sym'"; rm -f "$SYMS_TMP"; exit 1 } done rm -f "$SYMS_TMP" [ "$(stat -c%s "$BUILD_BIN")" -gt 5000000 ] || { echo "[core-dist] FATAL: core binary implausibly small"; exit 1 } log " ok: $(stat -c%s "$BUILD_BIN") bytes, symbols present" # 3) deb + rpm via nfpm. nfpm v2 here does not render {{ .Env.VERSION }}, so # stamp the version into a throwaway copy of the config; -t places the # generated package in the dist dir. log "packaging deb + rpm (v$VERSION)..." NFPM_CFG="$(mktemp)" && sed "s/__VERSION__/$VERSION/g" "$ROOT/packaging/nfpm.yaml" > "$NFPM_CFG" "$NFPM_BIN" package --config "$NFPM_CFG" --packager deb -t "$DIST" "$NFPM_BIN" package --config "$NFPM_CFG" --packager rpm -t "$DIST" rm -f "$NFPM_CFG" # 4) tar.gz log "packaging tar.gz..." TAR_DIR="$DIST/llmsproxy-$VERSION-linux-amd64" rm -rf "$TAR_DIR"; mkdir -p "$TAR_DIR" cp "$BUILD_BIN" "$TAR_DIR/llmsproxy" cp "$ROOT/config.yaml" "$TAR_DIR/config.example.yaml" cp "$ROOT/packaging/llmsproxy.service" "$TAR_DIR/llmsproxy.service" mkdir -p "$TAR_DIR/adapters" cp "$ROOT"/internal/lua/adapters/*.lua "$TAR_DIR/adapters/" tar -C "$DIST" -czf "$DIST/llmsproxy-$VERSION-linux-amd64.tar.gz" \ "$(basename "$TAR_DIR")" rm -rf "$TAR_DIR" # 5) verify artifacts are healthy (the same gate that would have caught the # 264KB exe fiasco) log "verifying packages..." for f in "$DIST"/llmsproxy_*.deb "$DIST"/llmsproxy-*.rpm "$DIST"/*.tar.gz; do [ -f "$f" ] || continue sz=$(stat -c%s "$f") [ "$sz" -gt 100000 ] || { echo "[core-dist] FATAL: $f suspiciously small ($sz B)"; exit 1; } log " ✓ $f ($((sz/1024)) KB)" done dpkg-deb -I "$DIST"/llmsproxy_*.deb 2>/dev/null | grep -E 'Package|Version' | head -2 log "done: $DIST"