#!/usr/bin/env bash set -euo pipefail # ============================================================================ # DIDI Frontend - Build Script # Checks prerequisites, builds Docker production image # ============================================================================ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" WEB_DIR="$SCRIPT_DIR/web" IMAGE_NAME="${DIDI_IMAGE_NAME:-didi-frontend}" IMAGE_TAG="${DIDI_IMAGE_TAG:-latest}" VITE_API_URL="${VITE_API_URL:-}" # -- Colors ------------------------------------------------------------------ RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' BOLD='\033[1m' NC='\033[0m' log() { echo -e "${GREEN}[OK]${NC} $*"; } warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } err() { echo -e "${RED}[ERR]${NC} $*" >&2; } step() { echo -e "\n${CYAN}==> $*${NC}"; } # -- Usage ------------------------------------------------------------------- usage() { cat </dev/null; then log "Docker: $(docker --version 2>/dev/null | head -1)" else err "Docker not installed. https://docs.docker.com/get-docker/" ok=false fi # Docker daemon running if command -v docker &>/dev/null; then if docker info &>/dev/null; then log "Docker daemon: running" else err "Docker daemon not running. Try: sudo systemctl start docker" ok=false fi fi # Required files for f in package.json Dockerfile nginx.conf index.html; do if [[ -f "$WEB_DIR/$f" ]]; then log "$f: found" else err "$f not found in $WEB_DIR" ok=false fi done # src/ directory if [[ -d "$WEB_DIR/src" ]]; then log "src/: found" else err "src/ directory not found" ok=false fi if ! $ok; then err "Prerequisites check failed." exit 1 fi } # -- Resolve API URL --------------------------------------------------------- resolve_api_url() { if [[ -z "$VITE_API_URL" && -f "$WEB_DIR/.env.local" ]]; then VITE_API_URL=$(grep -E '^VITE_API_URL=' "$WEB_DIR/.env.local" 2>/dev/null | cut -d'=' -f2- || true) fi if [[ -n "$VITE_API_URL" ]]; then log "VITE_API_URL = $VITE_API_URL" else warn "VITE_API_URL is empty (same-origin mode)" fi } # -- Docker build ------------------------------------------------------------ docker_build() { step "Building Docker image: ${IMAGE_NAME}:${IMAGE_TAG}" local build_args=() if [[ -n "$VITE_API_URL" ]]; then build_args+=(--build-arg "VITE_API_URL=${VITE_API_URL}") fi if $DRY_RUN; then warn "[dry-run] docker build ${build_args[*]+"${build_args[*]}"} -t ${IMAGE_NAME}:${IMAGE_TAG} $WEB_DIR" return fi docker build \ ${build_args[@]+"${build_args[@]}"} \ -t "${IMAGE_NAME}:${IMAGE_TAG}" \ "$WEB_DIR" log "Image built successfully" step "Image details" docker images "${IMAGE_NAME}:${IMAGE_TAG}" --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}\t{{.CreatedAt}}" } # -- Verify ------------------------------------------------------------------ verify_image() { step "Verifying image (smoke test)" if $DRY_RUN; then warn "[dry-run] Would start temp container, check /health, remove it" return fi local cname="didi-verify-$$" docker run -d --name "$cname" -p 0:80 "${IMAGE_NAME}:${IMAGE_TAG}" >/dev/null 2>&1 local port port=$(docker port "$cname" 80 | head -1 | cut -d: -f2) local retries=10 local healthy=false while (( retries > 0 )); do if curl -sf "http://localhost:${port}/health" >/dev/null 2>&1; then healthy=true break fi sleep 0.5 (( retries-- )) done docker rm -f "$cname" >/dev/null 2>&1 if $healthy; then log "Health check PASSED" else warn "Health check FAILED — image built but nginx may have issues" fi } # -- Summary ----------------------------------------------------------------- summary() { echo "" echo -e " ${BOLD}Build complete${NC}" echo "" echo " Image: ${IMAGE_NAME}:${IMAGE_TAG}" echo " API: ${VITE_API_URL:-}" echo "" echo " Run: docker run -d -p 8080:80 ${IMAGE_NAME}:${IMAGE_TAG}" echo " Test: curl http://localhost:8080/health" echo "" } # -- Main -------------------------------------------------------------------- main() { echo "" echo -e " ${BOLD}DIDI Frontend Build${NC}" echo "" check_prerequisites resolve_api_url docker_build if ! $SKIP_VERIFY; then verify_image fi summary } main