|
@@ -0,0 +1,448 @@
|
|
|
|
|
+# smartbotic-vectorapi Packaging Implementation Plan (Plan 3 of 3)
|
|
|
|
|
+
|
|
|
|
|
+> **For agentic workers:** REQUIRED SUB-SKILL: superpowers:subagent-driven-development. Implement task-by-task. Steps use `- [ ]`. Backend + web UI are on `main` (pushed). The DB (`smartbotic-database` 2.3.x) is installed locally and published to `repository.smartbotics.ai`.
|
|
|
|
|
+
|
|
|
|
|
+**Goal:** Produce two Debian packages — `smartbotic-vectorapi` (the server binary + systemd unit + config conffile + `openapi.json`/`llms.txt`) and `smartbotic-vectorapi-webui` (the built React assets) — for **Debian 13 (trixie)** via Docker, plus a `--local` native build for dev/testing on this box, and publish via the existing `/data/smartbotics-deb-repo` flow.
|
|
|
|
|
+
|
|
|
|
|
+**Architecture:** Mirror `smartbotic-database/packaging` (the sibling project, `/usr` layout, dedicated system user, `Type=notify` unit) and `callerai/packaging` (separate `-webui` package, Docker base+build images, `dependencies.conf`). `packaging/build.sh` orchestrates: `--local` (native CMake build → `create-debs.sh` → `dist/local/`) and the default Docker Debian-13 build (`Dockerfile.base` + `Dockerfile.build` → `dist/debian13/`). The Debian-13 base image adds the smartbotics apt repo (auth from `/data/smartbotics-deb-repo/.env`) to install `libsmartbotic-db-client-dev` (2.3.x) and Node for the web UI build.
|
|
|
|
|
+
|
|
|
|
|
+**Layout produced by the packages:**
|
|
|
|
|
+- `/usr/bin/smartbotic-vectorapi`
|
|
|
|
|
+- `/etc/smartbotic-vectorapi/config.json` (dpkg conffile)
|
|
|
|
|
+- `/lib/systemd/system/smartbotic-vectorapi.service`
|
|
|
|
|
+- `/usr/share/smartbotic-vectorapi/{openapi.json,llms.txt}`
|
|
|
|
|
+- `/usr/share/smartbotic-vectorapi/webui/*` (the `-webui` package)
|
|
|
|
|
+- runtime: system user `smartbotic-vectorapi`, data dir `/var/lib/smartbotic-vectorapi`
|
|
|
|
|
+
|
|
|
|
|
+**Verification:** `--local` build → `dpkg -i` install → the service starts, logs a generated admin key once, `/healthz` + `/openapi.json` answer, and (with the `-webui` package) `/` serves the SPA. The Docker Debian-13 build produces the prod artifacts (best-effort here: needs Docker + repo creds; the local path is the hard gate).
|
|
|
|
|
+
|
|
|
|
|
+**Reference files (read them):** `/data/smartbotic-database/packaging/{build.sh,deb/create-debs.sh,deb/templates/control.server,deb/systemd/smartbotic-database.service,deb/scripts/server.postinst,Dockerfile.base,Dockerfile.build}` and `/data/callerai/packaging/{build.sh,deb/create-debs.sh,Dockerfile.base}`. `/data/smartbotics-deb-repo/scripts/{add-packages.sh,create-repo.sh,sync-repo.sh}` + `README.md`.
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## File structure
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+packaging/
|
|
|
|
|
+├── build.sh # orchestrator: --local + Docker debian13
|
|
|
|
|
+├── Dockerfile.base # debian:13 + build deps + smartbotics repo + node
|
|
|
|
|
+├── Dockerfile.build # builds the project + runs create-debs.sh
|
|
|
|
|
+├── deb/
|
|
|
|
|
+│ ├── create-debs.sh # builds the 2 .debs from a CMake build dir
|
|
|
|
|
+│ ├── templates/
|
|
|
|
|
+│ │ ├── control.server # smartbotic-vectorapi (amd64)
|
|
|
|
|
+│ │ └── control.webui # smartbotic-vectorapi-webui (all)
|
|
|
|
|
+│ ├── scripts/
|
|
|
|
|
+│ │ ├── server.postinst # create user, dirs, enable+start
|
|
|
|
|
+│ │ ├── server.prerm # stop on remove
|
|
|
|
|
+│ │ └── server.postrm # purge: remove data dir + user
|
|
|
|
|
+│ └── systemd/
|
|
|
|
|
+│ └── smartbotic-vectorapi.service
|
|
|
|
|
+config/config.json # already exists (minimal bootstrap conffile)
|
|
|
|
|
+VERSION # already 0.1.0
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Task P1: systemd unit, control templates, maintainer scripts
|
|
|
|
|
+
|
|
|
|
|
+**Files:** create `packaging/deb/systemd/smartbotic-vectorapi.service`, `packaging/deb/templates/control.server`, `packaging/deb/templates/control.webui`, `packaging/deb/scripts/server.postinst`, `server.prerm`, `server.postrm`.
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 1: `packaging/deb/systemd/smartbotic-vectorapi.service`**
|
|
|
|
|
+
|
|
|
|
|
+```ini
|
|
|
|
|
+[Unit]
|
|
|
|
|
+Description=Smartbotic VectorAPI Service
|
|
|
|
|
+Documentation=https://git.smartbotics.ai/fszontagh/smartbotic-vectorapi
|
|
|
|
|
+After=network-online.target smartbotic-database.service
|
|
|
|
|
+Wants=network-online.target
|
|
|
|
|
+
|
|
|
|
|
+[Service]
|
|
|
|
|
+# The binary calls sd_notify(READY=1) after the HTTP listener is up (when built
|
|
|
|
|
+# with libsystemd). Type=notify makes dependents block until we're actually
|
|
|
|
|
+# serving. If built without libsystemd, sd_notify is a no-op — in that case
|
|
|
|
|
+# change Type to "exec".
|
|
|
|
|
+Type=notify
|
|
|
|
|
+NotifyAccess=main
|
|
|
|
|
+User=smartbotic-vectorapi
|
|
|
|
|
+Group=smartbotic-vectorapi
|
|
|
|
|
+ExecStart=/usr/bin/smartbotic-vectorapi --config /etc/smartbotic-vectorapi/config.json
|
|
|
|
|
+Restart=on-failure
|
|
|
|
|
+RestartSec=3
|
|
|
|
|
+WorkingDirectory=/var/lib/smartbotic-vectorapi
|
|
|
|
|
+LimitNOFILE=65536
|
|
|
|
|
+
|
|
|
|
|
+# Secrets (optional): seed the admin key / OpenAI key on first boot.
|
|
|
|
|
+EnvironmentFile=-/etc/smartbotic-vectorapi/vectorapi.env
|
|
|
|
|
+
|
|
|
|
|
+# Security hardening (mirrors callerai-webapi). Outbound network is allowed
|
|
|
|
|
+# (needed for OpenAI embeddings); only writes to the data dir are permitted.
|
|
|
|
|
+NoNewPrivileges=true
|
|
|
|
|
+ProtectSystem=strict
|
|
|
|
|
+ProtectHome=true
|
|
|
|
|
+PrivateTmp=true
|
|
|
|
|
+PrivateDevices=true
|
|
|
|
|
+ProtectKernelTunables=true
|
|
|
|
|
+ProtectKernelModules=true
|
|
|
|
|
+ProtectControlGroups=true
|
|
|
|
|
+RestrictRealtime=true
|
|
|
|
|
+RestrictSUIDSGID=true
|
|
|
|
|
+RestrictNamespaces=true
|
|
|
|
|
+LockPersonality=true
|
|
|
|
|
+ReadWritePaths=/var/lib/smartbotic-vectorapi
|
|
|
|
|
+SystemCallFilter=@system-service
|
|
|
|
|
+SystemCallErrorNumber=EPERM
|
|
|
|
|
+
|
|
|
|
|
+[Install]
|
|
|
|
|
+WantedBy=multi-user.target
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 2: `packaging/deb/templates/control.server`**
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+Package: smartbotic-vectorapi
|
|
|
|
|
+Version: {{VERSION}}
|
|
|
|
|
+Architecture: amd64
|
|
|
|
|
+Maintainer: Ferenc Szontagh <ferenc.szontagh@smartbotics.ai>
|
|
|
|
|
+Description: Smartbotic VectorAPI — REST API for RAG vectors and JSON
|
|
|
|
|
+ General-purpose, client-agnostic REST API in front of smartbotic-database:
|
|
|
|
|
+ multi-project namespaces, multi-key per-project-grant authorization, OpenAI
|
|
|
|
|
+ embedding generation for RAG, similarity search, JSON document CRUD, and
|
|
|
|
|
+ DB-backed hot-reloaded settings. Primary client: n8n workflows.
|
|
|
|
|
+Homepage: https://smartbotics.ai
|
|
|
|
|
+Section: contrib/utils
|
|
|
|
|
+Priority: optional
|
|
|
|
|
+Depends: libsmartbotic-db-client (>= 2.3.0), libssl3t64, libsystemd0, libspdlog1.15
|
|
|
|
|
+Recommends: smartbotic-vectorapi-webui (= {{VERSION}})
|
|
|
|
|
+Installed-Size: {{INSTALLED_SIZE}}
|
|
|
|
|
+```
|
|
|
|
|
+> Note: gRPC/protobuf/abseil come transitively via `libsmartbotic-db-client`'s own Depends. The implementer MUST verify the binary's actual shared-lib needs with `ldd build/src/smartbotic-vectorapi | grep -iE 'not found'` (should be empty on a machine with the deps) and `ldd ... | grep -oE 'lib[a-z0-9_+-]+\.so[0-9.]*'` to confirm `libspdlog`'s exact soname on the build distro — adjust the `libspdlog1.15` token if the trixie soname differs. If spdlog turns out to be statically linked (header-only build), drop it from Depends.
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 3: `packaging/deb/templates/control.webui`**
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+Package: smartbotic-vectorapi-webui
|
|
|
|
|
+Version: {{VERSION}}
|
|
|
|
|
+Architecture: all
|
|
|
|
|
+Maintainer: Ferenc Szontagh <ferenc.szontagh@smartbotics.ai>
|
|
|
|
|
+Description: Smartbotic VectorAPI — web administration console
|
|
|
|
|
+ React-based admin console for smartbotic-vectorapi: login, project switching,
|
|
|
|
|
+ dashboard, collections, JSON document editor (Monaco, bundled offline), RAG
|
|
|
|
|
+ search tester, and project/key administration. Served by smartbotic-vectorapi.
|
|
|
|
|
+Homepage: https://smartbotics.ai
|
|
|
|
|
+Section: contrib/utils
|
|
|
|
|
+Priority: optional
|
|
|
|
|
+Depends: smartbotic-vectorapi (>= {{VERSION}})
|
|
|
|
|
+Installed-Size: {{INSTALLED_SIZE}}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 4: `packaging/deb/scripts/server.postinst`**
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+#!/bin/bash
|
|
|
|
|
+# postinst for smartbotic-vectorapi
|
|
|
|
|
+set -e
|
|
|
|
|
+
|
|
|
|
|
+CONFIG_FILE="/etc/smartbotic-vectorapi/config.json"
|
|
|
|
|
+DATA_DIR="/var/lib/smartbotic-vectorapi"
|
|
|
|
|
+
|
|
|
|
|
+case "$1" in
|
|
|
|
|
+ configure)
|
|
|
|
|
+ if ! getent group smartbotic-vectorapi >/dev/null 2>&1; then
|
|
|
|
|
+ addgroup --system smartbotic-vectorapi
|
|
|
|
|
+ fi
|
|
|
|
|
+ if ! getent passwd smartbotic-vectorapi >/dev/null 2>&1; then
|
|
|
|
|
+ adduser --system --ingroup smartbotic-vectorapi --home "$DATA_DIR" \
|
|
|
|
|
+ --shell /usr/sbin/nologin --gecos "Smartbotic VectorAPI Service" smartbotic-vectorapi
|
|
|
|
|
+ fi
|
|
|
|
|
+
|
|
|
|
|
+ install -d -o smartbotic-vectorapi -g smartbotic-vectorapi -m 0750 "$DATA_DIR"
|
|
|
|
|
+ install -d -o root -g smartbotic-vectorapi -m 0750 /etc/smartbotic-vectorapi
|
|
|
|
|
+ if [ -f "$CONFIG_FILE" ]; then
|
|
|
|
|
+ chown root:smartbotic-vectorapi "$CONFIG_FILE"
|
|
|
|
|
+ chmod 640 "$CONFIG_FILE"
|
|
|
|
|
+ fi
|
|
|
|
|
+
|
|
|
|
|
+ systemctl daemon-reload || true
|
|
|
|
|
+ if [ -z "$2" ]; then
|
|
|
|
|
+ systemctl enable smartbotic-vectorapi.service || true
|
|
|
|
|
+ systemctl start smartbotic-vectorapi.service || true
|
|
|
|
|
+ else
|
|
|
|
|
+ systemctl reset-failed smartbotic-vectorapi.service 2>/dev/null || true
|
|
|
|
|
+ systemctl restart smartbotic-vectorapi.service || true
|
|
|
|
|
+ fi
|
|
|
|
|
+ ;;
|
|
|
|
|
+ abort-upgrade|abort-remove|abort-deconfigure) ;;
|
|
|
|
|
+ *) echo "postinst called with unknown argument '$1'" >&2; exit 1 ;;
|
|
|
|
|
+esac
|
|
|
|
|
+exit 0
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 5: `packaging/deb/scripts/server.prerm`**
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+#!/bin/bash
|
|
|
|
|
+set -e
|
|
|
|
|
+case "$1" in
|
|
|
|
|
+ remove|deconfigure)
|
|
|
|
|
+ systemctl stop smartbotic-vectorapi.service 2>/dev/null || true
|
|
|
|
|
+ systemctl disable smartbotic-vectorapi.service 2>/dev/null || true
|
|
|
|
|
+ ;;
|
|
|
|
|
+ upgrade|failed-upgrade) ;;
|
|
|
|
|
+esac
|
|
|
|
|
+exit 0
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 6: `packaging/deb/scripts/server.postrm`**
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+#!/bin/bash
|
|
|
|
|
+set -e
|
|
|
|
|
+case "$1" in
|
|
|
|
|
+ purge)
|
|
|
|
|
+ rm -rf /var/lib/smartbotic-vectorapi
|
|
|
|
|
+ if getent passwd smartbotic-vectorapi >/dev/null 2>&1; then
|
|
|
|
|
+ deluser --system smartbotic-vectorapi 2>/dev/null || true
|
|
|
|
|
+ fi
|
|
|
|
|
+ if getent group smartbotic-vectorapi >/dev/null 2>&1; then
|
|
|
|
|
+ delgroup --system smartbotic-vectorapi 2>/dev/null || true
|
|
|
|
|
+ fi
|
|
|
|
|
+ ;;
|
|
|
|
|
+ remove|upgrade|disappear|failed-upgrade|abort-install|abort-upgrade) ;;
|
|
|
|
|
+esac
|
|
|
|
|
+systemctl daemon-reload 2>/dev/null || true
|
|
|
|
|
+exit 0
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 7: Commit** `build(pkg): systemd unit, control templates, maintainer scripts`
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Task P2: `create-debs.sh`
|
|
|
|
|
+
|
|
|
|
|
+**Files:** create `packaging/deb/create-debs.sh` (executable). Mirror `smartbotic-database/packaging/deb/create-debs.sh` (read it) — same helpers (`calc_installed_size`, `build_deb` with `sed` placeholder substitution + perms + `dpkg-deb --build --root-owner-group`), but produce TWO packages.
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 1: write `packaging/deb/create-debs.sh`**
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+#!/usr/bin/env bash
|
|
|
|
|
+# create-debs.sh — build the smartbotic-vectorapi + -webui .deb packages
|
|
|
|
|
+set -euo pipefail
|
|
|
|
|
+
|
|
|
|
|
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
|
+SOURCE_DIR="${SOURCE_DIR:-$(cd "$SCRIPT_DIR/../.." && pwd)}"
|
|
|
|
|
+BUILD_DIR="${BUILD_DIR:-$SOURCE_DIR/build}"
|
|
|
|
|
+OUTPUT_DIR="${OUTPUT_DIR:-$SOURCE_DIR/dist}"
|
|
|
|
|
+BUILD_DEB_REVISION="${BUILD_DEB_REVISION:-1}"
|
|
|
|
|
+
|
|
|
|
|
+TEMPLATE_DIR="$SCRIPT_DIR/templates"
|
|
|
|
|
+SCRIPTS_DIR="$SCRIPT_DIR/scripts"
|
|
|
|
|
+SYSTEMD_DIR="$SCRIPT_DIR/systemd"
|
|
|
|
|
+CONFIG_DIR="$SOURCE_DIR/config"
|
|
|
|
|
+API_DIR="$SOURCE_DIR/api"
|
|
|
|
|
+WEBUI_DIST="${WEBUI_DIST:-$BUILD_DIR/webui/dist}"
|
|
|
|
|
+
|
|
|
|
|
+VERSION="$(cat "$SOURCE_DIR/VERSION")"
|
|
|
|
|
+DEB_VERSION="${VERSION}-${BUILD_DEB_REVISION}"
|
|
|
|
|
+
|
|
|
|
|
+echo "=== smartbotic-vectorapi deb builder ==="
|
|
|
|
|
+echo "VERSION=$VERSION DEB_VERSION=$DEB_VERSION"
|
|
|
|
|
+echo "BUILD_DIR=$BUILD_DIR OUTPUT_DIR=$OUTPUT_DIR WEBUI_DIST=$WEBUI_DIST"
|
|
|
|
|
+mkdir -p "$OUTPUT_DIR"
|
|
|
|
|
+
|
|
|
|
|
+calc_installed_size() {
|
|
|
|
|
+ local staging_dir="$1" total=0
|
|
|
|
|
+ for d in "$staging_dir"/*/; do
|
|
|
|
|
+ [ "$(basename "$d")" = "DEBIAN" ] && continue
|
|
|
|
|
+ total=$(( total + $(du -sk "$d" | awk '{print $1}') ))
|
|
|
|
|
+ done
|
|
|
|
|
+ echo "$total"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+build_deb() {
|
|
|
|
|
+ local pkg_name="$1" staging_dir="$2" arch="$3"
|
|
|
|
|
+ local installed_size; installed_size="$(calc_installed_size "$staging_dir")"
|
|
|
|
|
+ sed -i -e "s/{{VERSION}}/${DEB_VERSION}/g" -e "s/{{INSTALLED_SIZE}}/${installed_size}/g" "$staging_dir/DEBIAN/control"
|
|
|
|
|
+ find "$staging_dir" -type d -exec chmod 0755 {} +
|
|
|
|
|
+ find "$staging_dir/DEBIAN" -type f -exec chmod 0644 {} +
|
|
|
|
|
+ for f in postinst prerm postrm preinst; do
|
|
|
|
|
+ [ -f "$staging_dir/DEBIAN/$f" ] && chmod 0755 "$staging_dir/DEBIAN/$f"
|
|
|
|
|
+ done
|
|
|
|
|
+ local deb_file="${OUTPUT_DIR}/${pkg_name}_${DEB_VERSION}_${arch}.deb"
|
|
|
|
|
+ dpkg-deb --build --root-owner-group "$staging_dir" "$deb_file"
|
|
|
|
|
+ echo " -> $deb_file"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+# ---- Package 1: smartbotic-vectorapi (server) ----
|
|
|
|
|
+echo "--- smartbotic-vectorapi ---"
|
|
|
|
|
+PKG1="$(mktemp -d)"; trap 'rm -rf "$PKG1"' EXIT
|
|
|
|
|
+mkdir -p "$PKG1/DEBIAN" "$PKG1/usr/bin" "$PKG1/etc/smartbotic-vectorapi" \
|
|
|
|
|
+ "$PKG1/lib/systemd/system" "$PKG1/usr/share/smartbotic-vectorapi"
|
|
|
|
|
+
|
|
|
|
|
+[ -f "$BUILD_DIR/src/smartbotic-vectorapi" ] || { echo "ERROR: binary not found at $BUILD_DIR/src/smartbotic-vectorapi" >&2; exit 1; }
|
|
|
|
|
+cp "$BUILD_DIR/src/smartbotic-vectorapi" "$PKG1/usr/bin/smartbotic-vectorapi"
|
|
|
|
|
+chmod 0755 "$PKG1/usr/bin/smartbotic-vectorapi"
|
|
|
|
|
+cp "$CONFIG_DIR/config.json" "$PKG1/etc/smartbotic-vectorapi/config.json"
|
|
|
|
|
+cp "$SYSTEMD_DIR/smartbotic-vectorapi.service" "$PKG1/lib/systemd/system/"
|
|
|
|
|
+cp "$API_DIR/openapi.json" "$API_DIR/llms.txt" "$PKG1/usr/share/smartbotic-vectorapi/"
|
|
|
|
|
+cp "$TEMPLATE_DIR/control.server" "$PKG1/DEBIAN/control"
|
|
|
|
|
+cp "$SCRIPTS_DIR/server.postinst" "$PKG1/DEBIAN/postinst"
|
|
|
|
|
+cp "$SCRIPTS_DIR/server.prerm" "$PKG1/DEBIAN/prerm"
|
|
|
|
|
+cp "$SCRIPTS_DIR/server.postrm" "$PKG1/DEBIAN/postrm"
|
|
|
|
|
+printf '/etc/smartbotic-vectorapi/config.json\n' > "$PKG1/DEBIAN/conffiles"
|
|
|
|
|
+build_deb "smartbotic-vectorapi" "$PKG1" "amd64"
|
|
|
|
|
+
|
|
|
|
|
+# ---- Package 2: smartbotic-vectorapi-webui (static assets) ----
|
|
|
|
|
+echo "--- smartbotic-vectorapi-webui ---"
|
|
|
|
|
+PKG2="$(mktemp -d)"; trap 'rm -rf "$PKG1" "$PKG2"' EXIT
|
|
|
|
|
+mkdir -p "$PKG2/DEBIAN" "$PKG2/usr/share/smartbotic-vectorapi/webui"
|
|
|
|
|
+if [ -d "$WEBUI_DIST" ] && [ -n "$(ls -A "$WEBUI_DIST" 2>/dev/null)" ]; then
|
|
|
|
|
+ cp -a "$WEBUI_DIST"/. "$PKG2/usr/share/smartbotic-vectorapi/webui/"
|
|
|
|
|
+else
|
|
|
|
|
+ echo "ERROR: webui dist not found at $WEBUI_DIST (build with -DBUILD_WEBUI=ON)" >&2; exit 1
|
|
|
|
|
+fi
|
|
|
|
|
+cp "$TEMPLATE_DIR/control.webui" "$PKG2/DEBIAN/control"
|
|
|
|
|
+build_deb "smartbotic-vectorapi-webui" "$PKG2" "all"
|
|
|
|
|
+
|
|
|
|
|
+echo "=== Done. Packages in $OUTPUT_DIR ==="
|
|
|
|
|
+ls -lh "$OUTPUT_DIR"/*.deb
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 2: Commit** `build(pkg): create-debs.sh (server + webui packages)`
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Task P3: `build.sh` + Dockerfiles
|
|
|
|
|
+
|
|
|
|
|
+**Files:** create `packaging/build.sh` (exec), `packaging/Dockerfile.base`, `packaging/Dockerfile.build`. Mirror `smartbotic-database/packaging/{build.sh,Dockerfile.base,Dockerfile.build}` (read them) and `callerai/packaging/Dockerfile.base` (for the apt-repo-add pattern).
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 1: `packaging/build.sh`** — same flag set/structure as `smartbotic-database/packaging/build.sh`: `--local` (native), `--install` (local only), `--deb-revision N`, `--rebuild-base`, `--no-cache`, `--repo`, `--suite NAME`, `--sync`.
|
|
|
|
|
+ - `build_local()`: `cmake -B "$PROJECT_DIR/build" -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_WEBUI=ON -DBUILD_TESTS=OFF -S "$PROJECT_DIR"` → `cmake --build` → `OUTPUT_DIR=dist/local BUILD_DEB_REVISION=$REV packaging/deb/create-debs.sh` → optional `--install` (`sudo dpkg -i dist/local/smartbotic-vectorapi_*.deb dist/local/smartbotic-vectorapi-webui_*.deb || sudo apt-get install -f -y`).
|
|
|
|
|
+ - `build_docker()`: build `Dockerfile.base` (tag `smartbotic-vectorapi-build-base:debian13`, passing `--build-arg REPO_USER=.. --build-arg REPO_PASS=..` read from `${DEB_REPO_DIR:-/data/smartbotics-deb-repo}/.env`), then `docker buildx build -f Dockerfile.build --build-arg BASE_IMAGE=... --build-arg BUILD_VERSION=$VERSION --build-arg BUILD_DEB_REVISION=$REV --target packages --output type=local,dest=dist/debian13 .`.
|
|
|
|
|
+ - repo ops (when `--repo`): call `$DEB_REPO_DIR/scripts/add-packages.sh "$OUTPUT_DIR"`, then `create-repo.sh --suite "$SUITE"`, then (if `--sync`) `sync-repo.sh`.
|
|
|
|
|
+ Base the script almost verbatim on `smartbotic-database/packaging/build.sh`, changing names and the cmake invocation (add `-DBUILD_WEBUI=ON -DBUILD_TESTS=OFF`) and the install package list (2 debs).
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 2: `packaging/Dockerfile.base`** (Debian 13 build base)
|
|
|
|
|
+
|
|
|
|
|
+```dockerfile
|
|
|
|
|
+FROM debian:13-slim
|
|
|
|
|
+
|
|
|
|
|
+ARG REPO_USER
|
|
|
|
|
+ARG REPO_PASS
|
|
|
|
|
+ENV DEBIAN_FRONTEND=noninteractive
|
|
|
|
|
+
|
|
|
|
|
+RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
|
|
|
+ ca-certificates curl gnupg cmake ninja-build g++ pkg-config \
|
|
|
|
|
+ nlohmann-json3-dev libspdlog-dev libssl-dev libsystemd-dev git \
|
|
|
|
|
+ && rm -rf /var/lib/apt/lists/*
|
|
|
|
|
+
|
|
|
|
|
+# Node 22 for the web UI build (vite 7 needs node >=20.19/22).
|
|
|
|
|
+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).
|
|
|
|
|
+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" \
|
|
|
|
|
+ > /etc/apt/auth.conf.d/smartbotics.conf \
|
|
|
|
|
+ && chmod 600 /etc/apt/auth.conf.d/smartbotics.conf \
|
|
|
|
|
+ && 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 \
|
|
|
|
|
+ && rm -rf /var/lib/apt/lists/*
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 3: `packaging/Dockerfile.build`**
|
|
|
|
|
+
|
|
|
|
|
+```dockerfile
|
|
|
|
|
+ARG BASE_IMAGE=smartbotic-vectorapi-build-base:debian13
|
|
|
|
|
+FROM ${BASE_IMAGE} AS builder
|
|
|
|
|
+ARG BUILD_VERSION=0.1.0
|
|
|
|
|
+ARG BUILD_DEB_REVISION=1
|
|
|
|
|
+WORKDIR /build
|
|
|
|
|
+COPY . /build/
|
|
|
|
|
+RUN cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_WEBUI=ON -DBUILD_TESTS=OFF -S . \
|
|
|
|
|
+ && cmake --build build -j"$(nproc)"
|
|
|
|
|
+RUN OUTPUT_DIR=/packages BUILD_DEB_REVISION=${BUILD_DEB_REVISION} packaging/deb/create-debs.sh
|
|
|
|
|
+
|
|
|
|
|
+FROM scratch AS packages
|
|
|
|
|
+COPY --from=builder /packages/*.deb /
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 4: Commit** `build(pkg): build.sh orchestrator + Debian-13 Docker base/build images`
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Task P4: Local build + install + service smoke (the hard gate)
|
|
|
|
|
+
|
|
|
|
|
+This runs on THIS machine (Ubuntu 26.04 → produces a dev/test deb; the prod artifact is the Docker/trixie build in P5). Requires sudo for install.
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 1: Local build of both debs**
|
|
|
|
|
+
|
|
|
|
|
+Run: `cd /data/smartbotic-vectorapi && ./packaging/build.sh --local`
|
|
|
|
|
+Expected: configures with `-DBUILD_WEBUI=ON`, builds the binary + webui dist, runs `create-debs.sh`, and emits `dist/local/smartbotic-vectorapi_0.1.0-1_amd64.deb` + `dist/local/smartbotic-vectorapi-webui_0.1.0-1_all.deb`.
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 2: Inspect the packages**
|
|
|
|
|
+
|
|
|
|
|
+Run: `dpkg-deb -I dist/local/smartbotic-vectorapi_*.deb && dpkg-deb -c dist/local/smartbotic-vectorapi_*.deb | grep -E 'bin/|etc/|systemd|share'` and the same `-c` for the `-webui` deb (should list `usr/share/smartbotic-vectorapi/webui/index.html` + assets incl. the monaco worker chunks). Confirm control Depends + conffiles look right.
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 3: Install + verify the service** (needs sudo — if sudo prompts in this env, the operator runs these via `! sudo ...`; otherwise run directly)
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+sudo dpkg -i dist/local/smartbotic-vectorapi_*.deb dist/local/smartbotic-vectorapi-webui_*.deb || sudo apt-get install -f -y
|
|
|
|
|
+systemctl status smartbotic-vectorapi --no-pager | head -8
|
|
|
|
|
+journalctl -u smartbotic-vectorapi --no-pager -n 20 | grep -i "Generated initial admin API key" || true # the one-time key
|
|
|
|
|
+curl -s localhost:8080/healthz; echo
|
|
|
|
|
+curl -s localhost:8080/openapi.json | head -c 60; echo
|
|
|
|
|
+curl -s -o /dev/null -w "SPA: %{http_code}\n" localhost:8080/ # webui package serves the SPA
|
|
|
|
|
+```
|
|
|
|
|
+Expected: service `active (running)`; the journal shows the generated admin key once; `/healthz` → `{"status":"ok"}`; `/openapi.json` starts with the spec; `/` → 200 (SPA from the `-webui` package). **Note:** the service's `--webui-dir` default is `/usr/share/smartbotic-vectorapi/webui` (compiled default), which the `-webui` package populates — confirm `config.json` / the binary default points there (it does: `Config::webuiDir` default). If the unit serves the SPA only when the webui package is installed, that's correct.
|
|
|
|
|
+
|
|
|
|
|
+> If `Type=notify` causes a startup timeout (binary built without libsystemd → never sends READY), edit the unit to `Type=exec` and document it. Verify the local binary has systemd: `ldd build/src/smartbotic-vectorapi | grep -i systemd` (should show libsystemd if HAVE_SYSTEMD).
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 4: Clean up the smoke** — `sudo apt-get remove -y smartbotic-vectorapi smartbotic-vectorapi-webui` (or leave installed for ongoing dev use; ask). Document outcome.
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 5: Commit** any fixes made during the smoke (e.g. unit `Type`, Depends soname). Message: `build(pkg): local deb build verified (install + service smoke)`.
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Task P5: Docker Debian-13 build (prod artifact)
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 1:** Ensure `.dockerignore` excludes `build/`, `webui/node_modules`, `dist/`, `.git` (create `/data/smartbotic-vectorapi/.dockerignore`).
|
|
|
|
|
+- [ ] **Step 2:** Run `cd /data/smartbotic-vectorapi && ./packaging/build.sh` (default = Docker Debian-13). It builds the base image (installing `libsmartbotic-db-client-dev` from `repository.smartbotics.ai` using creds from `/data/smartbotics-deb-repo/.env`) then the build image, emitting `dist/debian13/*.deb`.
|
|
|
|
|
+ - Expected: `dist/debian13/smartbotic-vectorapi_0.1.0-1_amd64.deb` + `..._webui_0.1.0-1_all.deb`, built against trixie's `libsmartbotic-db-client` 2.3.x and trixie shared-lib sonames.
|
|
|
|
|
+ - **If the smartbotics repo creds/connectivity aren't available in this environment**, this step is BLOCKED on infra (not code): report DONE_WITH_CONCERNS, having confirmed the Dockerfiles are correct by other means (e.g. `docker build` of the base up to the apt step). The `--local` debs from P4 remain the verified deliverable.
|
|
|
|
|
+- [ ] **Step 3:** Inspect: `dpkg-deb -I dist/debian13/smartbotic-vectorapi_*.deb` — confirm Depends resolved for trixie (esp. the `libspdlog` soname on trixie).
|
|
|
|
|
+- [ ] **Step 4: Commit** `build(pkg): Debian-13 Docker build produces prod debs`.
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Task P6: Publish to the smartbotics apt repository (operator step)
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 1:** Stage + sign + (optionally) upload:
|
|
|
|
|
+```bash
|
|
|
|
|
+cd /data/smartbotic-vectorapi
|
|
|
|
|
+./packaging/build.sh --repo --suite trixie # build (Docker) + add to repo + create-repo
|
|
|
|
|
+# or, to also upload:
|
|
|
|
|
+./packaging/build.sh --repo --suite trixie --sync
|
|
|
|
|
+```
|
|
|
|
|
+This calls `/data/smartbotics-deb-repo/scripts/{add-packages.sh,create-repo.sh --suite trixie,sync-repo.sh}`. Publishing uploads to `repository.smartbotics.ai` — an outward-facing action; only run with explicit operator confirmation.
|
|
|
|
|
+- [ ] **Step 2:** Verify on a client: `apt update && apt-cache policy smartbotic-vectorapi` shows the published version.
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Packaging definition of done
|
|
|
|
|
+
|
|
|
|
|
+- `./packaging/build.sh --local` produces both `.deb`s in `dist/local/`.
|
|
|
|
|
+- Installing them yields a running `smartbotic-vectorapi` service that logs a one-time admin key, answers `/healthz`+`/openapi.json`, and serves the SPA at `/`.
|
|
|
|
|
+- `./packaging/build.sh` (Docker) produces Debian-13 `.deb`s in `dist/debian13/` (or DONE_WITH_CONCERNS if repo creds are unavailable in-env).
|
|
|
|
|
+- The repo-publish path (`--repo --suite trixie [--sync]`) is wired to `/data/smartbotics-deb-repo` (run on operator confirmation).
|
|
|
|
|
+
|
|
|
|
|
+## Self-review
|
|
|
|
|
+
|
|
|
|
|
+**Coverage:** systemd unit + user + data dir (P1) · two packages server+webui (P1 control, P2 create-debs) · conffile config (P2) · openapi/llms shipped (P2) · orchestrator + Docker trixie (P3) · local verify (P4) · prod artifact (P5) · publish (P6). Mirrors `smartbotic-database` (/usr layout, Type=notify, system user) and `callerai` (separate -webui, Docker base+build, repo-add).
|
|
|
|
|
+
|
|
|
|
|
+**Risks flagged inline:** `libspdlog` soname may differ on trixie (verify via `ldd`/`dpkg-deb -I`); `Type=notify` requires the binary built with libsystemd (fallback `Type=exec`); Docker P5 depends on smartbotics-repo creds/connectivity; sudo install in P4 may need the operator.
|
|
|
|
|
+
|