714 lines
20 KiB
Bash
714 lines
20 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
#
|
|
#Bash script for safe COIN sandbox deployment that prepares new release directories, extracts the release from a Docker image, runs interactive pre-checks (Docker, SSH, DB migrations),
|
|
#supports dry-run and node-specific deploys, and deploys to node-3 and node-4 with logging and safety guards
|
|
# Features:
|
|
# - Full/partial release deploy to node-3 / node-4
|
|
# - Manual EXPECTED_MIGRATION_ID check in DB
|
|
# - Colorful output
|
|
# - Logging to file
|
|
# - Interactive SELF-TEST
|
|
# - Manual stop for editing project.env
|
|
# - CLI flags:
|
|
# --dry-run
|
|
# --self-test-only
|
|
# --node3-only
|
|
# --node4-only
|
|
# --skip-db-check
|
|
# --skip-self-test
|
|
# --auto-yes
|
|
# --deploy-only node3|node4|node3,node4
|
|
# --help
|
|
#
|
|
#
|
|
#For testing use ./deploy.sh --dry-run --self-test-only
|
|
#
|
|
#
|
|
#NAME DESCRIPTION DOCKER ENDPOINT ERROR
|
|
#default Current DOCKER_HOST based configuration unix:///var/run/docker.sock
|
|
#wlt-sbx-coinssm-ams tcp://10.95.81.151:2376
|
|
#wlt-sbx-dkapp3-ams tcp://10.95.81.131:2376
|
|
#wlt-sbx-dkapp4-ams * tcp://10.95.81.132:2376
|
|
#
|
|
|
|
set -euo pipefail
|
|
|
|
############################################
|
|
# -------- COLORS (for console only) -------
|
|
############################################
|
|
|
|
RED="\033[1;31m"
|
|
GREEN="\033[1;32m"
|
|
YELLOW="\033[1;33m"
|
|
BLUE="\033[1;34m"
|
|
RESET="\033[0m"
|
|
|
|
############################################
|
|
# -------- ARGUMENT PARSING FLAGS ----------
|
|
############################################
|
|
|
|
CMD_DRY_RUN=false
|
|
CMD_SELF_TEST_ONLY=false
|
|
CMD_NODE3_ONLY=false
|
|
CMD_NODE4_ONLY=false
|
|
CMD_SKIP_DB_CHECK=false
|
|
CMD_SKIP_SELF_TEST=false
|
|
CMD_AUTO_YES=false
|
|
CMD_ROLLBACK=false
|
|
|
|
# NEW: deploy-only
|
|
CMD_DEPLOY_ONLY=false
|
|
DEPLOY_ONLY_NODES=""
|
|
|
|
############################################
|
|
# -------- STATUS FLAGS (summary) ----------
|
|
############################################
|
|
PREPARED_NODE3=false
|
|
PREPARED_NODE4=false
|
|
SELECTED_NODE3=false
|
|
SELECTED_NODE4=false
|
|
DEPLOY_ATTEMPT_NODE3=false
|
|
DEPLOY_ATTEMPT_NODE4=false
|
|
|
|
show_help() {
|
|
echo ""
|
|
echo "COIN Sandbox Deployment Script — usage:"
|
|
echo ""
|
|
echo " --dry-run Run commands in simulation mode (no real changes)"
|
|
echo " --self-test-only Run self-test checks and exit (no deploy)"
|
|
echo " --node3-only Prepare BOTH nodes, but deploy only node-3 (no questions)"
|
|
echo " --node4-only Prepare BOTH nodes, but deploy only node-4 (no questions)"
|
|
echo " --skip-db-check Do not check migration ID in DB after node-3 deploy"
|
|
echo " --skip-self-test Skip self-test before deployment"
|
|
echo " --auto-yes Automatically answer YES to all confirmations"
|
|
echo " --rollback Revert to previous release (stops stacks, redeploys previous version)"
|
|
echo " --deploy-only node3|node4|node3,node4 Deploy only selected node(s), skip prepare & questions"
|
|
echo " --help, -h Show this help message"
|
|
echo ""
|
|
exit 0
|
|
}
|
|
|
|
# NEW: robust arg parsing to support --deploy-only value
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--dry-run)
|
|
CMD_DRY_RUN=true
|
|
shift
|
|
;;
|
|
--self-test-only)
|
|
CMD_SELF_TEST_ONLY=true
|
|
shift
|
|
;;
|
|
--node3-only)
|
|
CMD_NODE3_ONLY=true
|
|
shift
|
|
;;
|
|
--node4-only)
|
|
CMD_NODE4_ONLY=true
|
|
shift
|
|
;;
|
|
--skip-db-check)
|
|
CMD_SKIP_DB_CHECK=true
|
|
shift
|
|
;;
|
|
--skip-self-test)
|
|
CMD_SKIP_SELF_TEST=true
|
|
shift
|
|
;;
|
|
--auto-yes)
|
|
CMD_AUTO_YES=true
|
|
shift
|
|
;;
|
|
--rollback)
|
|
CMD_ROLLBACK=true
|
|
shift
|
|
;;
|
|
--deploy-only)
|
|
CMD_DEPLOY_ONLY=true
|
|
DEPLOY_ONLY_NODES="${2:-}"
|
|
shift 2
|
|
;;
|
|
--help|-h)
|
|
show_help
|
|
;;
|
|
*)
|
|
echo "Unknown argument: $1"
|
|
echo "Use --help for usage."
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# NEW: validate deploy-only input
|
|
if [ "$CMD_DEPLOY_ONLY" = true ]; then
|
|
if [[ ! "$DEPLOY_ONLY_NODES" =~ ^(node3|node4|node3,node4|node4,node3)$ ]]; then
|
|
echo "ERROR: --deploy-only requires: node3 | node4 | node3,node4"
|
|
echo "Example: ./deploy.sh --deploy-only node3"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
############################################
|
|
# -------- INTERACTIVE INPUT ---------------
|
|
############################################
|
|
prompt_var() {
|
|
local var_name="$1"
|
|
local default_value="$2"
|
|
local current_value="${!var_name:-}"
|
|
|
|
if [ -n "$current_value" ]; then
|
|
printf -v "$var_name" "%s" "$current_value"
|
|
return
|
|
fi
|
|
|
|
read -r -p "${var_name} [${default_value}]: " input
|
|
if [ -z "$input" ]; then
|
|
printf -v "$var_name" "%s" "$default_value"
|
|
else
|
|
printf -v "$var_name" "%s" "$input"
|
|
fi
|
|
}
|
|
|
|
|
|
############################################
|
|
# -------- RELEASE INPUT -------------------
|
|
############################################
|
|
|
|
prompt_var "TASK_ID" "41361"
|
|
prompt_var "RELEASE_VERSION" "25.22"
|
|
prompt_var "RELEASE_TAG" "2025-12-15-11eeef9e99"
|
|
|
|
prompt_var "PREVIOUS_RELEASE_VERSION" "25.21"
|
|
prompt_var "PREVIOUS_RELEASE_TAG" "2025-12-05-ecacdc6c25"
|
|
|
|
prompt_var "EXPECTED_MIGRATION_ID" "565"
|
|
|
|
|
|
############################################
|
|
# -------- CONFIG (change per release) -----
|
|
############################################
|
|
|
|
# Base directory for sandbox releases
|
|
BASE_DIR="/home/dev-wltsbx/encrypted/sandbox"
|
|
|
|
# Docker registry
|
|
REGISTRY="wlt-sbx-hb-int.wltsbxinner.walletto.eu/coin/release"
|
|
|
|
# Docker contexts
|
|
NODE3_CONTEXT="wlt-sbx-dkapp3-ams"
|
|
NODE4_CONTEXT="wlt-sbx-dkapp4-ams"
|
|
|
|
# Docker stacks
|
|
NODE3_STACK="sbxapp3"
|
|
NODE4_STACK="sbxapp4"
|
|
|
|
# DRY-RUN: default false, can be overridden by env or --dry-run
|
|
DRY_RUN="${DRY_RUN:-false}"
|
|
if [ "$CMD_DRY_RUN" = true ]; then
|
|
DRY_RUN=true
|
|
fi
|
|
|
|
|
|
|
|
SSH_JUMP_HOST="${SSH_JUMP_HOST:-YOUR_JUMP_HOST}"
|
|
DB_HOST="${DB_HOST:-YOUR_DB_HOST}"
|
|
DB_PORT="${DB_PORT:-5432}"
|
|
DB_NAME="${DB_NAME:-coin}"
|
|
DB_USER="${DB_USER:-coin}"
|
|
DB_PASSWORD="${DB_PASSWORD:-YOUR_DB_PASSWORD}"
|
|
|
|
############################################
|
|
# -------- DERIVED PATHS -------------------
|
|
############################################
|
|
|
|
NEW_SUFFIX="_sbx_${RELEASE_TAG}"
|
|
PREV_SUFFIX="_sbx_${PREVIOUS_RELEASE_TAG}"
|
|
|
|
NODE4_NEW="${BASE_DIR}/${RELEASE_VERSION}${NEW_SUFFIX}-node-4"
|
|
NODE3_NEW="${BASE_DIR}/${RELEASE_VERSION}${NEW_SUFFIX}-node-3"
|
|
|
|
NODE4_PREV="${BASE_DIR}/${PREVIOUS_RELEASE_VERSION}${PREV_SUFFIX}-node-4"
|
|
NODE3_PREV="${BASE_DIR}/${PREVIOUS_RELEASE_VERSION}${PREV_SUFFIX}-node-3"
|
|
|
|
OLD_COIN="coin-${PREVIOUS_RELEASE_TAG}"
|
|
NEW_COIN="coin-${RELEASE_TAG}"
|
|
|
|
TARBALL="${RELEASE_TAG}.tar.gz"
|
|
|
|
############################################
|
|
# -------- LOGGING SETUP -------------------
|
|
############################################
|
|
|
|
LOG_DIR="${BASE_DIR}/logs"
|
|
mkdir -p "$LOG_DIR"
|
|
|
|
TIMESTAMP="$(date '+%Y-%m-%d__%H-%M-%S')"
|
|
LOGFILE="${LOG_DIR}/deploy_${RELEASE_TAG}__${TIMESTAMP}_task-${TASK_ID}.log"
|
|
touch "$LOGFILE"
|
|
|
|
############################################
|
|
# -------- UTILS (log, run, confirm) -------
|
|
############################################
|
|
|
|
log_msg() {
|
|
# Write to logfile without ANSI codes
|
|
printf "%s\n" "$(echo -e "$1" | sed 's/\x1B\[[0-9;]*[JKmsu]//g')" >> "$LOGFILE"
|
|
# Print to console with colors
|
|
echo -e "$1"
|
|
}
|
|
|
|
run() {
|
|
log_msg "${BLUE}+ $*${RESET}"
|
|
if [ "$DRY_RUN" != "true" ]; then
|
|
"$@"
|
|
fi
|
|
}
|
|
|
|
ensure_dir() {
|
|
if [ ! -d "$1" ]; then
|
|
log_msg "${RED}ERROR: directory not found: $1${RESET}"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
confirm() {
|
|
local question="$1"
|
|
|
|
if [ "$CMD_AUTO_YES" = true ]; then
|
|
log_msg "${YELLOW}[AUTO-YES] ${question}: YES${RESET}"
|
|
return 0
|
|
fi
|
|
|
|
read -r -p "${question} (yes/no): " answer
|
|
case "$answer" in
|
|
yes|y|Y) return 0 ;;
|
|
*) log_msg "${RED}Operation cancelled by user.${RESET}"; exit 1 ;;
|
|
esac
|
|
}
|
|
|
|
# NEW: soft confirm (no => skip, not exit)
|
|
confirm_optional() {
|
|
local question="$1"
|
|
|
|
if [ "$CMD_AUTO_YES" = true ]; then
|
|
log_msg "${YELLOW}[AUTO-YES] ${question}: YES${RESET}"
|
|
return 0
|
|
fi
|
|
|
|
while true; do
|
|
read -r -p "${question} (yes/no): " answer
|
|
case "$answer" in
|
|
yes|y|Y) return 0 ;;
|
|
no|n|N) return 1 ;;
|
|
*) echo "Please answer yes or no." ;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
print_summary() {
|
|
log_msg ""
|
|
log_msg "${BLUE}======== DEPLOY SUMMARY ========${RESET}"
|
|
|
|
if [ "$CMD_DEPLOY_ONLY" = true ]; then
|
|
log_msg "Prepared:"
|
|
log_msg " - node-4 : skipped (deploy-only)"
|
|
log_msg " - node-3 : skipped (deploy-only)"
|
|
else
|
|
log_msg "Prepared:"
|
|
log_msg " - node-4 : ${PREPARED_NODE4}"
|
|
log_msg " - node-3 : ${PREPARED_NODE3}"
|
|
fi
|
|
|
|
log_msg ""
|
|
log_msg "Selected:"
|
|
log_msg " - node-3 : ${SELECTED_NODE3}"
|
|
log_msg " - node-4 : ${SELECTED_NODE4}"
|
|
|
|
log_msg ""
|
|
log_msg "Deploy attempted:"
|
|
log_msg " - node-3 : ${DEPLOY_ATTEMPT_NODE3}"
|
|
log_msg " - node-4 : ${DEPLOY_ATTEMPT_NODE4}"
|
|
|
|
log_msg ""
|
|
log_msg "Mode:"
|
|
if [ "$CMD_DEPLOY_ONLY" = true ]; then
|
|
log_msg " - deploy-only : true (${DEPLOY_ONLY_NODES})"
|
|
else
|
|
log_msg " - deploy-only : false"
|
|
fi
|
|
log_msg "${BLUE}================================${RESET}"
|
|
}
|
|
|
|
############################################
|
|
# -------- SELF-TEST (interactive) ---------
|
|
############################################
|
|
|
|
self_test() {
|
|
log_msg "${BLUE}========== SELF-TEST ==========${RESET}"
|
|
|
|
local issues=()
|
|
|
|
# 1. Directories
|
|
[ -d "$BASE_DIR" ] || issues+=("BASE_DIR does not exist: $BASE_DIR")
|
|
[ -d "$NODE4_PREV" ] || issues+=("Previous node-4 release dir missing: $NODE4_PREV")
|
|
[ -d "$NODE3_PREV" ] || issues+=("Previous node-3 release dir missing: $NODE3_PREV")
|
|
|
|
# 2. Docker contexts
|
|
if ! docker context ls >/dev/null 2>&1; then
|
|
issues+=("docker context ls failed (docker not available?)")
|
|
else
|
|
docker context ls --format '{{.Name}}' | grep -qx "$NODE3_CONTEXT" || \
|
|
issues+=("docker context for node-3 not found: $NODE3_CONTEXT")
|
|
docker context ls --format '{{.Name}}' | grep -qx "$NODE4_CONTEXT" || \
|
|
issues+=("docker context for node-4 not found: $NODE4_CONTEXT")
|
|
fi
|
|
|
|
|
|
# Config summary
|
|
log_msg "${YELLOW}Release configuration:${RESET}"
|
|
log_msg " Release version : ${RELEASE_VERSION}"
|
|
log_msg " Release tag : ${RELEASE_TAG}"
|
|
log_msg " Previous version: ${PREVIOUS_RELEASE_VERSION} (${PREVIOUS_RELEASE_TAG})"
|
|
log_msg " Task ID : ${TASK_ID}"
|
|
log_msg " BASE_DIR : ${BASE_DIR}"
|
|
log_msg " NODE3 context : ${NODE3_CONTEXT}"
|
|
log_msg " NODE4 context : ${NODE4_CONTEXT}"
|
|
log_msg " EXPECTED MIG ID : ${EXPECTED_MIGRATION_ID}"
|
|
log_msg " Log file : ${LOGFILE}"
|
|
|
|
if [ "${#issues[@]}" -gt 0 ]; then
|
|
log_msg "${RED}Potential issues detected:${RESET}"
|
|
for item in "${issues[@]}"; do
|
|
log_msg " - ${item}"
|
|
done
|
|
confirm "⚠ Continue deployment despite these issues?"
|
|
else
|
|
log_msg "${GREEN}SELF-TEST: no critical issues detected.${RESET}"
|
|
confirm "Proceed with deployment?"
|
|
fi
|
|
|
|
log_msg "${BLUE}========== SELF-TEST DONE ======${RESET}"
|
|
}
|
|
|
|
|
|
############################################
|
|
# -------- ROLLBACK TO PREVIOUS RELEASE ----
|
|
############################################
|
|
|
|
rollback() {
|
|
log_msg "${BLUE}=== ROLLBACK TO PREVIOUS RELEASE ===${RESET}"
|
|
log_msg "${YELLOW}Rolling back from ${RELEASE_VERSION} (${RELEASE_TAG})${RESET}"
|
|
log_msg "${YELLOW} to ${PREVIOUS_RELEASE_VERSION} (${PREVIOUS_RELEASE_TAG})${RESET}"
|
|
|
|
confirm "⚠ This will stop current stacks and revert to previous release. Continue?"
|
|
|
|
# Stop node-3 stack
|
|
log_msg "${YELLOW}Stopping node-3 stack (${NODE3_STACK})…${RESET}"
|
|
run docker context use "$NODE3_CONTEXT"
|
|
run docker stack rm "$NODE3_STACK" || log_msg "${YELLOW}Stack not found or already removed.${RESET}"
|
|
sleep 3
|
|
|
|
# Stop node-4 stack
|
|
log_msg "${YELLOW}Stopping node-4 stack (${NODE4_STACK})…${RESET}"
|
|
run docker context use "$NODE4_CONTEXT"
|
|
run docker stack rm "$NODE4_STACK" || log_msg "${YELLOW}Stack not found or already removed.${RESET}"
|
|
sleep 3
|
|
|
|
log_msg "${GREEN}Stacks stopped.${RESET}"
|
|
|
|
# Deploy previous node-3 release
|
|
log_msg "${YELLOW}Deploying previous node-3 release…${RESET}"
|
|
ensure_dir "$NODE3_PREV"
|
|
cd "$NODE3_PREV"
|
|
run docker context use "$NODE3_CONTEXT"
|
|
run ./deploy.sh deploy \
|
|
-n "$NODE3_CONTEXT" \
|
|
-w "$NODE3_STACK" \
|
|
-N node.env \
|
|
-P project.env \
|
|
-P project_node3.env \
|
|
-f docker-compose.yml \
|
|
-f custom.secrets.yml \
|
|
-f docker-compose-testshop.yaml \
|
|
-s secrets.override.env \
|
|
-u
|
|
|
|
# Deploy previous node-4 release
|
|
log_msg "${YELLOW}Deploying previous node-4 release…${RESET}"
|
|
ensure_dir "$NODE4_PREV"
|
|
cd "$NODE4_PREV"
|
|
run docker context use "$NODE4_CONTEXT"
|
|
run ./deploy.sh deploy \
|
|
-n "$NODE4_CONTEXT" \
|
|
-w "$NODE4_STACK" \
|
|
-N node.env \
|
|
-P project.env \
|
|
-P project_node4.env \
|
|
-f docker-compose.yml \
|
|
-f custom.secrets.yml \
|
|
-f docker-compose-testshop.yaml \
|
|
-s secrets.override.env \
|
|
-u
|
|
|
|
log_msg "${GREEN}==================================================${RESET}"
|
|
log_msg "${GREEN} ROLLBACK COMPLETED${RESET}"
|
|
log_msg "${GREEN} Now running: ${PREVIOUS_RELEASE_VERSION} (${PREVIOUS_RELEASE_TAG})${RESET}"
|
|
log_msg "${GREEN}==================================================${RESET}"
|
|
}
|
|
|
|
############################################
|
|
# -------- NODE-4 PREPARATION --------------
|
|
############################################
|
|
|
|
prepare_node4() {
|
|
log_msg "${BLUE}=== PREPARE NODE-4 ===${RESET}"
|
|
|
|
ensure_dir "$NODE4_PREV"
|
|
ensure_dir "$BASE_DIR"
|
|
|
|
run cp -r "$NODE4_PREV" "$NODE4_NEW"
|
|
cd "$NODE4_NEW"
|
|
|
|
# Remove old coin dir
|
|
[ -d "$OLD_COIN" ] && run rm -rf "$OLD_COIN"
|
|
|
|
log_msg "${YELLOW}Extracting release archive from Docker…${RESET}"
|
|
if [ "$DRY_RUN" != "true" ]; then
|
|
docker run -i --rm "${REGISTRY}:${RELEASE_TAG}" release | base64 -d > "$TARBALL"
|
|
else
|
|
log_msg "${BLUE}+ docker run … > $TARBALL (DRY RUN)${RESET}"
|
|
fi
|
|
|
|
run tar -xzf "$TARBALL"
|
|
run rm -f "$TARBALL"
|
|
|
|
ensure_dir "$NEW_COIN"
|
|
|
|
# Copy deploy.sh and docker-compose.yml
|
|
run cp "${NEW_COIN}/deploy.sh" ./
|
|
run cp "${NEW_COIN}/docker-compose.yml" ./
|
|
|
|
# Update TAG in node.env (TAG = release tag, not dir name)
|
|
if grep -q '^TAG=' node.env; then
|
|
run sed -i "s/^TAG=.*/TAG=${RELEASE_TAG}/" node.env
|
|
else
|
|
run bash -c "echo TAG=${RELEASE_TAG} >> node.env"
|
|
fi
|
|
|
|
# Comment out all export TAG_* patch lines
|
|
if grep -q '^export TAG_' node.env; then
|
|
run sed -i 's/^export TAG_/#export TAG_/' node.env
|
|
fi
|
|
|
|
# Manual edit of project.env
|
|
if [ -f project.env ]; then
|
|
log_msg "${YELLOW}Manual step required: review and edit project.env NOW.${RESET}"
|
|
log_msg "${YELLOW}For example: vi ${NODE4_NEW}/project.env${RESET}"
|
|
confirm "Continue after you have manually updated project.env?"
|
|
else
|
|
log_msg "${RED}project.env not found in ${NODE4_NEW}!${RESET}"
|
|
exit 1
|
|
fi
|
|
|
|
PREPARED_NODE4=true
|
|
log_msg "${GREEN}Node-4 prepared: ${NODE4_NEW}${RESET}"
|
|
}
|
|
|
|
############################################
|
|
# -------- NODE-3 PREPARATION --------------
|
|
############################################
|
|
|
|
prepare_node3() {
|
|
log_msg "${BLUE}=== PREPARE NODE-3 ===${RESET}"
|
|
|
|
ensure_dir "$NODE3_PREV"
|
|
ensure_dir "$NODE4_NEW"
|
|
|
|
run cp -r "$NODE3_PREV" "$NODE3_NEW"
|
|
cd "$NODE3_NEW"
|
|
|
|
[ -d "$OLD_COIN" ] && run rm -rf "$OLD_COIN"
|
|
|
|
run cp -r "$NODE4_NEW/${NEW_COIN}" ./
|
|
|
|
run cp "${NEW_COIN}/deploy.sh" ./
|
|
run cp "${NEW_COIN}/docker-compose.yml" ./
|
|
|
|
# Reuse already updated node.env and project.env from node-4
|
|
run cp "$NODE4_NEW/node.env" ./
|
|
run cp "$NODE4_NEW/project.env" ./
|
|
|
|
PREPARED_NODE3=true
|
|
log_msg "${GREEN}Node-3 prepared: ${NODE3_NEW}${RESET}"
|
|
}
|
|
|
|
############################################
|
|
# -------- NODE-3 DEPLOY -------------------
|
|
############################################
|
|
|
|
deploy_node3() {
|
|
log_msg "${BLUE}=== DEPLOY NODE-3 ===${RESET}"
|
|
|
|
cd "$NODE3_NEW"
|
|
|
|
run docker context use "$NODE3_CONTEXT"
|
|
|
|
DEPLOY_ATTEMPT_NODE3=true
|
|
run ./deploy.sh deploy \
|
|
-n "$NODE3_CONTEXT" \
|
|
-w "$NODE3_STACK" \
|
|
-N node.env \
|
|
-P project.env \
|
|
-P project_node3.env \
|
|
-f docker-compose.yml \
|
|
-f custom.secrets.yml \
|
|
-f docker-compose-testshop.yaml \
|
|
-s secrets.override.env \
|
|
-u
|
|
|
|
run docker ps
|
|
}
|
|
|
|
############################################
|
|
# -------- NODE-4 DEPLOY -------------------
|
|
############################################
|
|
|
|
deploy_node4() {
|
|
log_msg "${BLUE}=== DEPLOY NODE-4 ===${RESET}"
|
|
|
|
cd "$NODE4_NEW"
|
|
|
|
run docker context use "$NODE4_CONTEXT"
|
|
|
|
DEPLOY_ATTEMPT_NODE4=true
|
|
run ./deploy.sh deploy \
|
|
-n "$NODE4_CONTEXT" \
|
|
-w "$NODE4_STACK" \
|
|
-N node.env \
|
|
-P project.env \
|
|
-P project_node4.env \
|
|
-f docker-compose.yml \
|
|
-f custom.secrets.yml \
|
|
-f docker-compose-testshop.yaml \
|
|
-s secrets.override.env \
|
|
-u
|
|
|
|
run docker ps
|
|
|
|
log_msg "${YELLOW}Reminder: run regression tests manually.${RESET}"
|
|
}
|
|
|
|
############################################
|
|
# -------- MAIN ----------------------------
|
|
############################################
|
|
|
|
main() {
|
|
log_msg "${BLUE}==================================================${RESET}"
|
|
log_msg "${BLUE} COIN Sandbox Deployment Script${RESET}"
|
|
log_msg "${BLUE} Release: ${RELEASE_VERSION} (${RELEASE_TAG})${RESET}"
|
|
log_msg "${BLUE} Task ID: ${TASK_ID}${RESET}"
|
|
log_msg "${BLUE} Logfile: ${LOGFILE}${RESET}"
|
|
log_msg "${BLUE} DRY_RUN: ${DRY_RUN}${RESET}"
|
|
log_msg "${BLUE}==================================================${RESET}"
|
|
|
|
# Rollback mode takes priority
|
|
if [ "$CMD_ROLLBACK" = true ]; then
|
|
rollback
|
|
print_summary
|
|
exit 0
|
|
fi
|
|
|
|
# Prevent conflicting flags
|
|
if [ "$CMD_NODE3_ONLY" = true ] && [ "$CMD_NODE4_ONLY" = true ]; then
|
|
log_msg "${RED}Cannot use --node3-only and --node4-only together.${RESET}"
|
|
exit 1
|
|
fi
|
|
|
|
# SELF-TEST
|
|
if [ "$CMD_SKIP_SELF_TEST" = false ]; then
|
|
self_test
|
|
else
|
|
log_msg "${YELLOW}SELF-TEST skipped (--skip-self-test).${RESET}"
|
|
fi
|
|
|
|
# Only self-test and exit
|
|
if [ "$CMD_SELF_TEST_ONLY" = true ]; then
|
|
log_msg "${YELLOW}Self-test only mode: no deployment will be performed.${RESET}"
|
|
print_summary
|
|
exit 0
|
|
fi
|
|
|
|
#########################################################
|
|
# DEPLOY-ONLY MODE: skip prepare and skip questions
|
|
#########################################################
|
|
if [ "$CMD_DEPLOY_ONLY" = true ]; then
|
|
log_msg "${YELLOW}DEPLOY-ONLY mode enabled: ${DEPLOY_ONLY_NODES}${RESET}"
|
|
log_msg "${YELLOW}Skipping prepare phase and all confirmations.${RESET}"
|
|
|
|
if [[ "$DEPLOY_ONLY_NODES" == *"node3"* ]]; then
|
|
SELECTED_NODE3=true
|
|
ensure_dir "$NODE3_NEW"
|
|
deploy_node3
|
|
fi
|
|
|
|
if [[ "$DEPLOY_ONLY_NODES" == *"node4"* ]]; then
|
|
SELECTED_NODE4=true
|
|
ensure_dir "$NODE4_NEW"
|
|
deploy_node4
|
|
fi
|
|
|
|
print_summary
|
|
exit 0
|
|
fi
|
|
|
|
#########################################################
|
|
# NORMAL MODE: ALWAYS PREPARE BOTH NODES
|
|
#########################################################
|
|
prepare_node4
|
|
prepare_node3
|
|
|
|
#########################################################
|
|
# DEPLOY SELECTION
|
|
#########################################################
|
|
|
|
if [ "$CMD_NODE3_ONLY" = true ]; then
|
|
log_msg "${YELLOW}Mode: node-3 only deployment.${RESET}"
|
|
SELECTED_NODE3=true
|
|
deploy_node3
|
|
print_summary
|
|
exit 0
|
|
fi
|
|
|
|
if [ "$CMD_NODE4_ONLY" = true ]; then
|
|
log_msg "${YELLOW}Mode: node-4 only deployment.${RESET}"
|
|
SELECTED_NODE4=true
|
|
deploy_node4
|
|
print_summary
|
|
exit 0
|
|
fi
|
|
|
|
# Interactive deploy questions
|
|
if confirm_optional "Запускать деплой node-3?"; then
|
|
SELECTED_NODE3=true
|
|
deploy_node3
|
|
else
|
|
log_msg "${YELLOW}Node-3 deployment skipped by user choice.${RESET}"
|
|
fi
|
|
|
|
if confirm_optional "Запускать деплой node-4?"; then
|
|
SELECTED_NODE4=true
|
|
deploy_node4
|
|
else
|
|
log_msg "${YELLOW}Node-4 deployment skipped by user choice.${RESET}"
|
|
fi
|
|
|
|
log_msg "${GREEN}==================================================${RESET}"
|
|
log_msg "${GREEN} DEPLOYMENT FINISHED.${RESET}"
|
|
log_msg "${GREEN} Expected DB last_id = ${EXPECTED_MIGRATION_ID}${RESET}"
|
|
log_msg "${GREEN}==================================================${RESET}"
|
|
|
|
print_summary
|
|
}
|
|
main "$@"
|