diff --git a/packaging/core-dist.sh b/packaging/core-dist.sh index 5445fc4..3013480 100755 --- a/packaging/core-dist.sh +++ b/packaging/core-dist.sh @@ -77,6 +77,21 @@ cp "$ROOT/packaging/config.example.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/" + +# The shipped plugins go into the archive too, not just into the binary's +# embedded FS. +# +# Seeding works without them (internal/lua/vm.go embeds plugins/*.lua and +# writeBundledPlugins materialises them on first start — verified: a fresh +# plugin_dir gains billing.lua, 70031 bytes, and the plugin loads), so this is +# not a functional fix. It is a contents/claim mismatch: the v1.8.0 release +# notes tell the operator the billing plugin ships with the core, and this +# archive — the artefact they unpack and inspect — did not contain it. Shipping +# the file also means an operator can read and adapt it before installing, +# instead of only discovering it after the first boot writes it out. +mkdir -p "$TAR_DIR/plugins" +cp "$ROOT"/internal/lua/plugins/*.lua "$TAR_DIR/plugins/" + tar -C "$DIST" -czf "$DIST/llmsproxy-$VERSION-linux-amd64.tar.gz" \ "$(basename "$TAR_DIR")" rm -rf "$TAR_DIR" @@ -90,6 +105,45 @@ for f in "$DIST"/llmsproxy_*.deb "$DIST"/llmsproxy-*.rpm "$DIST"/*.tar.gz; do [ "$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 +# dpkg-deb takes ONE archive; every extra argument is read as an additional +# control-component name. With the glob unquoted this used to expand to three +# .deb files (1.5.9 / 1.6.0 / the one just built) and dpkg-deb exited 2 — under +# `set -e` that aborted the script right here, so the "done" line never printed +# and NO content verification below ever ran. The size gate above was the only +# check that ever executed. Pick the newest deb explicitly. +newest_deb=$(ls -t "$DIST"/llmsproxy_*.deb 2>/dev/null | head -1 || true) +if [ -n "$newest_deb" ]; then + dpkg-deb -I "$newest_deb" 2>/dev/null | grep -E 'Package|Version' | head -2 || true +fi + +# 6) the archive must actually carry what the release notes promise. +# +# A size floor alone cannot catch this: a tar.gz missing all 70KB of plugins +# still clears the 100KB threshold easily, and the seeded-on-first-boot +# behaviour hides it at runtime — the operator sees a working billing plugin and +# concludes the package is complete. Assert the file is in the archive. +log "verifying archive contents..." +TARBALL="$DIST/llmsproxy-$VERSION-linux-amd64.tar.gz" +[ -f "$TARBALL" ] || { echo "[core-dist] FATAL: $TARBALL missing"; exit 1; } +listing=$(tar tzf "$TARBALL" 2>/dev/null || true) +[ -n "$listing" ] || { echo "[core-dist] FATAL: cannot list $TARBALL"; exit 1; } +for want in llmsproxy config.example.yaml llmsproxy.service plugins/billing.lua; do + if ! printf '%s\n' "$listing" | grep -q "/$want\$"; then + echo "[core-dist] FATAL: archive is missing $want" + echo " (release notes claim the billing plugin ships with the core)" + exit 1 + fi + log " ✓ archive contains $want" +done +# Directories are matched by their CONTENTS, not by name: tar written with +# `tar -czf` from a populated tree lists "…/adapters/openai.lua" and never a bare +# "…/adapters" entry, so an earlier version of this check that grepped for +# "/adapters$" reported a complete archive as broken. +n_adapters=$(printf '%s\n' "$listing" | grep -c "/adapters/.*\.lua\$" || true) +if [ "$n_adapters" -lt 10 ]; then + echo "[core-dist] FATAL: archive has only $n_adapters adapters (expected >= 10)" + exit 1 +fi +log " ✓ archive contains $n_adapters adapters" log "done: $DIST" \ No newline at end of file