|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | +set -e |
| 4 | +source erpnext-modules.env |
| 5 | +# Colors for output |
| 6 | +RED='\033[0;31m' |
| 7 | +GREEN='\033[0;32m' |
| 8 | +YELLOW='\033[1;33m' |
| 9 | +NC='\033[0m' # No Color |
| 10 | + |
| 11 | +# Function to print colored output |
| 12 | +print_info() { |
| 13 | + echo -e "${GREEN}[INFO]${NC} $1" |
| 14 | +} |
| 15 | + |
| 16 | +print_warning() { |
| 17 | + echo -e "${YELLOW}[WARNING]${NC} $1" |
| 18 | +} |
| 19 | + |
| 20 | +print_error() { |
| 21 | + echo -e "${RED}[ERROR]${NC} $1" |
| 22 | +} |
| 23 | + |
| 24 | +# Check if podman is installed |
| 25 | +if ! command -v podman &>/dev/null; then |
| 26 | + print_error "podman is required but not installed. Please install podman first." |
| 27 | + exit 1 |
| 28 | +fi |
| 29 | + |
| 30 | +# Check if jq is installed |
| 31 | +if ! command -v jq &>/dev/null; then |
| 32 | + print_error "jq is required but not installed. Please install jq first." |
| 33 | + exit 1 |
| 34 | +fi |
| 35 | + |
| 36 | +# Function to fetch latest ERPNext tag from GitHub based on FRAPPE_VERSION |
| 37 | +fetch_erpnext_tag() { |
| 38 | + local major_version="${FRAPPE_VERSION##version-}" |
| 39 | + local api_url="https://api.github.com/repos/frappe/erpnext/tags" |
| 40 | + |
| 41 | + local tags_json |
| 42 | + if ! tags_json=$(curl -fsSL "$api_url" 2>/dev/null); then |
| 43 | + print_warning "Failed to fetch tags from GitHub, using default" |
| 44 | + return 1 |
| 45 | + fi |
| 46 | + |
| 47 | + local first_tag |
| 48 | + if ! first_tag=$(echo "$tags_json" | jq -r ".[] | select(.name | startswith(\"v${major_version}.\")) | .name" 2>/dev/null | head -1); then |
| 49 | + print_warning "Failed to parse tags, using default" |
| 50 | + return 1 |
| 51 | + fi |
| 52 | + |
| 53 | + if [ -z "$first_tag" ] || [ "$first_tag" = "null" ]; then |
| 54 | + print_warning "No v${major_version} tags found, using default" |
| 55 | + return 1 |
| 56 | + fi |
| 57 | + |
| 58 | + echo "$first_tag" |
| 59 | + return 0 |
| 60 | +} |
| 61 | + |
| 62 | +# Cache file for app_json hash |
| 63 | +CACHE_FILE=".app_json_cache" |
| 64 | +CURRENT_APPS_JSON="$APPS_JSON" |
| 65 | + |
| 66 | +# Function to compute hash of the apps JSON |
| 67 | +compute_apps_hash() { |
| 68 | + echo -n "$1" | sha256sum | cut -d' ' -f1 |
| 69 | +} |
| 70 | + |
| 71 | +# Get current apps JSON hash |
| 72 | +CURRENT_HASH=$(compute_apps_hash "$CURRENT_APPS_JSON") |
| 73 | + |
| 74 | +# Check if cache exists and compare |
| 75 | +if [ -f "$CACHE_FILE" ]; then |
| 76 | + CACHED_HASH=$(cat "$CACHE_FILE") |
| 77 | + if [ "$CURRENT_HASH" = "$CACHED_HASH" ]; then |
| 78 | + print_warning "App configuration unchanged. Skipping Docker image build." |
| 79 | + print_info "To force a rebuild, delete the cache file: rm $CACHE_FILE" |
| 80 | + exit 0 |
| 81 | + else |
| 82 | + print_info "App configuration changed. Proceeding with Docker image build..." |
| 83 | + fi |
| 84 | +else |
| 85 | + print_info "No cache found. Building Docker image..." |
| 86 | +fi |
| 87 | + |
| 88 | +# Fetch latest ERPNext tag from GitHub based on FRAPPE_VERSION |
| 89 | +ERPNEXT_TAG=$(fetch_erpnext_tag) || true |
| 90 | + |
| 91 | +if [ -z "${ERPNEXT_TAG:-}" ]; then |
| 92 | + print_warning "Could not fetch ERPNext tag, using fallback" |
| 93 | + ERPNEXT_TAG="v${FRAPPE_VERSION##version-}.0.0" |
| 94 | +fi |
| 95 | + |
| 96 | +print_info "Using ERPNext tag: $ERPNEXT_TAG" |
| 97 | + |
| 98 | +ERPNEXT_IMAGE="frappe/erpnext:${ERPNEXT_TAG}" |
| 99 | + |
| 100 | +print_info "ERPNEXT_IMAGE forcibly set to: $ERPNEXT_IMAGE" |
| 101 | +# Extract image name and tag from ERPNEXT_IMAGE |
| 102 | +BASE_IMAGE="$ERPNEXT_IMAGE" |
| 103 | +# Extract repository and tag |
| 104 | +IMAGE_REPO=$(echo "$ERPNEXT_IMAGE" | cut -d':' -f1) |
| 105 | +IMAGE_TAG=$(echo "$ERPNEXT_IMAGE" | cut -d':' -f2) |
| 106 | + |
| 107 | +# Use the same tag for custom image |
| 108 | +CUSTOM_IMAGE_NAME="${IMAGE_REPO}" |
| 109 | +CUSTOM_IMAGE_TAG="$IMAGE_TAG" |
| 110 | + |
| 111 | +print_info "Base Image: $BASE_IMAGE" |
| 112 | +print_info "Custom Image will be: $CUSTOM_IMAGE_NAME:$CUSTOM_IMAGE_TAG" |
| 113 | + |
| 114 | +print_info "Apps to be installed:" |
| 115 | +echo "$APPS_JSON" |
| 116 | + |
| 117 | +FRAPPE_BRANCH="${FRAPPE_VERSION}" |
| 118 | + |
| 119 | +print_info "Using Frappe branch: $FRAPPE_BRANCH" |
| 120 | +print_info "Building custom ERPNext image with Podman..." |
| 121 | + |
| 122 | +# Build the image with Podman |
| 123 | +podman build --network=host \ |
| 124 | + --jobs=4 \ |
| 125 | + --build-arg APPS_JSON_BASE64="$APPS_JSON" \ |
| 126 | + --build-arg FRAPPE_BRANCH="$FRAPPE_BRANCH" \ |
| 127 | + -t "$CUSTOM_IMAGE_NAME:$CUSTOM_IMAGE_TAG" \ |
| 128 | + -f ../actions/configure-module/Dockerfile \ |
| 129 | + . |
| 130 | + |
| 131 | +if [ $? -eq 0 ]; then |
| 132 | + print_info "Build completed successfully!" |
| 133 | + print_info "Image tagged as: $CUSTOM_IMAGE_NAME:$CUSTOM_IMAGE_TAG" |
| 134 | + |
| 135 | + # Also tag as latest |
| 136 | + podman tag "$CUSTOM_IMAGE_NAME:$CUSTOM_IMAGE_TAG" "$CUSTOM_IMAGE_NAME:latest" |
| 137 | + |
| 138 | + # Tag with the same name as base image (for drop-in replacement) |
| 139 | + podman tag "$CUSTOM_IMAGE_NAME:$CUSTOM_IMAGE_TAG" "$BASE_IMAGE" |
| 140 | + print_info "Also tagged as: $BASE_IMAGE (drop-in replacement)" |
| 141 | + |
| 142 | + echo "" |
| 143 | + print_info "To push the image to a registry:" |
| 144 | + echo " podman push $CUSTOM_IMAGE_NAME:$CUSTOM_IMAGE_TAG" |
| 145 | + echo " podman push $CUSTOM_IMAGE_NAME:latest" |
| 146 | + echo " podman push $BASE_IMAGE" |
| 147 | + |
| 148 | + echo "" |
| 149 | + print_info "Image size:" |
| 150 | + podman images "$CUSTOM_IMAGE_NAME:$CUSTOM_IMAGE_TAG" --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" |
| 151 | + ENV_FILE="environment" |
| 152 | + |
| 153 | + # Ensure env file exists |
| 154 | + [ -f "$ENV_FILE" ] || { |
| 155 | + print_error "Env file not found" |
| 156 | + exit 1 |
| 157 | + } |
| 158 | + |
| 159 | + CUSTOM_IMAGE_FULL="$CUSTOM_IMAGE_NAME:$CUSTOM_IMAGE_TAG" |
| 160 | + |
| 161 | + # Update or add ERPNEXT_IMAGE |
| 162 | + if grep -q '^ERPNEXT_IMAGE=' "$ENV_FILE"; then |
| 163 | + sed -i "s|^ERPNEXT_IMAGE=.*|ERPNEXT_IMAGE=$CUSTOM_IMAGE_FULL|" "$ENV_FILE" |
| 164 | + else |
| 165 | + echo "ERPNEXT_IMAGE=$CUSTOM_IMAGE_FULL" >>"$ENV_FILE" |
| 166 | + fi |
| 167 | + |
| 168 | + print_info "Updated ERPNEXT_IMAGE in $ENV_FILE to:" |
| 169 | + print_info "$CUSTOM_IMAGE_FULL" print_info "To use this image, it's already tagged as: $BASE_IMAGE" |
| 170 | + print_info "Your existing docker-compose or deployment will automatically use the custom image!" |
| 171 | + |
| 172 | + # Update the cache with the new hash |
| 173 | + echo "$CURRENT_HASH" >"$CACHE_FILE" |
| 174 | + print_info "Cache updated." |
| 175 | +else |
| 176 | + print_error "Build failed!" |
| 177 | + exit 1 |
| 178 | +fi |
0 commit comments