#!/usr/bin/env bash set -Eeuo pipefail # Download a package URL and deploy it on the target server. # Usage: # DEPLOY_ENV=emp-uat bash deploy-from-url.sh "<signed package URL>" # DEPLOY_ENV=emp-uat PACKAGE_SHA256=<sha256> bash deploy-from-url.sh "<signed package URL>" DEPLOY_ENV="${DEPLOY_ENV:-emp-test}" PROJECT_NAME="${PROJECT_NAME:-$DEPLOY_ENV}" DEPLOY_HOME="${DEPLOY_HOME:-/home/admin-x99/emp/$DEPLOY_ENV}" PACKAGE_URL="${1:-}" EXPECTED_SHA256="${PACKAGE_SHA256:-${2:-}}" RUN_ID="${RUN_ID:-$(date '+%Y%m%d%H%M%S')}" PACKAGE_ROOT="${PACKAGE_ROOT:-$DEPLOY_HOME/packages}" RUNTIME_DIR="${RUNTIME_DIR:-$DEPLOY_HOME/runtime}" WORK_DIR="$PACKAGE_ROOT/$RUN_ID" DOWNLOAD_FILE="$WORK_DIR/package.tar.gz" EXTRACT_DIR="$WORK_DIR/extracted" 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" } download_package() { local url="$1" local output="$2" if command -v curl >/dev/null 2>&1; then curl -fL --retry 3 --connect-timeout 20 -o "$output" "$url" elif command -v wget >/dev/null 2>&1; then wget -O "$output" "$url" else die "Missing curl or wget" fi } calc_sha256() { local file="$1" if command -v sha256sum >/dev/null 2>&1; then sha256sum "$file" | awk '{print $1}' elif command -v shasum >/dev/null 2>&1; then shasum -a 256 "$file" | awk '{print $1}' else die "Missing sha256sum or shasum for checksum verification" fi } verify_checksum() { local file="$1" local expected="$2" [[ -n "$expected" ]] || return local actual actual="$(calc_sha256 "$file")" if [[ "$actual" != "$expected" ]]; then die "SHA256 mismatch. expected=$expected actual=$actual" fi log "SHA256 verified: $actual" } copy_runtime_package() { mkdir -p "$RUNTIME_DIR" cp "$EXTRACT_DIR/docker-compose.yml" "$RUNTIME_DIR/docker-compose.yml" cp "$EXTRACT_DIR/install.sh" "$RUNTIME_DIR/install.sh" cp "$EXTRACT_DIR/images.tar" "$RUNTIME_DIR/images.tar" if [[ -f "$EXTRACT_DIR/deploy-from-url.sh" ]]; then cp "$EXTRACT_DIR/deploy-from-url.sh" "$RUNTIME_DIR/deploy-from-url.sh" fi if [[ -f "$EXTRACT_DIR/.env.example" ]]; then cp "$EXTRACT_DIR/.env.example" "$RUNTIME_DIR/.env.example" fi if [[ -f "$EXTRACT_DIR/README.md" ]]; then cp "$EXTRACT_DIR/README.md" "$RUNTIME_DIR/README.md" fi } deploy_runtime_package() { log "Deploy runtime package to $RUNTIME_DIR" copy_runtime_package ( cd "$RUNTIME_DIR" DEPLOY_ENV="$DEPLOY_ENV" \ PROJECT_NAME="$PROJECT_NAME" \ ENV_FILE=.env \ COMPOSE_FILE=docker-compose.yml \ IMAGE_TAR=images.tar \ bash install.sh ) } deploy_update_package() { [[ -f "$RUNTIME_DIR/.env" ]] || die "Missing runtime env file: $RUNTIME_DIR/.env" [[ -f "$RUNTIME_DIR/docker-compose.yml" ]] || die "Missing runtime compose file: $RUNTIME_DIR/docker-compose.yml" log "Apply update package with runtime dir: $RUNTIME_DIR" ( cd "$EXTRACT_DIR" DEPLOY_ENV="$DEPLOY_ENV" \ DEPLOY_HOME="$DEPLOY_HOME" \ PROJECT_NAME="$PROJECT_NAME" \ ENV_FILE="$RUNTIME_DIR/.env" \ COMPOSE_FILE="$RUNTIME_DIR/docker-compose.yml" \ IMAGE_TAR=images.tar \ bash apply-update.sh ) } [[ -n "$PACKAGE_URL" ]] || die "Usage: DEPLOY_ENV=emp-uat bash deploy-from-url.sh <package-url>" need_cmd tar mkdir -p "$WORK_DIR" "$EXTRACT_DIR" log "Deploy env: $DEPLOY_ENV" log "Deploy home: $DEPLOY_HOME" log "Download package" download_package "$PACKAGE_URL" "$DOWNLOAD_FILE" verify_checksum "$DOWNLOAD_FILE" "$EXPECTED_SHA256" log "Extract package" tar -xzf "$DOWNLOAD_FILE" -C "$EXTRACT_DIR" --strip-components=1 if [[ -f "$EXTRACT_DIR/install.sh" && -f "$EXTRACT_DIR/docker-compose.yml" ]]; then deploy_runtime_package elif [[ -f "$EXTRACT_DIR/apply-update.sh" && -f "$EXTRACT_DIR/images.tar" ]]; then deploy_update_package else die "Unknown package structure: $EXTRACT_DIR" fi log "Done. Package workspace: $WORK_DIR"