#!/bin/bash set -e TAG="" REMOTE_HOST="erpnext.lasthourhosting.org" REMOTE_USER="root" MIGRATE=false BUILD_ONLY=false ALREADY_EXISTING=false while [[ $# -gt 0 ]]; do case "$1" in --tag) if [[ -z "${2:-}" ]]; then echo "Error: --tag requires a value" echo "Usage: $0 [--tag ] [--remote-host ] [--remote-user ]" exit 1 fi TAG="$2" shift 2 ;; --migrate) MIGRATE=true shift 1 ;; --remote-host) if [[ -z "${2:-}" ]]; then echo "Error: --remote-host requires a value" echo "Usage: $0 [--tag ] [--remote-host ] [--remote-user ]" exit 1 fi REMOTE_HOST="$2" shift 2 ;; --remote-user) if [[ -z "${2:-}" ]]; then echo "Error: --remote-user requires a value" echo "Usage: $0 [--tag ] [--remote-host ] [--remote-user ]" exit 1 fi REMOTE_USER="$2" shift 2 ;; -h|--help) echo "Usage: $0 --tag [OPTIONS]" echo "" echo "Automated Build & Deploy Script for Brotherton Frappe Docker" echo "--------------------------------------------------------" echo "" echo "description:" echo " This script orchestrates the full deployment pipeline. It first validates that" echo " the requested tag does not already exist locally, remotely, or in the registry." echo " It then builds the Docker image, pushes it to the registry, and triggers the" echo " remote deployment script." echo "" echo "Remote Deployment Actions (executed on server via re-deploy.sh):" echo " 1. Updates 'frappe-compose.yml' with the new image tag (preserves backup)." echo " 2. Restarts containers to load the new image." echo " 3. Runs 'bench migrate' (only if --migrate is passed)." echo " 4. Compiles assets via 'bench build' and 'bench build-frontend'." echo " 5. cleanup: Removes old images (Patch Version - 2) to save space." echo " 6. RECOVERY: If any step fails, it automatically rolls back config and containers." echo "" echo "Options:" echo " --tag REQUIRED. Version tag for the image (e.g., 1.0.0)." echo " --migrate Run 'bench migrate' on the remote server." echo " --build-only Build and push only; skip remote deployment checks & action." echo " --remote-host Target server (Default: $REMOTE_HOST)." echo " --remote-user SSH User (Default: $REMOTE_USER)." echo " -h, --help Show this help message." echo "" exit 0 ;; --build-only) BUILD_ONLY=true shift 1 ;; *) echo "Usage: $0 [--tag ] [--remote-host ] [--remote-user ]" exit 1 ;; esac done if [[ -z "$TAG" ]]; then echo "Error: --tag is required" echo "Usage: $0 [--tag ] [--remote-host ] [--remote-user ]" exit 1 fi cleanup() { set +e echo "🚨 Build failed! Starting cleanup..." IMAGE_NAME="githaven.org/shiloh/brotherton_frappe_docker:$TAG" # Local cleanup if docker image inspect "$IMAGE_NAME" >/dev/null 2>&1; then echo "🗑️ Removing local image $IMAGE_NAME..." docker rmi -f "$IMAGE_NAME" else echo "Local image $IMAGE_NAME not found." fi # Remote cleanup echo "Checking remote registry for $IMAGE_NAME..." if skopeo inspect "docker://$IMAGE_NAME" >/dev/null 2>&1; then echo "🗑️ Removing remote image $IMAGE_NAME..." skopeo delete "docker://$IMAGE_NAME" else echo "Remote image $IMAGE_NAME not found." fi } echo "" echo "+-----------------------------------------------+" echo " ██████╗ ██╗ ██╗██╗██╗ ██████╗ ██╗ ██╗" echo " ██╔════╝ ██║ ██║██║██║ ██╔═══██╗██║ ██║" echo " ╚█████╗ ███████║██║██║ ██║ ██║███████║" echo " ╚═══██╗ ██╔══██║██║██║ ██║ ██║██╔══██║" echo " ██████╔╝ ██║ ██║██║███████╗╚██████╔╝██║ ██║" echo " ╚═════╝ ╚═╝ ╚═╝╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝" echo "+-----------------------------------------------+" echo " Automated Build & Deploy Script for Brotherton Frappe Docker" echo "" sleep 3 trap 'cleanup' ERR IMAGE_NAME="githaven.org/shiloh/brotherton_frappe_docker:$TAG" echo "🔍 Checking for pre-existing tag: $TAG" if skopeo inspect "docker://$IMAGE_NAME" >/dev/null 2>&1; then echo "❗ Tag $TAG already exists in the remote registry." ALREADY_EXISTING=true else echo "✅ Tag $TAG is available in registry." fi if docker image inspect "$IMAGE_NAME" >/dev/null 2>&1; then echo "❗ Tag $TAG already exists in the local Docker images." ALREADY_EXISTING=true else echo "✅ Tag $TAG is available locally." fi if [[ -n "$REMOTE_HOST" ]] && [ "$BUILD_ONLY" = false ]; then echo "Checking remote server $REMOTE_HOST for existing image..." if ssh -o StrictHostKeyChecking=no "$REMOTE_USER@$REMOTE_HOST" "docker image inspect $IMAGE_NAME >/dev/null 2>&1"; then echo "❗ Tag $TAG already exists on remote server $REMOTE_HOST." ALREADY_EXISTING=true else echo "✅ Tag $TAG is available on remote server." fi fi if [ "$ALREADY_EXISTING" = true ]; then echo "⚠️ Build aborted due to existing tag. View logs above to identify where the tag exists." exit 1 fi export TAG export APPS_JSON_BASE64=$(base64 -w 0 ./apps_new.json) echo "Building Brotherton Frappe Docker Image with tag: $TAG" echo "APPS_JSON_BASE64: $APPS_JSON_BASE64" echo "🚀 Starting Docker build..." docker build --no-cache \ --build-arg=FRAPPE_PATH=https://github.com/frappe/frappe \ --build-arg=FRAPPE_BRANCH=version-15 \ --build-arg=APPS_JSON_BASE64=$APPS_JSON_BASE64 \ --tag=githaven.org/shiloh/brotherton_frappe_docker:$TAG \ --file=images/layered/Containerfile . echo "✅ Docker build completed!" echo "📤 Pushing image to registry..." docker push githaven.org/shiloh/brotherton_frappe_docker:$TAG echo "✅ Image pushed successfully!" MIGRATE_COMMAND="" if [ "$MIGRATE" = true ]; then MIGRATE_COMMAND="--migrate" fi if [[ -n "$REMOTE_HOST" ]] && [ "$BUILD_ONLY" = false ]; then echo "🔗 Connecting to remote server $REMOTE_USER@$REMOTE_HOST..." ssh "$REMOTE_USER@$REMOTE_HOST" "./re-deploy.sh --tag $TAG $MIGRATE_COMMAND" echo "✅ Remote deployment completed!" else echo "⚙️ Build-only mode enabled; skipping remote deployment." fi if [ "$BUILD_ONLY" = false ]; then echo "🎉 Deployment of tag $TAG completed successfully!" else echo "🎉 Build and push of tag $TAG completed successfully!" fi