From 0a168c82e69343e3a1be4f4b9dbdfbef3f4defce Mon Sep 17 00:00:00 2001 From: Deckard Date: Sun, 19 Oct 2025 04:59:06 -0400 Subject: [PATCH] Add migration script and harden module deploy SQL - add scripts/migrate-stack.sh to export module images and sync project/storage to a remote host - ensure manage-modules-sql.sh applies module db-world/db-auth/db-characters and custom SmartAI fixes idempotently - stage AutoBalance configs with EndGameBoost disabled on every deploy - bump MySQL tmpfs size (MYSQL_RUNTIME_TMPFS_SIZE, default 8G) to avoid OOM/ENOSPC --- .env.template | 1 + compose.yml | 2 +- scripts/manage-modules-sql.sh | 36 +++++- scripts/manage-modules.sh | 20 ++- scripts/migrate-stack.sh | 114 ++++++++++++++++++ .../custom/world/2025-10-19-smartai-fixes.sql | 45 +++++++ 6 files changed, 214 insertions(+), 4 deletions(-) create mode 100755 scripts/migrate-stack.sh create mode 100644 scripts/sql/custom/world/2025-10-19-smartai-fixes.sql diff --git a/.env.template b/.env.template index b913c58..16f7423 100644 --- a/.env.template +++ b/.env.template @@ -26,6 +26,7 @@ MYSQL_COLLATION=utf8mb4_unicode_ci MYSQL_MAX_CONNECTIONS=1000 MYSQL_INNODB_BUFFER_POOL_SIZE=256M MYSQL_INNODB_LOG_FILE_SIZE=64M +MYSQL_RUNTIME_TMPFS_SIZE=8G # DB names DB_AUTH_NAME=acore_auth diff --git a/compose.yml b/compose.yml index af22816..c74738c 100644 --- a/compose.yml +++ b/compose.yml @@ -23,7 +23,7 @@ services: - ${STORAGE_PATH:-./storage}/mysql-data:/var/lib/mysql-persistent - ${HOST_BACKUP_PATH:-${STORAGE_PATH:-./storage}/backups}:/backups tmpfs: - - /var/lib/mysql-runtime:size=2G + - /var/lib/mysql-runtime:size=${MYSQL_RUNTIME_TMPFS_SIZE:-8G} command: - mysqld - --datadir=/var/lib/mysql-runtime diff --git a/scripts/manage-modules-sql.sh b/scripts/manage-modules-sql.sh index fe01f53..ec8d2f3 100755 --- a/scripts/manage-modules-sql.sh +++ b/scripts/manage-modules-sql.sh @@ -1,6 +1,29 @@ #!/bin/bash # ac-compose set -e +trap 'echo " ❌ SQL helper error (line ${LINENO}): ${BASH_COMMAND}" >&2' ERR + +CUSTOM_SQL_ROOT="/tmp/scripts/sql/custom" +ALT_CUSTOM_SQL_ROOT="/scripts/sql/custom" + +run_custom_sql_group(){ + local subdir="$1" target_db="$2" label="$3" + local dir="${CUSTOM_SQL_ROOT}/${subdir}" + if [ ! -d "$dir" ] && [ -d "${ALT_CUSTOM_SQL_ROOT}/${subdir}" ]; then + dir="${ALT_CUSTOM_SQL_ROOT}/${subdir}" + fi + [ -d "$dir" ] || return 0 + LC_ALL=C find "$dir" -type f -name "*.sql" | sort | while read -r sql_file; do + local base_name + base_name="$(basename "$sql_file")" + echo " Executing ${label}: ${base_name}" + if mariadb --ssl=false -h "${CONTAINER_MYSQL}" -P 3306 -u root -p"${MYSQL_ROOT_PASSWORD}" "${target_db}" < "$sql_file" >/dev/null 2>&1; then + echo " ✅ Successfully executed ${base_name}" + else + echo " ❌ Failed to execute $sql_file" + fi + done || true +} # Function to execute SQL files for a module execute_module_sql() { @@ -30,7 +53,7 @@ execute_module_sql() { else echo " ❌ Failed to execute $sql_file" fi - done + done || true } echo "Processing SQL scripts for $module_name..." @@ -57,6 +80,7 @@ execute_module_sql() { fi done fi + run_sorted_sql "$module_dir/data/sql/db-world" "${DB_WORLD_NAME}" "world SQL" # Execute auth database scripts if [ -d "$module_dir/data/sql/auth" ]; then @@ -69,6 +93,7 @@ execute_module_sql() { fi done fi + run_sorted_sql "$module_dir/data/sql/db-auth" "${DB_AUTH_NAME}" "auth SQL" # Execute character database scripts if [ -d "$module_dir/data/sql/characters" ]; then @@ -81,6 +106,7 @@ execute_module_sql() { fi done fi + run_sorted_sql "$module_dir/data/sql/db-characters" "${DB_CHARACTERS_NAME}" "characters SQL" # Execute playerbots database scripts if [ "$module_name" = "Playerbots" ] && [ -d "$module_dir/data/sql/playerbots" ]; then @@ -106,6 +132,8 @@ execute_module_sql() { mysql -h "${CONTAINER_MYSQL}" -P 3306 -u root -p"${MYSQL_ROOT_PASSWORD}" "${DB_WORLD_NAME}" < "$sql_file" 2>/dev/null || echo " Warning: Failed to execute $sql_file" done fi + + return 0 } # Main function to execute SQL for all enabled modules @@ -240,4 +268,10 @@ execute_module_sql_scripts() { if [ "$MODULE_BLACK_MARKET_AUCTION_HOUSE" = "1" ] && [ -d "mod-black-market" ]; then execute_module_sql "mod-black-market" "Black Market" fi + + run_custom_sql_group world "${DB_WORLD_NAME}" "custom world SQL" + run_custom_sql_group auth "${DB_AUTH_NAME}" "custom auth SQL" + run_custom_sql_group characters "${DB_CHARACTERS_NAME}" "custom characters SQL" + + return 0 } diff --git a/scripts/manage-modules.sh b/scripts/manage-modules.sh index 6065777..58cf4de 100755 --- a/scripts/manage-modules.sh +++ b/scripts/manage-modules.sh @@ -547,6 +547,13 @@ for module_dir in mod-*; do fi done +if [ "$MODULE_AUTOBALANCE" = "1" ]; then + if [ -f "/azerothcore/env/dist/etc/AutoBalance.conf.dist" ]; then + sed -i 's/^AutoBalance\.LevelScaling\.EndGameBoost.*/AutoBalance.LevelScaling.EndGameBoost = false # disabled pending proper implementation/' \ + /azerothcore/env/dist/etc/AutoBalance.conf.dist || true + fi +fi + # Load SQL runner if present if [ -f "/scripts/manage-modules-sql.sh" ]; then . /scripts/manage-modules-sql.sh @@ -557,10 +564,15 @@ else fi # Execute SQLs for enabled modules (via helper) +SQL_EXECUTION_FAILED=0 if declare -f execute_module_sql_scripts >/dev/null 2>&1; then echo 'Executing module SQL scripts...' - execute_module_sql_scripts - echo 'SQL execution complete.' + if execute_module_sql_scripts; then + echo 'SQL execution complete.' + else + echo '⚠️ Module SQL scripts reported errors' + SQL_EXECUTION_FAILED=1 + fi fi # Module state tracking and rebuild logic @@ -653,6 +665,10 @@ fi echo 'Module management complete.' REBUILD_SENTINEL="/modules/.requires_rebuild" +if [ "$SQL_EXECUTION_FAILED" = "1" ]; then + echo "⚠️ SQL execution encountered issues; review logs above." +fi + if [ "$REBUILD_REQUIRED" = "1" ] && [ -n "$ENABLED_MODULES" ]; then echo "$ENABLED_MODULES" > "$REBUILD_SENTINEL" else diff --git a/scripts/migrate-stack.sh b/scripts/migrate-stack.sh new file mode 100755 index 0000000..1b5d6ee --- /dev/null +++ b/scripts/migrate-stack.sh @@ -0,0 +1,114 @@ +#!/bin/bash + +# Utility to migrate the current acore-compose stack to a remote host. +# It assumes the module images have already been rebuilt locally. + +set -euo pipefail + +usage(){ + cat </storage) + --skip-images Do not export/import Docker images + --help Show this help + +Example: + $(basename "$0") --host wow.example.com --user deploy --identity ~/.ssh/id_ed25519 \ + --project-dir /opt/acore-compose +EOF +} + +HOST="" +USER="" +PORT=22 +IDENTITY="" +PROJECT_DIR="" +TARBALL="" +REMOTE_STORAGE="" +SKIP_IMAGES=0 + +while [[ $# -gt 0 ]]; do + case "$1" in + --host) HOST="$2"; shift 2;; + --user) USER="$2"; shift 2;; + --port) PORT="$2"; shift 2;; + --identity) IDENTITY="$2"; shift 2;; + --project-dir) PROJECT_DIR="$2"; shift 2;; + --tarball) TARBALL="$2"; shift 2;; + --storage) REMOTE_STORAGE="$2"; shift 2;; + --skip-images) SKIP_IMAGES=1; shift;; + --help|-h) usage; exit 0;; + *) echo "Unknown option: $1" >&2; usage; exit 1;; + esac +done + +if [[ -z "$HOST" || -z "$USER" ]]; then + echo "--host and --user are required" >&2 + usage + exit 1 +fi + +PROJECT_DIR="${PROJECT_DIR:-/home/${USER}/acore-compose}" +REMOTE_STORAGE="${REMOTE_STORAGE:-${PROJECT_DIR}/storage}" +TARBALL="${TARBALL:-$(pwd)/acore-modules-images.tar}" + +SCP_OPTS=(-P "$PORT") +SSH_OPTS=(-p "$PORT") +if [[ -n "$IDENTITY" ]]; then + SCP_OPTS+=(-i "$IDENTITY") + SSH_OPTS+=(-i "$IDENTITY") +fi + +run_ssh(){ + ssh "${SSH_OPTS[@]}" "$USER@$HOST" "$@" +} + +run_scp(){ + scp "${SCP_OPTS[@]}" "$@" +} + +echo "⋅ Preparing project archive" +TMP_PROJECT_ARCHIVE="$(mktemp -u acore-compose-XXXXXX.tar.gz)" +tar --exclude '.git' --exclude 'storage/backups' --exclude 'storage/logs' \ + --exclude 'acore-modules-images.tar' -czf "$TMP_PROJECT_ARCHIVE" -C "$(pwd)/.." "$(basename "$(pwd)")" + +if [[ $SKIP_IMAGES -eq 0 ]]; then + echo "⋅ Exporting module images to $TARBALL" + docker image save \ + acore/ac-wotlk-worldserver:modules-latest \ + acore/ac-wotlk-authserver:modules-latest \ + > "$TARBALL" +fi + +echo "⋅ Removing rebuild sentinel" +rm -f storage/modules/.requires_rebuild || true + +echo "⋅ Syncing project to remote $USER@$HOST:$PROJECT_DIR" +run_ssh "mkdir -p '$PROJECT_DIR'" +run_scp "$TMP_PROJECT_ARCHIVE" "$USER@$HOST:/tmp/acore-compose.tar.gz" +run_ssh "tar -xzf /tmp/acore-compose.tar.gz -C '$PROJECT_DIR' --strip-components=1 && rm /tmp/acore-compose.tar.gz" + +echo "⋅ Syncing storage to remote" +run_ssh "mkdir -p '$REMOTE_STORAGE'" +run_scp -r storage/* "$USER@$HOST:$REMOTE_STORAGE/" + +if [[ $SKIP_IMAGES -eq 0 ]]; then + echo "⋅ Transferring docker images" + run_scp "$TARBALL" "$USER@$HOST:/tmp/acore-modules-images.tar" + run_ssh "docker load < /tmp/acore-modules-images.tar && rm /tmp/acore-modules-images.tar" +fi + +echo "⋅ Remote prepares completed" +echo "Run the following on the remote host to deploy:" +echo " cd $PROJECT_DIR && ./deploy.sh --skip-rebuild --no-watch" + +rm -f "$TMP_PROJECT_ARCHIVE" +echo "Migration script finished" diff --git a/scripts/sql/custom/world/2025-10-19-smartai-fixes.sql b/scripts/sql/custom/world/2025-10-19-smartai-fixes.sql new file mode 100644 index 0000000..a082ec4 --- /dev/null +++ b/scripts/sql/custom/world/2025-10-19-smartai-fixes.sql @@ -0,0 +1,45 @@ +-- Fix SmartAI boolean parameters for action 53 (Start Waypoint) on specific creatures. +-- This script is idempotent and can be executed multiple times safely. + +UPDATE smart_scripts +SET action_param1 = 1 +WHERE source_type = 9 + AND action_type = 53 + AND action_param1 = 2 + AND entryorguid IN ( + 2576200, 2658200, 2658201, 2681404, 2740900, 2741100, + 2748001, 2762600, 2819200, 2821700, 2821701, 2830800, + 2866500, 2866900 + ); + +-- Remove obsolete “Set Active” actions linked to event 12 that generate SmartAI warnings. +DELETE FROM smart_scripts +WHERE source_type = 0 + AND entryorguid IN (18948, 18950, 18965, 18970, 18972, 18986) + AND event_type IN (11, 36) + AND id IN (42, 43) + AND action_type = 48; + +-- Clear dangling linked events for Dalaran Pilgrims to silence "Link Event 3" warnings. +UPDATE smart_scripts +SET link = 0 +WHERE source_type = 0 + AND entryorguid IN (32596, 32597, 32598, 32600, 32601, 32602) + AND id = 2 + AND link = 3; + +-- Remove Link Event 12 references on the Darkshore defenders to avoid fallback errors. +UPDATE smart_scripts +SET link = 0 +WHERE source_type = 0 + AND entryorguid IN (18948, 18950, 18965, 18970, 18972, 18986) + AND id = 2 + AND link = 12; + +-- Clear Link Event 6 usage for entry 31702, which produces log spam. +UPDATE smart_scripts +SET link = 0 +WHERE source_type = 0 + AND entryorguid = 31702 + AND id = 5 + AND link = 6;