build.sh 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #!/usr/bin/env bash
  2. # smartbotic-automation production build orchestrator.
  3. # Modeled on /data/shadowman-cpp/packaging/build.sh.
  4. #
  5. # Usage:
  6. # packaging/build.sh # Build with version from VERSION
  7. # packaging/build.sh 1.2.0 # Override version
  8. # packaging/build.sh --rebuild-base # Force rebuild of base image
  9. # packaging/build.sh --sync --suite trixie # Build + publish to APT repo
  10. set -euo pipefail
  11. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
  12. PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
  13. cd "$PROJECT_DIR"
  14. BASE_IMAGE_NAME="smartbotic-automation-build-base:debian13"
  15. OUTPUT_DIR="${PROJECT_DIR}/dist/debian13"
  16. BUILD_JOBS="${BUILD_JOBS:-$(nproc)}"
  17. DEB_REPO_DIR="${DEB_REPO_DIR:-/data/smartbotics-deb-repo}"
  18. RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m'
  19. log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
  20. log_success() { echo -e "${GREEN}[OK]${NC} $1"; }
  21. log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
  22. log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
  23. REBUILD_BASE=false
  24. NO_CACHE=false
  25. BUILD_REPO=false
  26. SYNC_REPO=false
  27. REPO_SUITE=""
  28. VERSION=""
  29. DEB_REVISION="1"
  30. while [[ $# -gt 0 ]]; do
  31. case $1 in
  32. --rebuild-base) REBUILD_BASE=true; shift ;;
  33. --no-cache) NO_CACHE=true; shift ;;
  34. --deb-revision) DEB_REVISION="$2"; shift 2 ;;
  35. --repo) BUILD_REPO=true; shift ;;
  36. --suite) REPO_SUITE="$2"; shift 2 ;;
  37. --sync) SYNC_REPO=true; BUILD_REPO=true; shift ;;
  38. --help|-h)
  39. cat <<EOF
  40. smartbotic-automation Production Build Script
  41. Usage: $0 [OPTIONS] [VERSION]
  42. Options:
  43. --rebuild-base Force rebuild the base image
  44. --no-cache Build without using BuildKit caches
  45. --deb-revision N Debian revision suffix (default: 1)
  46. --repo Generate APT repo from built packages
  47. --suite NAME Distribution suite for repo (e.g., trixie)
  48. --sync Generate repo and sync to repository.smartbotics.ai
  49. Environment:
  50. BUILD_JOBS Parallel build jobs (default: nproc)
  51. DEB_REPO_DIR Path to smartbotics-deb-repo (default: /data/smartbotics-deb-repo)
  52. EOF
  53. exit 0 ;;
  54. *) VERSION="$1"; shift ;;
  55. esac
  56. done
  57. if [ -z "$VERSION" ]; then
  58. VERSION="$(tr -d '[:space:]' < VERSION 2>/dev/null || true)"
  59. if [ -z "$VERSION" ]; then
  60. log_error "Could not read version from VERSION file"; exit 1
  61. fi
  62. fi
  63. if ! command -v docker &>/dev/null; then
  64. log_error "Docker not found in PATH"; exit 1
  65. fi
  66. base_image_exists() { docker image inspect "$BASE_IMAGE_NAME" &>/dev/null; }
  67. build_base_image() {
  68. log_info "Building base image: $BASE_IMAGE_NAME"
  69. local repo_pass=""
  70. if [ -f "${DEB_REPO_DIR}/.env" ]; then
  71. repo_pass=$(grep -oP 'RepoPass:\s*\K.*' "${DEB_REPO_DIR}/.env" | tr -d '[:space:]')
  72. fi
  73. if [ -z "$repo_pass" ]; then
  74. log_error "Could not read RepoPass from ${DEB_REPO_DIR}/.env"; exit 1
  75. fi
  76. docker buildx build \
  77. -f packaging/Dockerfile.base \
  78. --build-arg REPO_PASS="$repo_pass" \
  79. -t "$BASE_IMAGE_NAME" \
  80. .
  81. log_success "Base image built"
  82. }
  83. if $REBUILD_BASE; then
  84. build_base_image
  85. elif base_image_exists; then
  86. log_success "Base image cached: $BASE_IMAGE_NAME"
  87. else
  88. build_base_image
  89. fi
  90. GIT_COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo unknown)
  91. rm -rf "$OUTPUT_DIR"; mkdir -p "$OUTPUT_DIR"
  92. BUILD_ARGS=(
  93. -f packaging/Dockerfile.build
  94. --build-arg BASE_IMAGE="$BASE_IMAGE_NAME"
  95. --build-arg BUILD_VERSION="$VERSION"
  96. --build-arg BUILD_DEB_REVISION="$DEB_REVISION"
  97. --build-arg BUILD_GIT_COMMIT="$GIT_COMMIT"
  98. --build-arg BUILD_JOBS="$BUILD_JOBS"
  99. --target packages
  100. --output "type=local,dest=$OUTPUT_DIR"
  101. )
  102. $NO_CACHE && BUILD_ARGS+=(--no-cache)
  103. log_info "Building smartbotic-automation ${VERSION}-${DEB_REVISION} (commit ${GIT_COMMIT})"
  104. docker buildx build "${BUILD_ARGS[@]}" .
  105. log_success "Built packages:"
  106. ls -lh "$OUTPUT_DIR"/*.deb
  107. if $BUILD_REPO; then
  108. if [ -z "$REPO_SUITE" ]; then
  109. log_error "--suite is required with --repo"; exit 1
  110. fi
  111. if [ ! -d "$DEB_REPO_DIR" ]; then
  112. log_error "Repository dir not found: $DEB_REPO_DIR"; exit 1
  113. fi
  114. "$DEB_REPO_DIR/scripts/add-packages.sh" "$OUTPUT_DIR"
  115. "$DEB_REPO_DIR/scripts/create-repo.sh" --suite "$REPO_SUITE"
  116. fi
  117. if $SYNC_REPO; then
  118. "$DEB_REPO_DIR/scripts/sync-repo.sh"
  119. fi
  120. log_success "Done."