Explorar o código

build: adapt build tooling to the zeus/Void dev host

The dev host moved from mulan to zeus, which runs Void Linux, and the repo
tree moved to /data/dev/<org>/<project>.

- build.sh: DEB_REPO_DIR defaults to the new deb-repo path, and --local now
  refuses to build .debs on a non-Debian host (it compiles and runs the tests
  instead, and rejects --install/--repo/--sync). A Void-linked package would
  not install on Debian 13; release packages come from the Docker path only.
  --skip-tests became real: --local builds and runs the suite by default.
- tests: fall back to FetchContent when the host has no system GoogleTest,
  so the suite configures on any distro. Debian images keep using libgtest-dev.
- WebUI.cmake: the bundle target depended only on node_modules, so editing a
  page never rebuilt the UI and the server kept serving a stale bundle. It now
  depends on the UI sources.
- Dockerfile.base: pin libsmartbotic-db-client-dev. Every 2.x client shares a
  SONAME, so a deb built against a newer client installs next to an older one
  on the target and only segfaults on the next restart.
fszontagh hai 1 semana
pai
achega
d3b6120b5e
Modificáronse 4 ficheiros con 140 adicións e 24 borrados
  1. 12 1
      cmake/WebUI.cmake
  2. 12 2
      packaging/Dockerfile.base
  3. 103 20
      packaging/build.sh
  4. 13 1
      tests/CMakeLists.txt

+ 12 - 1
cmake/WebUI.cmake

@@ -16,12 +16,23 @@ add_custom_command(
     COMMENT "webui: npm ci"
     VERBATIM)
 
+# Everything the bundle is built from. Without these as DEPENDS the output
+# already exists after the first build, so editing a page or component would
+# never rebuild the UI and the server would keep serving a stale bundle.
+file(GLOB_RECURSE WEBUI_SOURCES CONFIGURE_DEPENDS
+    "${WEBUI_SRC}/src/*"
+    "${WEBUI_SRC}/index.html"
+    "${WEBUI_SRC}/package.json"
+    "${WEBUI_SRC}/package-lock.json"
+    "${WEBUI_SRC}/vite.config.ts"
+    "${WEBUI_SRC}/tsconfig*.json")
+
 # Build the UI into the CMake build tree (outDir override).
 add_custom_command(
     OUTPUT "${WEBUI_DIST}/index.html"
     COMMAND ${NPM_EXECUTABLE} run build -- --outDir "${WEBUI_DIST}" --emptyOutDir
     WORKING_DIRECTORY "${WEBUI_SRC}"
-    DEPENDS "${WEBUI_SRC}/node_modules/.package-lock.json"
+    DEPENDS "${WEBUI_SRC}/node_modules/.package-lock.json" ${WEBUI_SOURCES}
     COMMENT "webui: npm run build -> ${WEBUI_DIST}"
     VERBATIM)
 

+ 12 - 2
packaging/Dockerfile.base

