|
- #!/usr/bin/env bash
- set -Eeuo pipefail
-
- # Build all images locally, export them, and create a server runtime package.
- # Supports both layouts:
- # 1. monorepo: emp/deploy/isolated/build-package.sh
- # 2. split deploy: emp_test_deploy/isolated/build-package.sh with EMP_ROOT=/path/to/emp
-
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
- DIST_DIR="$SCRIPT_DIR/dist"
- BUILD_CONTEXT_DIR="$SCRIPT_DIR/.build-context"
-
- DEPLOY_ENV="${DEPLOY_ENV:-emp-test}"
- IMAGE_NAMESPACE="${IMAGE_NAMESPACE:-$DEPLOY_ENV}"
- IMAGE_TAG="${IMAGE_TAG:-$(date '+%Y%m%d%H%M%S')}"
- PACKAGE_NAME="${PACKAGE_NAME:-${DEPLOY_ENV}-runtime-${IMAGE_TAG}}"
- PACKAGE_DIR="$DIST_DIR/$PACKAGE_NAME"
- PACKAGE_ARCHIVE="$DIST_DIR/${PACKAGE_NAME}.tar.gz"
- NPM_REGISTRY="${NPM_REGISTRY:-https://registry.npmjs.org}"
- SKIP_BUILD="${SKIP_BUILD:-0}"
- INCLUDE_MIDDLEWARE_IMAGES="${INCLUDE_MIDDLEWARE_IMAGES:-1}"
- COS_UPLOAD="${COS_UPLOAD:-0}"
-
- JAVA_MODULES=(emp_gateway emp_auth emp_monitor emp_data)
- APP_IMAGES=(
- "$IMAGE_NAMESPACE/emp-gateway:$IMAGE_TAG"
- "$IMAGE_NAMESPACE/emp-gateway:latest"
- "$IMAGE_NAMESPACE/emp-auth:$IMAGE_TAG"
- "$IMAGE_NAMESPACE/emp-auth:latest"
- "$IMAGE_NAMESPACE/emp-monitor:$IMAGE_TAG"
- "$IMAGE_NAMESPACE/emp-monitor:latest"
- "$IMAGE_NAMESPACE/emp-data:$IMAGE_TAG"
- "$IMAGE_NAMESPACE/emp-data:latest"
- "$IMAGE_NAMESPACE/emp-pdf:$IMAGE_TAG"
- "$IMAGE_NAMESPACE/emp-pdf:latest"
- "$IMAGE_NAMESPACE/emp-ws:$IMAGE_TAG"
- "$IMAGE_NAMESPACE/emp-ws:latest"
- "$IMAGE_NAMESPACE/emp-admin:$IMAGE_TAG"
- "$IMAGE_NAMESPACE/emp-admin:latest"
- )
-
- MIDDLEWARE_IMAGES=(
- "${MYSQL_IMAGE:-mysql:8.0}"
- "${REDIS_IMAGE:-redis:7-alpine}"
- "${KAFKA_IMAGE:-bitnami/kafka:3.7.0}"
- "${TDENGINE_IMAGE:-tdengine/tdengine:3.3.6.0}"
- "${NACOS_IMAGE:-nacos/nacos-server:v2.3.2-slim}"
- )
-
- log() {
- echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
- }
-
- die() {
- echo "ERROR: $*" >&2
- exit 1
- }
-
- need_cmd() {
- command -v "$1" >/dev/null 2>&1 || die "Missing command: $1"
- }
-
- has_emp_root() {
- [[ -d "$1/emp_server" && -d "$1/emp_admin" && -d "$1/emp_ws" ]]
- }
-
- resolve_root_dir() {
- if [[ -n "${EMP_ROOT:-}" ]]; then
- local root
- root="$(cd "$EMP_ROOT" && pwd)"
- has_emp_root "$root" || die "EMP_ROOT is invalid: $EMP_ROOT"
- printf '%s\n' "$root"
- return
- fi
-
- local candidates=(
- "$SCRIPT_DIR/../.."
- "$SCRIPT_DIR/../../emp"
- "$SCRIPT_DIR/.."
- "$PWD"
- )
- local candidate root
- for candidate in "${candidates[@]}"; do
- if [[ -d "$candidate" ]]; then
- root="$(cd "$candidate" && pwd)"
- if has_emp_root "$root"; then
- printf '%s\n' "$root"
- return
- fi
- fi
- done
-
- die "Cannot find EMP root. Set EMP_ROOT=/path/to/emp where emp_server, emp_admin and emp_ws exist."
- }
-
- ROOT_DIR="$(resolve_root_dir)"
-
- build_java_images() {
- cd "$ROOT_DIR/emp_server"
- log "Build backend jars"
- mvn package -DskipTests -B -pl "$(IFS=,; echo "${JAVA_MODULES[*]}")" -am
-
- for module in "${JAVA_MODULES[@]}"; do
- local jar
- jar="$(ls "$module"/target/*.jar | grep -v original | grep -v app.jar | head -1)"
- [[ -n "$jar" ]] || die "Jar not found for $module"
- cp "$jar" "$module/target/app.jar"
- done
-
- log "Build backend images"
- docker build -f Dockerfile.service --build-arg MODULE=emp_gateway -t "$IMAGE_NAMESPACE/emp-gateway:$IMAGE_TAG" -t "$IMAGE_NAMESPACE/emp-gateway:latest" .
- docker build -f Dockerfile.service --build-arg MODULE=emp_auth -t "$IMAGE_NAMESPACE/emp-auth:$IMAGE_TAG" -t "$IMAGE_NAMESPACE/emp-auth:latest" .
- docker build -f Dockerfile.service --build-arg MODULE=emp_monitor -t "$IMAGE_NAMESPACE/emp-monitor:$IMAGE_TAG" -t "$IMAGE_NAMESPACE/emp-monitor:latest" .
- docker build -f Dockerfile.service --build-arg MODULE=emp_data -t "$IMAGE_NAMESPACE/emp-data:$IMAGE_TAG" -t "$IMAGE_NAMESPACE/emp-data:latest" .
-
- log "Build PDF image"
- docker build -f emp_pdf/Dockerfile -t "$IMAGE_NAMESPACE/emp-pdf:$IMAGE_TAG" -t "$IMAGE_NAMESPACE/emp-pdf:latest" emp_pdf
- }
-
- build_ws_image() {
- cd "$ROOT_DIR"
- log "Build WS/simulator image"
- docker build \
- -f "$SCRIPT_DIR/dockerfiles/emp-ws.Dockerfile" \
- --build-arg "NPM_REGISTRY=$NPM_REGISTRY" \
- -t "$IMAGE_NAMESPACE/emp-ws:$IMAGE_TAG" \
- -t "$IMAGE_NAMESPACE/emp-ws:latest" \
- .
- }
-
- build_admin_image() {
- cd "$ROOT_DIR/emp_admin"
- log "Build frontend dist"
- pnpm install --frozen-lockfile
- pnpm run build:shunfeng
-
- log "Prepare frontend image context"
- rm -rf "$BUILD_CONTEXT_DIR/emp-admin"
- mkdir -p "$BUILD_CONTEXT_DIR/emp-admin"
- cp -R "$ROOT_DIR/emp_admin/dist" "$BUILD_CONTEXT_DIR/emp-admin/dist"
- cp "$SCRIPT_DIR/nginx/admin.conf" "$BUILD_CONTEXT_DIR/emp-admin/admin.conf"
-
- log "Build frontend image"
- docker build \
- -f "$SCRIPT_DIR/dockerfiles/emp-admin.Dockerfile" \
- -t "$IMAGE_NAMESPACE/emp-admin:$IMAGE_TAG" \
- -t "$IMAGE_NAMESPACE/emp-admin:latest" \
- "$BUILD_CONTEXT_DIR/emp-admin"
- }
-
- prepare_package() {
- rm -rf "$PACKAGE_DIR"
- mkdir -p "$PACKAGE_DIR"
-
- local common_profile_compose="$SCRIPT_DIR/profiles/docker-compose.yml"
- local compose_src="$SCRIPT_DIR/docker-compose.runtime.yml"
- local env_src="$SCRIPT_DIR/.env.example"
- local profile_dir="${PROFILE_DIR:-$SCRIPT_DIR/profiles/$DEPLOY_ENV}"
-
- if [[ -f "$profile_dir/docker-compose.yml" ]]; then
- compose_src="$profile_dir/docker-compose.yml"
- elif [[ -f "$common_profile_compose" ]]; then
- compose_src="$common_profile_compose"
- elif [[ "$DEPLOY_ENV" == "emp-test" && -f "$SCRIPT_DIR/test/docker-compose.yml" ]]; then
- compose_src="$SCRIPT_DIR/test/docker-compose.yml"
- fi
-
- if [[ -f "$profile_dir/.env.example" ]]; then
- env_src="$profile_dir/.env.example"
- elif [[ -f "$profile_dir/env.txt" ]]; then
- env_src="$profile_dir/env.txt"
- elif [[ "$DEPLOY_ENV" == "emp-test" && -f "$SCRIPT_DIR/test/env.txt" ]]; then
- env_src="$SCRIPT_DIR/test/env.txt"
- fi
-
- cp "$compose_src" "$PACKAGE_DIR/docker-compose.yml"
- cp "$env_src" "$PACKAGE_DIR/.env.example"
- cp "$SCRIPT_DIR/install.sh" "$PACKAGE_DIR/install.sh"
- cp "$SCRIPT_DIR/deploy-from-url.sh" "$PACKAGE_DIR/deploy-from-url.sh"
- cp "$SCRIPT_DIR/README.md" "$PACKAGE_DIR/README.md"
-
- chmod +x "$PACKAGE_DIR/install.sh"
- chmod +x "$PACKAGE_DIR/deploy-from-url.sh"
- }
-
- save_images() {
- local images=("${APP_IMAGES[@]}")
-
- if [[ "$INCLUDE_MIDDLEWARE_IMAGES" == "1" ]]; then
- log "Pull middleware images"
- for image in "${MIDDLEWARE_IMAGES[@]}"; do
- docker pull "$image"
- images+=("$image")
- done
- fi
-
- log "Save images"
- docker save -o "$PACKAGE_DIR/images.tar" "${images[@]}"
- }
-
- archive_package() {
- mkdir -p "$DIST_DIR"
- rm -f "$PACKAGE_ARCHIVE"
- tar -czf "$PACKAGE_ARCHIVE" -C "$DIST_DIR" "$PACKAGE_NAME"
- log "Package created: $PACKAGE_ARCHIVE"
- }
-
- publish_package() {
- if [[ "$COS_UPLOAD" != "1" ]]; then
- return
- fi
-
- log "Upload package to COS"
- DEPLOY_ENV="$DEPLOY_ENV" PACKAGE_KIND=runtime bash "$SCRIPT_DIR/publish-cos.sh" "$PACKAGE_ARCHIVE"
- }
-
- need_cmd docker
- need_cmd tar
-
- log "EMP root: $ROOT_DIR"
- log "Deploy root: $SCRIPT_DIR"
- log "Deploy env: $DEPLOY_ENV"
-
- if [[ "$SKIP_BUILD" != "1" ]]; then
- need_cmd mvn
- need_cmd pnpm
- build_java_images
- build_ws_image
- build_admin_image
- else
- log "Skip build, package existing local images only"
- fi
-
- prepare_package
- save_images
- archive_package
- publish_package
|