|
@@ -0,0 +1,285 @@
|
|
|
|
|
+#!/usr/bin/env bash
|
|
|
|
|
+#
|
|
|
|
|
+# packaging/build.sh — Top-level build orchestrator for smartbotic-database
|
|
|
|
|
+#
|
|
|
|
|
+# Supports two modes:
|
|
|
|
|
+# Default: Docker build targeting Debian 13 (production .debs)
|
|
|
|
|
+# --local: Native build on current system (development/testing)
|
|
|
|
|
+#
|
|
|
|
|
+set -euo pipefail
|
|
|
|
|
+
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+# Paths
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
|
+PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
|
+
|
|
|
|
|
+BASE_IMAGE_NAME="smartbotic-db-build-base:debian13"
|
|
|
|
|
+OUTPUT_DIR="${PROJECT_DIR}/dist"
|
|
|
|
|
+BUILD_JOBS="${BUILD_JOBS:-$(nproc)}"
|
|
|
|
|
+DEB_REPO_DIR="${DEB_REPO_DIR:-/data/smartbotics-deb-repo}"
|
|
|
|
|
+
|
|
|
|
|
+VERSION="$(cat "$PROJECT_DIR/VERSION")"
|
|
|
|
|
+GIT_COMMIT="$(git -C "$PROJECT_DIR" rev-parse --short HEAD 2>/dev/null || echo "unknown")"
|
|
|
|
|
+
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+# Defaults
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+LOCAL_MODE=0
|
|
|
|
|
+INSTALL_AFTER=0
|
|
|
|
|
+SKIP_TESTS=0
|
|
|
|
|
+DEB_REVISION=1
|
|
|
|
|
+REBUILD_BASE=0
|
|
|
|
|
+NO_CACHE=0
|
|
|
|
|
+DO_REPO=0
|
|
|
|
|
+SUITE=""
|
|
|
|
|
+DO_SYNC=0
|
|
|
|
|
+
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+# Colored logging
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+log_info() { printf '\033[1;34m[INFO]\033[0m %s\n' "$*"; }
|
|
|
|
|
+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' "$*"; }
|
|
|
|
|
+
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+# Usage
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+usage() {
|
|
|
|
|
+ cat <<EOF
|
|
|
|
|
+Usage: packaging/build.sh [OPTIONS]
|
|
|
|
|
+
|
|
|
|
|
+Build modes:
|
|
|
|
|
+ (default) Docker build targeting Debian 13 (production)
|
|
|
|
|
+ --local Native build for current system (development)
|
|
|
|
|
+
|
|
|
|
|
+Options:
|
|
|
|
|
+ --install Install .debs locally after build (--local only)
|
|
|
|
|
+ --skip-tests Skip running tests
|
|
|
|
|
+ --deb-revision N Debian revision suffix (default: 1)
|
|
|
|
|
+ --rebuild-base Force rebuild Docker base image
|
|
|
|
|
+ --no-cache Build without Docker caches
|
|
|
|
|
+ --repo Add packages to local APT repository
|
|
|
|
|
+ --suite NAME Distribution suite (e.g., trixie)
|
|
|
|
|
+ --sync Add to repo and upload to repository.smartbotics.ai
|
|
|
|
|
+
|
|
|
|
|
+Environment variables:
|
|
|
|
|
+ BUILD_JOBS Parallel build jobs (default: nproc)
|
|
|
|
|
+ DEB_REPO_DIR Path to smartbotics-deb-repo (default: /data/smartbotics-deb-repo)
|
|
|
|
|
+EOF
|
|
|
|
|
+ exit 0
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+# Argument parsing
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+while [[ $# -gt 0 ]]; do
|
|
|
|
|
+ case "$1" in
|
|
|
|
|
+ --local) LOCAL_MODE=1; shift ;;
|
|
|
|
|
+ --install) INSTALL_AFTER=1; shift ;;
|
|
|
|
|
+ --skip-tests) SKIP_TESTS=1; shift ;;
|
|
|
|
|
+ --deb-revision) DEB_REVISION="$2"; shift 2 ;;
|
|
|
|
|
+ --rebuild-base) REBUILD_BASE=1; shift ;;
|
|
|
|
|
+ --no-cache) NO_CACHE=1; shift ;;
|
|
|
|
|
+ --repo) DO_REPO=1; shift ;;
|
|
|
|
|
+ --suite) SUITE="$2"; shift 2 ;;
|
|
|
|
|
+ --sync) DO_SYNC=1; shift ;;
|
|
|
|
|
+ -h|--help) usage ;;
|
|
|
|
|
+ *)
|
|
|
|
|
+ log_error "Unknown option: $1"
|
|
|
|
|
+ usage
|
|
|
|
|
+ ;;
|
|
|
|
|
+ esac
|
|
|
|
|
+done
|
|
|
|
|
+
|
|
|
|
|
+# Validate option combinations
|
|
|
|
|
+if [[ $INSTALL_AFTER -eq 1 && $LOCAL_MODE -eq 0 ]]; then
|
|
|
|
|
+ log_error "--install is only supported with --local"
|
|
|
|
|
+ exit 1
|
|
|
|
|
+fi
|
|
|
|
|
+
|
|
|
|
|
+if [[ $DO_SYNC -eq 1 && $DO_REPO -eq 0 ]]; then
|
|
|
|
|
+ DO_REPO=1
|
|
|
|
|
+fi
|
|
|
|
|
+
|
|
|
|
|
+if [[ $DO_REPO -eq 1 && -z "$SUITE" ]]; then
|
|
|
|
|
+ log_error "--repo requires --suite NAME"
|
|
|
|
|
+ exit 1
|
|
|
|
|
+fi
|
|
|
|
|
+
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+# Banner
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+log_info "smartbotic-database build v${VERSION} (${GIT_COMMIT})"
|
|
|
|
|
+log_info "Build jobs: ${BUILD_JOBS}"
|
|
|
|
|
+if [[ $LOCAL_MODE -eq 1 ]]; then
|
|
|
|
|
+ log_info "Mode: local (native)"
|
|
|
|
|
+else
|
|
|
|
|
+ log_info "Mode: Docker (Debian 13)"
|
|
|
|
|
+fi
|
|
|
|
|
+
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+# Local build
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+build_local() {
|
|
|
|
|
+ log_info "Configuring CMake (Release)..."
|
|
|
|
|
+ cmake -B "$PROJECT_DIR/build" -G Ninja \
|
|
|
|
|
+ -DCMAKE_BUILD_TYPE=Release \
|
|
|
|
|
+ -DSMARTBOTIC_DB_BUILD_SERVICE=ON \
|
|
|
|
|
+ -DSMARTBOTIC_DB_BUILD_CLIENT=ON \
|
|
|
|
|
+ -DSMARTBOTIC_DB_BUILD_CLI=ON \
|
|
|
|
|
+ -DSMARTBOTIC_DB_BUILD_TESTS=ON \
|
|
|
|
|
+ -DBUILD_SHARED_LIBS=ON \
|
|
|
|
|
+ -S "$PROJECT_DIR"
|
|
|
|
|
+
|
|
|
|
|
+ log_info "Building with ${BUILD_JOBS} jobs..."
|
|
|
|
|
+ cmake --build "$PROJECT_DIR/build" -j"$BUILD_JOBS"
|
|
|
|
|
+ log_success "Build completed"
|
|
|
|
|
+
|
|
|
|
|
+ if [[ $SKIP_TESTS -eq 0 ]]; then
|
|
|
|
|
+ log_info "Running tests..."
|
|
|
|
|
+ LD_LIBRARY_PATH="$PROJECT_DIR/build/client" \
|
|
|
|
|
+ "$PROJECT_DIR/build/tests/test_vector_storage"
|
|
|
|
|
+ log_success "Tests passed"
|
|
|
|
|
+ else
|
|
|
|
|
+ log_warn "Tests skipped (--skip-tests)"
|
|
|
|
|
+ fi
|
|
|
|
|
+
|
|
|
|
|
+ log_info "Creating .deb packages..."
|
|
|
|
|
+ BUILD_DEB_REVISION="$DEB_REVISION" "$PROJECT_DIR/packaging/deb/create-debs.sh"
|
|
|
|
|
+ log_success "Packages created"
|
|
|
|
|
+
|
|
|
|
|
+ if [[ $INSTALL_AFTER -eq 1 ]]; then
|
|
|
|
|
+ log_info "Installing .deb packages..."
|
|
|
|
|
+ sudo dpkg -i \
|
|
|
|
|
+ "$OUTPUT_DIR"/libsmartbotic-db-client_*.deb \
|
|
|
|
|
+ "$OUTPUT_DIR"/libsmartbotic-db-client-dev_*.deb \
|
|
|
|
|
+ "$OUTPUT_DIR"/smartbotic-db-cli_*.deb \
|
|
|
|
|
+ "$OUTPUT_DIR"/smartbotic-database_*.deb \
|
|
|
|
|
+ 2>/dev/null || sudo apt-get install -f -y
|
|
|
|
|
+ log_success "Packages installed"
|
|
|
|
|
+ fi
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+# Docker build
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+build_docker() {
|
|
|
|
|
+ if ! command -v docker &>/dev/null; then
|
|
|
|
|
+ log_error "Docker is not installed or not in PATH"
|
|
|
|
|
+ exit 1
|
|
|
|
|
+ fi
|
|
|
|
|
+
|
|
|
|
|
+ # Check / build base image
|
|
|
|
|
+ if [[ $REBUILD_BASE -eq 1 ]] || ! docker image inspect "$BASE_IMAGE_NAME" &>/dev/null; then
|
|
|
|
|
+ if [[ $REBUILD_BASE -eq 1 ]]; then
|
|
|
|
|
+ log_info "Rebuilding base image (--rebuild-base)..."
|
|
|
|
|
+ else
|
|
|
|
|
+ log_info "Base image not found, building ${BASE_IMAGE_NAME}..."
|
|
|
|
|
+ fi
|
|
|
|
|
+
|
|
|
|
|
+ local base_cache_args=()
|
|
|
|
|
+ if [[ $NO_CACHE -eq 1 ]]; then
|
|
|
|
|
+ base_cache_args+=("--no-cache")
|
|
|
|
|
+ fi
|
|
|
|
|
+
|
|
|
|
|
+ docker buildx build \
|
|
|
|
|
+ -f "$PROJECT_DIR/packaging/Dockerfile.base" \
|
|
|
|
|
+ -t "$BASE_IMAGE_NAME" \
|
|
|
|
|
+ "${base_cache_args[@]+"${base_cache_args[@]}"}" \
|
|
|
|
|
+ "$PROJECT_DIR"
|
|
|
|
|
+ log_success "Base image built: ${BASE_IMAGE_NAME}"
|
|
|
|
|
+ else
|
|
|
|
|
+ log_info "Using existing base image: ${BASE_IMAGE_NAME}"
|
|
|
|
|
+ fi
|
|
|
|
|
+
|
|
|
|
|
+ # Build packages
|
|
|
|
|
+ log_info "Building packages in Docker..."
|
|
|
|
|
+ mkdir -p "$OUTPUT_DIR"
|
|
|
|
|
+
|
|
|
|
|
+ local build_cache_args=()
|
|
|
|
|
+ if [[ $NO_CACHE -eq 1 ]]; then
|
|
|
|
|
+ build_cache_args+=("--no-cache")
|
|
|
|
|
+ fi
|
|
|
|
|
+
|
|
|
|
|
+ docker buildx build \
|
|
|
|
|
+ -f "$PROJECT_DIR/packaging/Dockerfile.build" \
|
|
|
|
|
+ --build-arg "BASE_IMAGE=${BASE_IMAGE_NAME}" \
|
|
|
|
|
+ --build-arg "BUILD_VERSION=${VERSION}" \
|
|
|
|
|
+ --build-arg "BUILD_DEB_REVISION=${DEB_REVISION}" \
|
|
|
|
|
+ --build-arg "BUILD_JOBS=${BUILD_JOBS}" \
|
|
|
|
|
+ --build-arg "BUILD_GIT_COMMIT=${GIT_COMMIT}" \
|
|
|
|
|
+ --target packages \
|
|
|
|
|
+ --output "type=local,dest=$OUTPUT_DIR" \
|
|
|
|
|
+ "${build_cache_args[@]+"${build_cache_args[@]}"}" \
|
|
|
|
|
+ "$PROJECT_DIR"
|
|
|
|
|
+
|
|
|
|
|
+ log_success "Docker build completed"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+# Main
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+if [[ $LOCAL_MODE -eq 1 ]]; then
|
|
|
|
|
+ build_local
|
|
|
|
|
+else
|
|
|
|
|
+ build_docker
|
|
|
|
|
+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
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+# Repository operations
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+if [[ $DO_REPO -eq 1 ]]; then
|
|
|
|
|
+ echo ""
|
|
|
|
|
+ log_info "Adding packages to repository (suite: ${SUITE})..."
|
|
|
|
|
+
|
|
|
|
|
+ if [[ ! -x "$DEB_REPO_DIR/scripts/add-packages.sh" ]]; then
|
|
|
|
|
+ log_error "Repository tool not found: $DEB_REPO_DIR/scripts/add-packages.sh"
|
|
|
|
|
+ exit 1
|
|
|
|
|
+ fi
|
|
|
|
|
+
|
|
|
|
|
+ "$DEB_REPO_DIR/scripts/add-packages.sh" "$OUTPUT_DIR"
|
|
|
|
|
+ log_success "Packages added to staging"
|
|
|
|
|
+
|
|
|
|
|
+ "$DEB_REPO_DIR/scripts/create-repo.sh" --suite "$SUITE"
|
|
|
|
|
+ log_success "Repository created for suite: ${SUITE}"
|
|
|
|
|
+
|
|
|
|
|
+ if [[ $DO_SYNC -eq 1 ]]; then
|
|
|
|
|
+ log_info "Syncing repository to repository.smartbotics.ai..."
|
|
|
|
|
+ "$DEB_REPO_DIR/scripts/sync-repo.sh"
|
|
|
|
|
+ log_success "Repository synced"
|
|
|
|
|
+ fi
|
|
|
|
|
+fi
|
|
|
|
|
+
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+# Next steps
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+echo ""
|
|
|
|
|
+log_success "Build complete! (v${VERSION}-${DEB_REVISION})"
|
|
|
|
|
+echo ""
|
|
|
|
|
+if [[ $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:"
|
|
|
|
|
+ echo " packaging/build.sh --repo --suite trixie"
|
|
|
|
|
+ echo ""
|
|
|
|
|
+fi
|
|
|
|
|
+if [[ $DO_REPO -eq 1 && $DO_SYNC -eq 0 ]]; then
|
|
|
|
|
+ log_info "To sync repository to remote:"
|
|
|
|
|
+ echo " packaging/build.sh --repo --suite ${SUITE} --sync"
|
|
|
|
|
+ echo ""
|
|
|
|
|
+fi
|