@@ -20,7 +20,15 @@ RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
     && apt-get install -y --no-install-recommends nodejs \
     && rm -rf /var/lib/apt/lists/*
 
-# Smartbotics apt repo — provides libsmartbotic-db-client-dev (2.3.x).
+# Smartbotics apt repo - provides libsmartbotic-db-client-dev.
+#
+# The client version is PINNED on purpose. vectorapi links
+# libsmartbotic-db-client.so, and every 2.x shares one SONAME, so a deb built
+# against a newer client installs happily next to an older one on the target and
+# only segfaults on the next service restart. Keep this equal to the client
+# version installed on the deploy target; when the target's DB moves, bump this
+# and ship both together.
+ARG DB_CLIENT_VERSION=2.11.1-1
 RUN curl -fsSL https://repository.smartbotics.ai/smartbotics-repo.gpg \
         | gpg --dearmor -o /usr/share/keyrings/smartbotics-repo.gpg \
     && printf 'machine repository.smartbotics.ai\nlogin %s\npassword %s\n' "$REPO_USER" "$REPO_PASS" \
@@ -29,5 +37,7 @@ RUN curl -fsSL https://repository.smartbotics.ai/smartbotics-repo.gpg \
     && echo "deb [signed-by=/usr/share/keyrings/smartbotics-repo.gpg] https://repository.smartbotics.ai trixie main" \
         > /etc/apt/sources.list.d/smartbotics.list \
     && apt-get update \
-    && apt-get install -y --no-install-recommends libsmartbotic-db-client-dev \
+    && apt-get install -y --no-install-recommends \
+        "libsmartbotic-db-client-dev=${DB_CLIENT_VERSION}" \
+        "libsmartbotic-db-client=${DB_CLIENT_VERSION}" \
     && rm -rf /var/lib/apt/lists/*

+ 103 - 20
packaging/build.sh

@@ -4,7 +4,10 @@
 #
 # Supports two modes:
 #   Default:  Docker build targeting Debian 13 (production .debs)
-#   --local:  Native build on current system (development/testing)
+#   --local:  Native build on current system (development/testing).
+#             .deb packaging only happens on a Debian-family host; elsewhere
+#             (e.g. Void Linux) it compiles and tests only - packages for
+#             release always come from the Docker/Debian-13 path.
 #
 set -euo pipefail
 
@@ -16,7 +19,7 @@ PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
 
 BASE_IMAGE_NAME="smartbotic-vectorapi-build-base:debian13"
 BUILD_JOBS="${BUILD_JOBS:-$(nproc)}"
-DEB_REPO_DIR="${DEB_REPO_DIR:-/data/smartbotics-deb-repo}"
+DEB_REPO_DIR="${DEB_REPO_DIR:-/data/dev/smartbotics/smartbotics-deb-repo}"
 
 # Output directories — separate to prevent local/Docker overwriting each other
 #   dist/local/    — native build for current system
@@ -38,6 +41,7 @@ NO_CACHE=0
 DO_REPO=0
 SUITE=""
 DO_SYNC=0
+MAKE_DEBS=1
 
 # ---------------------------------------------------------------------------
 # Colored logging
@@ -47,6 +51,28 @@ log_success() { printf '\033[1;32m[OK]\033[0m    %s\n' "$*"; }
 log_warn()    { printf '\033[1;33m[WARN]\033[0m  %s\n' "$*"; }
 log_error()   { printf '\033[1;31m[ERROR]\033[0m %s\n' "$*"; }
 
+# ---------------------------------------------------------------------------
+# Host detection
+# ---------------------------------------------------------------------------
+# .debs are only meaningful when produced on a Debian-family host: a package
+# linked against another distro's glibc/abseil/gRPC will not install (or will
+# crash-loop) on Debian 13. Everything we ship comes from the Docker path.
+host_is_debian() {
+    [[ -r /etc/os-release ]] || return 1
+    local ID="" ID_LIKE=""
+    # shellcheck disable=SC1091
+    . /etc/os-release
+    [[ "$ID" == "debian" || "$ID" == "ubuntu" || "$ID_LIKE" == *debian* ]]
+}
+
+host_name() {
+    if [[ -r /etc/os-release ]]; then
+        ( . /etc/os-release; echo "${PRETTY_NAME:-${NAME:-unknown}}" )
+    else
+        echo "unknown"
+    fi
+}
+
 # ---------------------------------------------------------------------------
 # Usage
 # ---------------------------------------------------------------------------
@@ -56,11 +82,13 @@ Usage: packaging/build.sh [OPTIONS]
 
 Build modes:
   (default)            Docker build targeting Debian 13 (production)
-  --local              Native build for current system (development)
+  --local              Native compile + tests for current system (development).
+                       Builds .debs only on a Debian-family host; on any other
+                       distro packaging is refused - use the Docker mode.
 
 Options:
-  --install            Install .debs locally after build (--local only)
-  --skip-tests         Skip running tests (no-op; tests disabled by default)
+  --install            Install .debs locally after build (--local, Debian host only)
+  --skip-tests         Skip building and running the test suite (--local only)
   --deb-revision N     Debian revision suffix (default: 1)
   --rebuild-base       Force rebuild Docker base image
   --no-cache           Build without Docker caches
@@ -70,7 +98,7 @@ Options:
 
 Environment variables:
   BUILD_JOBS           Parallel build jobs (default: nproc)
-  DEB_REPO_DIR         Path to smartbotics-deb-repo (default: /data/smartbotics-deb-repo)
+  DEB_REPO_DIR         Path to smartbotics-deb-repo (default: /data/dev/smartbotics/smartbotics-deb-repo)
 EOF
     exit 0
 }
@@ -112,6 +140,24 @@ if [[ $DO_REPO -eq 1 && -z "$SUITE" ]]; then
     exit 1
 fi
 
+# Native packaging is only allowed on a Debian-family host. On anything else
+# (Void Linux on zeus, for example) --local compiles and tests, but must not
+# emit .debs: they would be linked against the wrong libc/abseil/gRPC.
+if [[ $LOCAL_MODE -eq 1 ]] && ! host_is_debian; then
+    MAKE_DEBS=0
+    log_warn "Non-Debian host detected ($(host_name)): --local will compile and test only."
+    log_warn "Release packages must be built with the Docker mode: packaging/build.sh"
+
+    if [[ $INSTALL_AFTER -eq 1 ]]; then
+        log_error "--install needs .deb packages, which are not built on a non-Debian host."
+        exit 1
+    fi
+    if [[ $DO_REPO -eq 1 ]]; then
+        log_error "--repo/--sync need .deb packages; run the Docker mode (drop --local)."
+        exit 1
+    fi
+fi
+
 # ---------------------------------------------------------------------------
 # Set output directory based on mode
 # ---------------------------------------------------------------------------
@@ -120,7 +166,9 @@ if [[ $LOCAL_MODE -eq 1 ]]; then
 else
     OUTPUT_DIR="${DIST_BASE}/debian13"
 fi
-mkdir -p "$OUTPUT_DIR"
+if [[ $MAKE_DEBS -eq 1 ]]; then
+    mkdir -p "$OUTPUT_DIR"
+fi
 
 # ---------------------------------------------------------------------------
 # Banner
@@ -128,27 +176,48 @@ mkdir -p "$OUTPUT_DIR"
 log_info "smartbotic-vectorapi build v${VERSION} (${GIT_COMMIT})"
 log_info "Build jobs: ${BUILD_JOBS}"
 if [[ $LOCAL_MODE -eq 1 ]]; then
-    log_info "Mode: local (native)"
+    log_info "Mode: local (native, $(host_name))"
 else
     log_info "Mode: Docker (Debian 13)"
 fi
-log_info "Output: ${OUTPUT_DIR}"
+if [[ $MAKE_DEBS -eq 1 ]]; then
+    log_info "Output: ${OUTPUT_DIR}"
+else
+    log_info "Output: ${PROJECT_DIR}/build (no packages on this host)"
+fi
 
 # ---------------------------------------------------------------------------
 # Local build
 # ---------------------------------------------------------------------------
 build_local() {
-    log_info "Configuring CMake (Release)..."
+    local tests="ON"
+    if [[ $SKIP_TESTS -eq 1 ]]; then
+        tests="OFF"
+    fi
+
+    log_info "Configuring CMake (Release, BUILD_TESTS=${tests})..."
     cmake -B "$PROJECT_DIR/build" -G Ninja \
         -DCMAKE_BUILD_TYPE=Release \
         -DBUILD_WEBUI=ON \
-        -DBUILD_TESTS=OFF \
+        -DBUILD_TESTS="$tests" \
         -S "$PROJECT_DIR"
 
     log_info "Building with ${BUILD_JOBS} jobs..."
     cmake --build "$PROJECT_DIR/build" -j"$BUILD_JOBS"
     log_success "Build completed"
 
+    if [[ $tests == "ON" ]]; then
+        log_info "Running tests..."
+        # Integration tests GTEST_SKIP() when smartbotic-database is unreachable.
+        ctest --test-dir "$PROJECT_DIR/build" --output-on-failure
+        log_success "Tests passed"
+    fi
+
+    if [[ $MAKE_DEBS -eq 0 ]]; then
+        log_success "Native build verified: $PROJECT_DIR/build/src/smartbotic-vectorapi"
+        return 0
+    fi
+
     log_info "Creating .deb packages..."
     OUTPUT_DIR="$OUTPUT_DIR" BUILD_DEB_REVISION="$DEB_REVISION" "$PROJECT_DIR/packaging/deb/create-debs.sh"
     log_success "Packages created"
@@ -246,12 +315,14 @@ fi
 # ---------------------------------------------------------------------------
 # List created packages
 # ---------------------------------------------------------------------------
-echo ""
-log_info "Created packages:"
-ls -lh "$OUTPUT_DIR"/*.deb 2>/dev/null || {
-    log_error "No .deb files found in $OUTPUT_DIR"
-    exit 1
-}
+if [[ $MAKE_DEBS -eq 1 ]]; then
+    echo ""
+    log_info "Created packages:"
+    ls -lh "$OUTPUT_DIR"/*.deb 2>/dev/null || {
+        log_error "No .deb files found in $OUTPUT_DIR"
+        exit 1
+    }
+fi
 
 # ---------------------------------------------------------------------------
 # Repository operations
@@ -282,15 +353,27 @@ fi
 # Next steps
 # ---------------------------------------------------------------------------
 echo ""
-log_success "Build complete! (v${VERSION}-${DEB_REVISION})"
+if [[ $MAKE_DEBS -eq 1 ]]; then
+    log_success "Build complete! (v${VERSION}-${DEB_REVISION})"
+else
+    log_success "Native build complete! (v${VERSION}, ${GIT_COMMIT})"
+fi
 echo ""
-if [[ $LOCAL_MODE -eq 1 && $INSTALL_AFTER -eq 0 ]]; then
+if [[ $MAKE_DEBS -eq 0 ]]; then
+    log_info "To run the server in place:"
+    echo "  SMARTBOTIC_VECTORAPI_KEY=dev ${PROJECT_DIR}/build/src/smartbotic-vectorapi \\"
+    echo "    --config ${PROJECT_DIR}/config/config.json \\"
+    echo "    --share-dir ${PROJECT_DIR}/api \\"
+    echo "    --webui-dir ${PROJECT_DIR}/build/webui/dist"
+    echo ""
+fi
+if [[ $MAKE_DEBS -eq 1 && $LOCAL_MODE -eq 1 && $INSTALL_AFTER -eq 0 ]]; then
     log_info "To install locally:"
     echo "  sudo dpkg -i ${OUTPUT_DIR}/*.deb || sudo apt-get install -f -y"
     echo ""
 fi
 if [[ $DO_REPO -eq 0 ]]; then
-    log_info "To publish to repository:"
+    log_info "To build release packages and publish:"
     echo "  packaging/build.sh --repo --suite trixie"
     echo ""
 fi

+ 13 - 1
tests/CMakeLists.txt

@@ -1,4 +1,16 @@
-find_package(GTest REQUIRED)
+# Prefer a system GoogleTest (Debian build images ship libgtest-dev); fall back
+# to FetchContent so the test suite also configures on distros without it
+# (e.g. the Void Linux dev host).
+find_package(GTest QUIET)
+if(NOT GTest_FOUND)
+    message(STATUS "GTest not found on the system - fetching googletest")
+    include(FetchContent)
+    FetchContent_Declare(googletest
+        GIT_REPOSITORY https://github.com/google/googletest.git
+        GIT_TAG        v1.15.2)
+    set(INSTALL_GTEST OFF CACHE BOOL "" FORCE)
+    FetchContent_MakeAvailable(googletest)
+endif()
 include(GoogleTest)
 
 add_executable(test_smoke test_smoke.cpp)