build.sh 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. #!/bin/bash
  2. #
  3. # Smartbotic Production Build Script
  4. #
  5. # This script handles the Docker build workflow:
  6. # 1. Checks if the pre-built base image exists
  7. # 2. Creates it if needed
  8. # 3. Builds production packages using the base image
  9. #
  10. # Usage:
  11. # ./packaging/build.sh # Build with auto-detected version
  12. # ./packaging/build.sh 0.1.0 # Build with specific version
  13. # ./packaging/build.sh --rebuild-base # Force rebuild the base image
  14. #
  15. set -e
  16. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
  17. PROJECT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
  18. cd "$PROJECT_DIR"
  19. # Configuration
  20. BASE_IMAGE_NAME="smartbotic-build-base:debian13"
  21. OUTPUT_DIR="${PROJECT_DIR}/dist"
  22. BUILD_JOBS="${BUILD_JOBS:-16}"
  23. # Colors for output
  24. RED='\033[0;31m'
  25. GREEN='\033[0;32m'
  26. YELLOW='\033[1;33m'
  27. BLUE='\033[0;34m'
  28. NC='\033[0m' # No Color
  29. log_info() {
  30. echo -e "${BLUE}[INFO]${NC} $1"
  31. }
  32. log_success() {
  33. echo -e "${GREEN}[OK]${NC} $1"
  34. }
  35. log_warn() {
  36. echo -e "${YELLOW}[WARN]${NC} $1"
  37. }
  38. log_error() {
  39. echo -e "${RED}[ERROR]${NC} $1"
  40. }
  41. # Parse arguments
  42. REBUILD_BASE=false
  43. CLEAR_CACHE=false
  44. NO_CACHE=false
  45. VERSION=""
  46. while [[ $# -gt 0 ]]; do
  47. case $1 in
  48. --rebuild-base)
  49. REBUILD_BASE=true
  50. shift
  51. ;;
  52. --clear-cache)
  53. CLEAR_CACHE=true
  54. shift
  55. ;;
  56. --no-cache)
  57. NO_CACHE=true
  58. shift
  59. ;;
  60. --help|-h)
  61. echo "Smartbotic Production Build Script"
  62. echo ""
  63. echo "Usage: $0 [OPTIONS] [VERSION]"
  64. echo ""
  65. echo "Options:"
  66. echo " --rebuild-base Force rebuild the base image"
  67. echo " --clear-cache Clear BuildKit build caches (ccache, npm)"
  68. echo " --no-cache Build without using caches"
  69. echo " --help, -h Show this help message"
  70. echo ""
  71. echo "Arguments:"
  72. echo " VERSION Version string (default: auto-detect from CMakeLists.txt)"
  73. echo ""
  74. echo "Environment variables:"
  75. echo " BUILD_JOBS Number of parallel build jobs (default: 16)"
  76. echo ""
  77. echo "Examples:"
  78. echo " $0 # Build with auto-detected version"
  79. echo " $0 0.1.0 # Build version 0.1.0"
  80. echo " $0 --rebuild-base # Rebuild base image and build packages"
  81. echo " $0 --clear-cache # Clear caches and build fresh"
  82. exit 0
  83. ;;
  84. *)
  85. VERSION="$1"
  86. shift
  87. ;;
  88. esac
  89. done
  90. # Auto-detect version if not specified
  91. if [ -z "$VERSION" ]; then
  92. VERSION=$(grep -oP 'project\(smartbotic-microbit VERSION \K[0-9.]+' CMakeLists.txt)
  93. if [ -z "$VERSION" ]; then
  94. log_error "Could not detect version from CMakeLists.txt"
  95. exit 1
  96. fi
  97. fi
  98. log_info "Smartbotic Build Script"
  99. log_info "Version: $VERSION"
  100. log_info "Output directory: $OUTPUT_DIR"
  101. echo ""
  102. # Check if Docker is available
  103. if ! command -v docker &> /dev/null; then
  104. log_error "Docker is not installed or not in PATH"
  105. exit 1
  106. fi
  107. # Check if base image exists
  108. base_image_exists() {
  109. docker image inspect "$BASE_IMAGE_NAME" &> /dev/null
  110. }
  111. # Build base image
  112. build_base_image() {
  113. log_info "Building base image: $BASE_IMAGE_NAME"
  114. log_info "This may take several minutes on first run..."
  115. echo ""
  116. docker buildx build \
  117. -f packaging/Dockerfile.base \
  118. -t "$BASE_IMAGE_NAME" \
  119. .
  120. log_success "Base image built successfully"
  121. echo ""
  122. }
  123. # Build production packages
  124. build_packages() {
  125. log_info "Building production packages..."
  126. log_info "Using base image: $BASE_IMAGE_NAME"
  127. log_info "Build jobs: $BUILD_JOBS"
  128. if [ "$NO_CACHE" = true ]; then
  129. log_warn "Building without caches (--no-cache)"
  130. else
  131. log_info "Using ccache and npm cache for faster builds"
  132. fi
  133. echo ""
  134. # Get git info
  135. GIT_COMMIT=$(git rev-parse HEAD 2>/dev/null || echo "unknown")
  136. GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
  137. log_info "Git commit: $GIT_COMMIT"
  138. log_info "Git branch: $GIT_BRANCH"
  139. echo ""
  140. # Clean output directory
  141. rm -rf "$OUTPUT_DIR"
  142. mkdir -p "$OUTPUT_DIR"
  143. # Build arguments
  144. BUILD_ARGS=(
  145. -f packaging/Dockerfile.build
  146. --build-arg BASE_IMAGE="$BASE_IMAGE_NAME"
  147. --build-arg BUILD_VERSION="$VERSION"
  148. --build-arg BUILD_GIT_COMMIT="$GIT_COMMIT"
  149. --build-arg BUILD_GIT_BRANCH="$GIT_BRANCH"
  150. --build-arg BUILD_JOBS="$BUILD_JOBS"
  151. --target packages
  152. --output "type=local,dest=$OUTPUT_DIR"
  153. )
  154. # Add --no-cache if requested
  155. if [ "$NO_CACHE" = true ]; then
  156. BUILD_ARGS+=(--no-cache)
  157. fi
  158. # Build packages
  159. docker buildx build "${BUILD_ARGS[@]}" .
  160. log_success "Packages built successfully"
  161. echo ""
  162. }
  163. # Clear build caches
  164. clear_build_cache() {
  165. log_info "Clearing BuildKit build caches..."
  166. docker builder prune --filter type=exec.cachemount -f
  167. log_success "Build caches cleared"
  168. echo ""
  169. }
  170. # Main flow
  171. echo "=================================================="
  172. echo " Smartbotic Production Build"
  173. echo " Version: $VERSION"
  174. echo "=================================================="
  175. echo ""
  176. # Clear cache if requested
  177. if [ "$CLEAR_CACHE" = true ]; then
  178. clear_build_cache
  179. fi
  180. # Check/build base image
  181. if [ "$REBUILD_BASE" = true ]; then
  182. log_warn "Force rebuilding base image..."
  183. build_base_image
  184. elif base_image_exists; then
  185. log_success "Base image found: $BASE_IMAGE_NAME"
  186. else
  187. log_warn "Base image not found, building..."
  188. build_base_image
  189. fi
  190. # Build packages
  191. build_packages
  192. # List created packages
  193. echo "=================================================="
  194. echo " Build Complete"
  195. echo "=================================================="
  196. echo ""
  197. log_info "Created packages in $OUTPUT_DIR:"
  198. echo ""
  199. ls -lh "$OUTPUT_DIR"/*.tar.gz 2>/dev/null | while read line; do
  200. echo " $line"
  201. done
  202. echo ""
  203. # Calculate total size
  204. TOTAL_SIZE=$(du -sh "$OUTPUT_DIR" | cut -f1)
  205. log_info "Total size: $TOTAL_SIZE"
  206. echo ""
  207. # Show cache info
  208. echo "=================================================="
  209. echo " Build Cache Info"
  210. echo "=================================================="
  211. echo ""
  212. log_info "BuildKit caches (ccache, npm) are stored persistently."
  213. log_info "Subsequent builds will be faster due to compilation caching."
  214. echo ""
  215. log_info "Cache management commands:"
  216. echo " $0 --clear-cache # Clear all build caches"
  217. echo " $0 --no-cache # Build without using caches"
  218. echo ""
  219. log_success "Build completed successfully!"
  220. echo ""
  221. echo "To deploy to production:"
  222. echo " scp dist/*.tar.gz root@<server>:/tmp/smartbotic-update/"
  223. echo " ssh root@<server> '/opt/smartbotic/bin/smartbotic-update --rolling --backup /tmp/smartbotic-update/'"
  224. echo ""