| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- #!/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
|