mirror of
https://github.com/uprightbass360/AzerothCore-RealmMaster.git
synced 2026-02-03 10:53:48 +00:00
module setup process
This commit is contained in:
@@ -165,6 +165,14 @@ EOF
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Capture module SQL ledger snapshot if available
|
||||
local ledger_src="/modules-meta/module-sql-ledger.txt"
|
||||
if [ -f "$ledger_src" ]; then
|
||||
cp "$ledger_src" "$target_dir/module-sql-ledger.txt"
|
||||
else
|
||||
log "ℹ️ Module SQL ledger not found (modules/meta missing); snapshot not included in this backup"
|
||||
fi
|
||||
|
||||
# Create completion marker to indicate backup is finished
|
||||
touch "$target_dir/.backup_complete"
|
||||
|
||||
|
||||
@@ -34,6 +34,35 @@ Notes:
|
||||
EOF
|
||||
}
|
||||
|
||||
verify_databases_populated() {
|
||||
local mysql_host="${CONTAINER_MYSQL:-ac-mysql}"
|
||||
local mysql_port="${MYSQL_PORT:-3306}"
|
||||
local mysql_user="${MYSQL_USER:-root}"
|
||||
local mysql_pass="${MYSQL_ROOT_PASSWORD:-root}"
|
||||
local db_auth="${DB_AUTH_NAME:-acore_auth}"
|
||||
local db_world="${DB_WORLD_NAME:-acore_world}"
|
||||
local db_characters="${DB_CHARACTERS_NAME:-acore_characters}"
|
||||
|
||||
if ! command -v mysql >/dev/null 2>&1; then
|
||||
echo "⚠️ mysql client is not available to verify restoration status"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local query="SELECT COUNT(*) FROM information_schema.tables WHERE table_schema IN ('$db_auth','$db_world','$db_characters');"
|
||||
local table_count
|
||||
if ! table_count=$(MYSQL_PWD="$mysql_pass" mysql -h "$mysql_host" -P "$mysql_port" -u "$mysql_user" -N -B -e "$query" 2>/dev/null); then
|
||||
echo "⚠️ Unable to query MySQL at ${mysql_host}:${mysql_port} to verify restoration status"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "${table_count:-0}" -gt 0 ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "⚠️ MySQL is reachable but no AzerothCore tables were found"
|
||||
return 1
|
||||
}
|
||||
|
||||
case "${1:-}" in
|
||||
-h|--help)
|
||||
print_help
|
||||
@@ -70,10 +99,17 @@ fi
|
||||
echo "🔍 Checking restoration status..."
|
||||
|
||||
if [ -f "$RESTORE_SUCCESS_MARKER" ]; then
|
||||
echo "✅ Backup restoration completed successfully"
|
||||
cat "$RESTORE_SUCCESS_MARKER" || true
|
||||
echo "🚫 Skipping database import - data already restored from backup"
|
||||
exit 0
|
||||
if verify_databases_populated; then
|
||||
echo "✅ Backup restoration completed successfully"
|
||||
cat "$RESTORE_SUCCESS_MARKER" || true
|
||||
echo "🚫 Skipping database import - data already restored from backup"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "⚠️ Restoration marker found, but databases are empty - forcing re-import"
|
||||
rm -f "$RESTORE_SUCCESS_MARKER" 2>/dev/null || true
|
||||
rm -f "$RESTORE_SUCCESS_MARKER_TMP" 2>/dev/null || true
|
||||
rm -f "$RESTORE_FAILED_MARKER" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
if [ -f "$RESTORE_FAILED_MARKER" ]; then
|
||||
@@ -352,6 +388,15 @@ EOF
|
||||
# Verify and apply missing updates
|
||||
verify_and_update_restored_databases
|
||||
|
||||
if [ -x "/tmp/restore-and-stage.sh" ]; then
|
||||
echo "🔧 Running restore-time module SQL staging..."
|
||||
MODULES_DIR="/modules" \
|
||||
RESTORE_SOURCE_DIR="$backup_path" \
|
||||
/tmp/restore-and-stage.sh
|
||||
else
|
||||
echo "ℹ️ restore-and-stage helper not available; skipping automatic module SQL staging"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
else
|
||||
echo "$(date): Backup restoration failed - proceeding with fresh setup" > "$RESTORE_FAILED_MARKER"
|
||||
|
||||
@@ -477,84 +477,11 @@ load_sql_helper(){
|
||||
err "SQL helper not found; expected manage-modules-sql.sh to be available"
|
||||
}
|
||||
|
||||
stage_module_sql_files(){
|
||||
# Stage SQL files to AzerothCore's native update directory structure
|
||||
# This replaces manual SQL execution with AzerothCore's built-in updater
|
||||
|
||||
local staging_dir="${MODULE_STAGING_DIR:-$MODULES_ROOT}"
|
||||
local sql_manifest="$STATE_DIR/.sql-manifest.json"
|
||||
|
||||
if [ ! -f "$sql_manifest" ]; then
|
||||
info "No SQL manifest found - no SQL files to stage"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Check if manifest has any modules with SQL
|
||||
local module_count
|
||||
module_count=$(python3 -c "import json; data=json.load(open('$sql_manifest')); print(len(data.get('modules', [])))" 2>/dev/null || echo "0")
|
||||
|
||||
if [ "$module_count" = "0" ]; then
|
||||
info "No modules with SQL files to stage"
|
||||
return 0
|
||||
fi
|
||||
|
||||
info "Staging SQL for $module_count module(s)"
|
||||
|
||||
# Read each module from manifest and stage its SQL
|
||||
local modules_json
|
||||
modules_json=$(python3 -c "import json; data=json.load(open('$sql_manifest')); print('\n'.join(m['name'] for m in data['modules']))" 2>/dev/null || echo "")
|
||||
|
||||
if [ -z "$modules_json" ]; then
|
||||
warn "Failed to parse SQL manifest"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local staged_count=0
|
||||
while IFS= read -r module_name; do
|
||||
if [ -z "$module_name" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
local module_path="$staging_dir/$module_name"
|
||||
local acore_modules="/azerothcore/modules/$module_name"
|
||||
|
||||
if [ ! -d "$module_path" ]; then
|
||||
warn "Module path not found: $module_path"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Call stage-module-sql.sh for this module
|
||||
local stage_script="${PROJECT_ROOT}/scripts/bash/stage-module-sql.sh"
|
||||
if [ ! -f "$stage_script" ]; then
|
||||
# Try container location
|
||||
stage_script="/scripts/bash/stage-module-sql.sh"
|
||||
fi
|
||||
|
||||
if [ -f "$stage_script" ]; then
|
||||
if "$stage_script" \
|
||||
--module-name "$module_name" \
|
||||
--module-path "$module_path" \
|
||||
--acore-path "$acore_modules"; then
|
||||
((staged_count++))
|
||||
fi
|
||||
else
|
||||
warn "SQL staging script not found: $stage_script"
|
||||
fi
|
||||
done <<< "$modules_json"
|
||||
|
||||
if [ "$staged_count" -gt 0 ]; then
|
||||
ok "Staged SQL for $staged_count module(s)"
|
||||
info "SQL will be applied by AzerothCore's updater on next server startup"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
execute_module_sql(){
|
||||
# Legacy function - now calls staging instead of direct execution
|
||||
SQL_EXECUTION_FAILED=0
|
||||
stage_module_sql_files || SQL_EXECUTION_FAILED=1
|
||||
}
|
||||
# REMOVED: stage_module_sql_files() and execute_module_sql()
|
||||
# These functions were part of build-time SQL staging that created files in
|
||||
# /azerothcore/modules/*/data/sql/updates/ which are NEVER scanned by AzerothCore's DBUpdater.
|
||||
# Module SQL is now staged at runtime by stage-modules.sh which copies files to
|
||||
# /azerothcore/data/sql/updates/ (core directory) where they ARE scanned and processed.
|
||||
|
||||
track_module_state(){
|
||||
echo 'Checking for module changes that require rebuild...'
|
||||
@@ -655,18 +582,11 @@ main(){
|
||||
remove_disabled_modules
|
||||
install_enabled_modules
|
||||
manage_configuration_files
|
||||
info "SQL staging gate: MODULES_SKIP_SQL=${MODULES_SKIP_SQL:-0}"
|
||||
if [ "${MODULES_SKIP_SQL:-0}" = "1" ]; then
|
||||
info "Skipping module SQL staging (MODULES_SKIP_SQL=1)"
|
||||
else
|
||||
info "Staging module SQL files for AzerothCore updater"
|
||||
execute_module_sql
|
||||
fi
|
||||
track_module_state
|
||||
# NOTE: Module SQL staging is now handled at runtime by stage-modules.sh
|
||||
# which copies SQL files to /azerothcore/data/sql/updates/ after containers start.
|
||||
# Build-time SQL staging has been removed as it created files that were never processed.
|
||||
|
||||
if [ "${SQL_EXECUTION_FAILED:-0}" = "1" ]; then
|
||||
warn "Module SQL execution reported issues; review logs above."
|
||||
fi
|
||||
track_module_state
|
||||
|
||||
echo 'Module management complete.'
|
||||
|
||||
|
||||
@@ -75,6 +75,13 @@ for db in "${dbs[@]}"; do
|
||||
echo "[manual] ✅ ${db}"
|
||||
done
|
||||
|
||||
ledger_src="/modules-meta/module-sql-ledger.txt"
|
||||
if [ -f "${ledger_src}" ]; then
|
||||
cp "${ledger_src}" "${TARGET_DIR}/module-sql-ledger.txt"
|
||||
else
|
||||
echo "[manual] ℹ️ Module SQL ledger not found; snapshot not included"
|
||||
fi
|
||||
|
||||
size="$(du -sh "${TARGET_DIR}" | cut -f1)"
|
||||
cat > "${TARGET_DIR}/manifest.json" <<EOF
|
||||
{
|
||||
|
||||
103
scripts/bash/restore-and-stage.sh
Executable file
103
scripts/bash/restore-and-stage.sh
Executable file
@@ -0,0 +1,103 @@
|
||||
#!/bin/bash
|
||||
# Refresh the module SQL ledger after a database restore so the runtime staging
|
||||
# flow knows exactly which files to copy into /azerothcore/data/sql/updates/*.
|
||||
set -euo pipefail
|
||||
|
||||
info(){ echo "🔧 [restore-stage] $*"; }
|
||||
warn(){ echo "⚠️ [restore-stage] $*" >&2; }
|
||||
|
||||
MODULES_DIR="${MODULES_DIR:-/modules}"
|
||||
RESTORE_SOURCE_DIR="${RESTORE_SOURCE_DIR:-}"
|
||||
MODULES_META_DIR="${MODULES_DIR}/.modules-meta"
|
||||
LEDGER_FILE="${MODULES_META_DIR}/module-sql-ledger.txt"
|
||||
RESTORE_FLAG="${MODULES_META_DIR}/.restore-prestaged"
|
||||
SNAPSHOT_FILE=""
|
||||
|
||||
ensure_modules_dir(){
|
||||
if [ ! -d "$MODULES_DIR" ]; then
|
||||
warn "Modules directory not found at ${MODULES_DIR}; skipping restore-time staging prep."
|
||||
exit 0
|
||||
fi
|
||||
}
|
||||
|
||||
hash_sql_file(){
|
||||
local sql_file="$1"
|
||||
if command -v sha1sum >/dev/null 2>&1; then
|
||||
sha1sum "$sql_file" | awk '{print $1}'
|
||||
elif command -v md5sum >/dev/null 2>&1; then
|
||||
md5sum "$sql_file" | awk '{print $1}'
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
collect_sql_files(){
|
||||
local db_type="$1" legacy="$2"
|
||||
local -a patterns=(
|
||||
"$MODULES_DIR"/*/data/sql/"$db_type"/*.sql
|
||||
"$MODULES_DIR"/*/data/sql/"$db_type"/base/*.sql
|
||||
"$MODULES_DIR"/*/data/sql/"$db_type"/updates/*.sql
|
||||
"$MODULES_DIR"/*/data/sql/"$legacy"/*.sql
|
||||
"$MODULES_DIR"/*/data/sql/"$legacy"/base/*.sql
|
||||
"$MODULES_DIR"/*/data/sql/"$legacy"/updates/*.sql
|
||||
)
|
||||
declare -A seen=()
|
||||
local -a files=()
|
||||
for pattern in "${patterns[@]}"; do
|
||||
for path in $pattern; do
|
||||
[ -f "$path" ] || continue
|
||||
if [ -z "${seen[$path]:-}" ]; then
|
||||
seen["$path"]=1
|
||||
files+=("$path")
|
||||
fi
|
||||
done
|
||||
done
|
||||
if [ ${#files[@]} -eq 0 ]; then
|
||||
return 0
|
||||
fi
|
||||
printf '%s\n' "${files[@]}" | sort
|
||||
}
|
||||
|
||||
rebuild_ledger(){
|
||||
local tmp_file
|
||||
tmp_file="$(mktemp)"
|
||||
for db_type in db-world db-characters db-auth; do
|
||||
local legacy=""
|
||||
case "$db_type" in
|
||||
db-world) legacy="world" ;;
|
||||
db-characters) legacy="characters" ;;
|
||||
db-auth) legacy="auth" ;;
|
||||
esac
|
||||
while IFS= read -r sql_file; do
|
||||
[ -n "$sql_file" ] || continue
|
||||
[ -f "$sql_file" ] || continue
|
||||
local module_name base_name hash
|
||||
module_name="$(echo "$sql_file" | sed 's|.*/modules/||' | cut -d'/' -f1)"
|
||||
base_name="$(basename "$sql_file" .sql)"
|
||||
if ! hash="$(hash_sql_file "$sql_file")"; then
|
||||
continue
|
||||
fi
|
||||
printf '%s|%s|%s|%s\n' "$db_type" "$module_name" "$base_name" "$hash" >> "$tmp_file"
|
||||
done < <(collect_sql_files "$db_type" "$legacy")
|
||||
done
|
||||
sort -u "$tmp_file" > "$LEDGER_FILE"
|
||||
rm -f "$tmp_file"
|
||||
}
|
||||
|
||||
ensure_modules_dir
|
||||
mkdir -p "$MODULES_META_DIR" 2>/dev/null || true
|
||||
|
||||
if [ -n "$RESTORE_SOURCE_DIR" ] && [ -f "${RESTORE_SOURCE_DIR}/module-sql-ledger.txt" ]; then
|
||||
SNAPSHOT_FILE="${RESTORE_SOURCE_DIR}/module-sql-ledger.txt"
|
||||
info "Snapshot found in backup (${SNAPSHOT_FILE}); syncing to host ledger."
|
||||
cp "$SNAPSHOT_FILE" "$LEDGER_FILE"
|
||||
else
|
||||
warn "Module SQL snapshot not found in backup; rebuilding ledger from module sources."
|
||||
rebuild_ledger
|
||||
fi
|
||||
|
||||
touch "$RESTORE_FLAG"
|
||||
echo "restore_at=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" > "$RESTORE_FLAG"
|
||||
|
||||
info "Ledger ready at ${LEDGER_FILE}; runtime staging will copy SQL before worldserver starts."
|
||||
info "Flagged ${RESTORE_FLAG} to force staging on next ./scripts/bash/stage-modules.sh run."
|
||||
@@ -1,297 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Stage Module SQL Files
|
||||
# Copies module SQL to AzerothCore's native update directory structure
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
|
||||
# Colors
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Icons
|
||||
ICON_SUCCESS="✅"
|
||||
ICON_WARNING="⚠️"
|
||||
ICON_ERROR="❌"
|
||||
ICON_INFO="ℹ️"
|
||||
|
||||
# Default values
|
||||
MODULE_NAME=""
|
||||
MODULE_PATH=""
|
||||
ACORE_PATH=""
|
||||
MANIFEST_PATH=""
|
||||
DRY_RUN=0
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: ./stage-module-sql.sh [options]
|
||||
|
||||
Stage module SQL files into AzerothCore's native update directory structure.
|
||||
|
||||
Options:
|
||||
--module-name NAME Module name (e.g., mod-aoe-loot)
|
||||
--module-path PATH Path to module repository
|
||||
--acore-path PATH Path to AzerothCore modules directory
|
||||
--manifest PATH Path to SQL manifest JSON (optional)
|
||||
--dry-run Show what would be staged without doing it
|
||||
-h, --help Show this help
|
||||
|
||||
Examples:
|
||||
./stage-module-sql.sh \
|
||||
--module-name mod-aoe-loot \
|
||||
--module-path /staging/mod-aoe-loot \
|
||||
--acore-path /azerothcore/modules/mod-aoe-loot
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# Parse arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--module-name) MODULE_NAME="$2"; shift 2;;
|
||||
--module-path) MODULE_PATH="$2"; shift 2;;
|
||||
--acore-path) ACORE_PATH="$2"; shift 2;;
|
||||
--manifest) MANIFEST_PATH="$2"; shift 2;;
|
||||
--dry-run) DRY_RUN=1; shift;;
|
||||
-h|--help) usage; exit 0;;
|
||||
*) echo "Unknown option: $1"; usage; exit 1;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Validate arguments
|
||||
if [ -z "$MODULE_NAME" ] || [ -z "$MODULE_PATH" ] || [ -z "$ACORE_PATH" ]; then
|
||||
echo -e "${RED}${ICON_ERROR} Missing required arguments${NC}"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "$MODULE_PATH" ]; then
|
||||
echo -e "${RED}${ICON_ERROR} Module path does not exist: $MODULE_PATH${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Logging functions
|
||||
info() {
|
||||
echo -e "${BLUE}${ICON_INFO}${NC} $*"
|
||||
}
|
||||
|
||||
ok() {
|
||||
echo -e "${GREEN}${ICON_SUCCESS}${NC} $*"
|
||||
}
|
||||
|
||||
warn() {
|
||||
echo -e "${YELLOW}${ICON_WARNING}${NC} $*"
|
||||
}
|
||||
|
||||
err() {
|
||||
echo -e "${RED}${ICON_ERROR}${NC} $*"
|
||||
}
|
||||
|
||||
# Generate timestamp-based filename
|
||||
generate_sql_timestamp() {
|
||||
# Format: YYYYMMDD_HH
|
||||
# Uses current time to ensure unique, sequential naming
|
||||
date +"%Y%m%d_%H"
|
||||
}
|
||||
|
||||
# Validate SQL file
|
||||
validate_sql_file() {
|
||||
local sql_file="$1"
|
||||
|
||||
if [ ! -f "$sql_file" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Basic validation - file should not be empty
|
||||
if [ ! -s "$sql_file" ]; then
|
||||
warn "SQL file is empty: $(basename "$sql_file")"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Check for shell commands (security check)
|
||||
if grep -qE '^\s*(system|exec|shell)' "$sql_file"; then
|
||||
err "SQL file contains suspicious shell commands: $(basename "$sql_file")"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Discover SQL files in module
|
||||
discover_module_sql() {
|
||||
local module_path="$1"
|
||||
local sql_base="$module_path/data/sql"
|
||||
|
||||
if [ ! -d "$sql_base" ]; then
|
||||
# No SQL directory, not an error
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Search in base/, updates/, and custom/ directories
|
||||
local -A sql_files
|
||||
|
||||
# Support both underscore (db_world) and hyphen (db-world) naming conventions
|
||||
local -A db_variants=(
|
||||
["db_auth"]="db_auth db-auth"
|
||||
["db_world"]="db_world db-world"
|
||||
["db_characters"]="db_characters db-characters"
|
||||
["db_playerbots"]="db_playerbots db-playerbots"
|
||||
)
|
||||
|
||||
for canonical_type in db_auth db_world db_characters db_playerbots; do
|
||||
for variant in ${db_variants[$canonical_type]}; do
|
||||
# Check base/
|
||||
if [ -d "$sql_base/base/$variant" ]; then
|
||||
while IFS= read -r -d '' file; do
|
||||
sql_files["$canonical_type"]+="$file"$'\n'
|
||||
done < <(find "$sql_base/base/$variant" -name "*.sql" -type f -print0 2>/dev/null)
|
||||
fi
|
||||
|
||||
# Check updates/
|
||||
if [ -d "$sql_base/updates/$variant" ]; then
|
||||
while IFS= read -r -d '' file; do
|
||||
sql_files["$canonical_type"]+="$file"$'\n'
|
||||
done < <(find "$sql_base/updates/$variant" -name "*.sql" -type f -print0 2>/dev/null)
|
||||
fi
|
||||
|
||||
# Check custom/
|
||||
if [ -d "$sql_base/custom/$variant" ]; then
|
||||
while IFS= read -r -d '' file; do
|
||||
sql_files["$canonical_type"]+="$file"$'\n'
|
||||
done < <(find "$sql_base/custom/$variant" -name "*.sql" -type f -print0 2>/dev/null)
|
||||
fi
|
||||
|
||||
# ALSO check direct db-type directories (legacy format used by many modules)
|
||||
if [ -d "$sql_base/$variant" ]; then
|
||||
while IFS= read -r -d '' file; do
|
||||
sql_files["$canonical_type"]+="$file"$'\n'
|
||||
done < <(find "$sql_base/$variant" -name "*.sql" -type f -print0 2>/dev/null)
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# Print discovered files
|
||||
for db_type in "${!sql_files[@]}"; do
|
||||
echo "$db_type"
|
||||
echo "${sql_files[$db_type]}"
|
||||
done
|
||||
}
|
||||
|
||||
# Stage single SQL file
|
||||
stage_sql_file() {
|
||||
local source_file="$1"
|
||||
local target_dir="$2"
|
||||
local module_name="$3"
|
||||
local counter="$4"
|
||||
|
||||
# Validate source file
|
||||
if ! validate_sql_file "$source_file"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Generate target filename
|
||||
local timestamp
|
||||
timestamp=$(generate_sql_timestamp)
|
||||
local basename
|
||||
basename=$(basename "$source_file" .sql)
|
||||
local target_file="$target_dir/${timestamp}_${counter}_${module_name}_${basename}.sql"
|
||||
|
||||
# Create target directory
|
||||
if [ "$DRY_RUN" = "0" ]; then
|
||||
mkdir -p "$target_dir"
|
||||
fi
|
||||
|
||||
# Copy file
|
||||
if [ "$DRY_RUN" = "1" ]; then
|
||||
info "Would stage: $(basename "$source_file") -> $(basename "$target_file")"
|
||||
else
|
||||
if cp "$source_file" "$target_file"; then
|
||||
ok "Staged: $(basename "$target_file")"
|
||||
else
|
||||
err "Failed to stage: $(basename "$source_file")"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Stage all SQL for module
|
||||
stage_module_sql() {
|
||||
local module_name="$1"
|
||||
local module_path="$2"
|
||||
local acore_path="$3"
|
||||
|
||||
info "Staging SQL for module: $module_name"
|
||||
|
||||
# Discover SQL files
|
||||
local sql_discovery
|
||||
sql_discovery=$(discover_module_sql "$module_path")
|
||||
|
||||
if [ -z "$sql_discovery" ]; then
|
||||
info "No SQL files found in module"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Parse discovery output
|
||||
local current_db=""
|
||||
local counter=1
|
||||
local staged_count=0
|
||||
|
||||
while IFS= read -r line; do
|
||||
if [ -z "$line" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Check if this is a database type line
|
||||
if [[ "$line" =~ ^db_(auth|world|characters|playerbots)$ ]]; then
|
||||
current_db="$line"
|
||||
counter=1
|
||||
continue
|
||||
fi
|
||||
|
||||
# This is a file path
|
||||
if [ -n "$current_db" ] && [ -f "$line" ]; then
|
||||
# AzerothCore expects db_world, db_auth, etc. (WITH db_ prefix)
|
||||
local target_dir="$acore_path/data/sql/updates/$current_db"
|
||||
|
||||
if stage_sql_file "$line" "$target_dir" "$module_name" "$counter"; then
|
||||
((staged_count++))
|
||||
((counter++))
|
||||
fi
|
||||
fi
|
||||
done <<< "$sql_discovery"
|
||||
|
||||
if [ "$staged_count" -gt 0 ]; then
|
||||
ok "Staged $staged_count SQL file(s) for $module_name"
|
||||
else
|
||||
warn "No SQL files staged for $module_name"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Main execution
|
||||
main() {
|
||||
echo
|
||||
info "Module SQL Staging"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo
|
||||
|
||||
if [ "$DRY_RUN" = "1" ]; then
|
||||
warn "DRY RUN MODE - No files will be modified"
|
||||
echo
|
||||
fi
|
||||
|
||||
stage_module_sql "$MODULE_NAME" "$MODULE_PATH" "$ACORE_PATH"
|
||||
|
||||
echo
|
||||
ok "SQL staging complete"
|
||||
echo
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@@ -17,6 +17,97 @@ show_staging_step(){
|
||||
printf '%b\n' "${YELLOW}🔧 ${step}: ${message}...${NC}"
|
||||
}
|
||||
|
||||
ensure_host_writable(){
|
||||
local target="$1"
|
||||
[ -n "$target" ] || return 0
|
||||
if [ -d "$target" ] || mkdir -p "$target" 2>/dev/null; then
|
||||
local uid gid
|
||||
uid="$(id -u)"
|
||||
gid="$(id -g)"
|
||||
if ! chown -R "$uid":"$gid" "$target" 2>/dev/null; then
|
||||
if command -v docker >/dev/null 2>&1; then
|
||||
local helper_image
|
||||
helper_image="$(read_env ALPINE_IMAGE "alpine:latest")"
|
||||
docker run --rm \
|
||||
-u 0:0 \
|
||||
-v "$target":/workspace \
|
||||
"$helper_image" \
|
||||
sh -c "chown -R ${uid}:${gid} /workspace" >/dev/null 2>&1 || true
|
||||
fi
|
||||
fi
|
||||
chmod -R u+rwX "$target" 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
seed_sql_ledger_if_needed(){
|
||||
local sentinel="$1" ledger="$2"
|
||||
mkdir -p "$(dirname "$ledger")" 2>/dev/null || true
|
||||
|
||||
local need_seed=0
|
||||
local reason=""
|
||||
if [ ! -f "$ledger" ] || [ ! -s "$ledger" ]; then
|
||||
need_seed=1
|
||||
reason="Module SQL ledger missing; rebuilding."
|
||||
elif [ -f "$sentinel" ] && [ "$sentinel" -nt "$ledger" ]; then
|
||||
need_seed=1
|
||||
reason="Database restore detected; seeding module SQL ledger."
|
||||
fi
|
||||
|
||||
if [ "$need_seed" -ne 1 ]; then
|
||||
touch "$ledger" 2>/dev/null || true
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "↻ ${reason}"
|
||||
|
||||
local tmp_file="${ledger}.tmp"
|
||||
> "$tmp_file"
|
||||
|
||||
shopt -s nullglob
|
||||
for db_type in db-world db-characters db-auth; do
|
||||
local legacy_name=""
|
||||
case "$db_type" in
|
||||
db-world) legacy_name="world" ;;
|
||||
db-characters) legacy_name="characters" ;;
|
||||
db-auth) legacy_name="auth" ;;
|
||||
esac
|
||||
|
||||
local search_paths=(
|
||||
"$MODULES_DIR"/*/data/sql/"$db_type"
|
||||
"$MODULES_DIR"/*/data/sql/"$db_type"/base
|
||||
"$MODULES_DIR"/*/data/sql/"$db_type"/updates
|
||||
"$MODULES_DIR"/*/data/sql/"$legacy_name"
|
||||
"$MODULES_DIR"/*/data/sql/"$legacy_name"/base
|
||||
)
|
||||
|
||||
for module_dir in "${search_paths[@]}"; do
|
||||
for sql_file in "$module_dir"/*.sql; do
|
||||
[ -e "$sql_file" ] || continue
|
||||
local module_name
|
||||
module_name="$(echo "$sql_file" | sed 's|.*/modules/||' | cut -d'/' -f1)"
|
||||
local base_name
|
||||
base_name="$(basename "$sql_file" .sql)"
|
||||
local hash_cmd=""
|
||||
if command -v sha1sum >/dev/null 2>&1; then
|
||||
hash_cmd="sha1sum"
|
||||
elif command -v md5sum >/dev/null 2>&1; then
|
||||
hash_cmd="md5sum"
|
||||
fi
|
||||
local file_hash=""
|
||||
if [ -n "$hash_cmd" ]; then
|
||||
file_hash=$($hash_cmd "$sql_file" | awk '{print $1}')
|
||||
fi
|
||||
[ -n "$file_hash" ] || continue
|
||||
printf '%s|%s|%s|%s\n' "$db_type" "$module_name" "$base_name" "$file_hash" >> "$tmp_file"
|
||||
done
|
||||
done
|
||||
done
|
||||
shopt -u nullglob
|
||||
|
||||
sort -u "$tmp_file" > "$ledger"
|
||||
rm -f "$tmp_file"
|
||||
}
|
||||
|
||||
sync_local_staging(){
|
||||
local src_root="$LOCAL_STORAGE_PATH"
|
||||
local dest_root="$STORAGE_PATH"
|
||||
@@ -53,6 +144,10 @@ sync_local_staging(){
|
||||
return
|
||||
fi
|
||||
|
||||
# Ensure both source and destination trees are writable by the host user.
|
||||
ensure_host_writable "$src_modules"
|
||||
ensure_host_writable "$dest_modules"
|
||||
|
||||
if command -v rsync >/dev/null 2>&1; then
|
||||
# rsync may return exit code 23 (permission warnings) in WSL2 - these are harmless
|
||||
rsync -a --delete "$src_modules"/ "$dest_modules"/ || {
|
||||
@@ -229,6 +324,34 @@ if [[ "$LOCAL_STORAGE_PATH" != /* ]]; then
|
||||
fi
|
||||
LOCAL_STORAGE_PATH="$(canonical_path "$LOCAL_STORAGE_PATH")"
|
||||
SENTINEL_FILE="$LOCAL_STORAGE_PATH/modules/.requires_rebuild"
|
||||
MODULES_META_DIR="$STORAGE_PATH/modules/.modules-meta"
|
||||
MODULES_SQL_LEDGER_HOST="$MODULES_META_DIR/module-sql-ledger.txt"
|
||||
RESTORE_PRESTAGED_FLAG="$MODULES_META_DIR/.restore-prestaged"
|
||||
MODULES_ENABLED_FILE="$MODULES_META_DIR/modules-enabled.txt"
|
||||
|
||||
declare -A ENABLED_MODULES=()
|
||||
|
||||
load_enabled_modules(){
|
||||
ENABLED_MODULES=()
|
||||
if [ -f "$MODULES_ENABLED_FILE" ]; then
|
||||
while IFS= read -r enabled_module; do
|
||||
enabled_module="$(echo "$enabled_module" | tr -d '\r')"
|
||||
[ -n "$enabled_module" ] || continue
|
||||
ENABLED_MODULES["$enabled_module"]=1
|
||||
done < "$MODULES_ENABLED_FILE"
|
||||
fi
|
||||
}
|
||||
|
||||
module_is_enabled(){
|
||||
local module_dir="$1"
|
||||
if [ ${#ENABLED_MODULES[@]} -eq 0 ]; then
|
||||
return 0
|
||||
fi
|
||||
if [ -n "${ENABLED_MODULES[$module_dir]:-}" ]; then
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# Define module mappings (from rebuild-with-modules.sh)
|
||||
declare -A MODULE_REPO_MAP=(
|
||||
@@ -347,9 +470,12 @@ fi
|
||||
# Stage the services
|
||||
show_staging_step "Service Orchestration" "Preparing realm services"
|
||||
sync_local_staging
|
||||
|
||||
echo "🎬 Staging services with profile: services-$TARGET_PROFILE"
|
||||
echo "⏳ Pulling images and starting containers; this can take several minutes on first run."
|
||||
|
||||
load_enabled_modules
|
||||
|
||||
# Stop any currently running services
|
||||
echo "🛑 Stopping current services..."
|
||||
docker compose \
|
||||
@@ -392,6 +518,11 @@ stage_module_sql_to_core() {
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ -f "$RESTORE_PRESTAGED_FLAG" ]; then
|
||||
echo "↻ Restore pipeline detected (flag: $RESTORE_PRESTAGED_FLAG); re-staging module SQL so worldserver can apply updates."
|
||||
rm -f "$RESTORE_PRESTAGED_FLAG" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
echo "📦 Staging module SQL files to core updates directory..."
|
||||
|
||||
# Create core updates directories inside container
|
||||
@@ -403,52 +534,220 @@ stage_module_sql_to_core() {
|
||||
|
||||
# Stage SQL from all modules
|
||||
local staged_count=0
|
||||
local timestamp=$(date +"%Y_%m_%d_%H%M%S")
|
||||
local total_skipped=0
|
||||
local total_failed=0
|
||||
local RESTORE_SENTINEL="$LOCAL_STORAGE_PATH/mysql-data/.restore-completed"
|
||||
ensure_host_writable "$MODULES_META_DIR"
|
||||
seed_sql_ledger_if_needed "$RESTORE_SENTINEL" "$MODULES_SQL_LEDGER_HOST"
|
||||
docker exec ac-worldserver bash -c "find /azerothcore/data/sql/updates -name '*_MODULE_*.sql' -delete" >/dev/null 2>&1 || true
|
||||
|
||||
# Find all modules with SQL files
|
||||
shopt -s nullglob
|
||||
for db_type in db-world db-characters db-auth; do
|
||||
local core_dir=""
|
||||
local legacy_name=""
|
||||
case "$db_type" in
|
||||
db-world) core_dir="db_world" ;;
|
||||
db-characters) core_dir="db_characters" ;;
|
||||
db-auth) core_dir="db_auth" ;;
|
||||
db-world)
|
||||
core_dir="db_world"
|
||||
legacy_name="world" # Some modules use 'world' instead of 'db-world'
|
||||
;;
|
||||
db-characters)
|
||||
core_dir="db_characters"
|
||||
legacy_name="characters"
|
||||
;;
|
||||
db-auth)
|
||||
core_dir="db_auth"
|
||||
legacy_name="auth"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Copy SQL files from each module
|
||||
docker exec ac-worldserver bash -c "
|
||||
counter=0
|
||||
for module_dir in /azerothcore/modules/*/data/sql/$db_type; do
|
||||
if [ -d \"\$module_dir\" ]; then
|
||||
module_name=\$(basename \$(dirname \$(dirname \$module_dir)))
|
||||
for sql_file in \"\$module_dir\"/*.sql; do
|
||||
if [ -f \"\$sql_file\" ]; then
|
||||
base_name=\$(basename \"\$sql_file\" .sql)
|
||||
target_name=\"${timestamp}_\${counter}_MODULE_\${module_name}_\${base_name}.sql\"
|
||||
cp \"\$sql_file\" \"/azerothcore/data/sql/updates/$core_dir/\$target_name\"
|
||||
echo \" ✓ Staged \$module_name/$db_type/\$(basename \$sql_file)\"
|
||||
counter=\$((counter + 1))
|
||||
fi
|
||||
done
|
||||
docker exec ac-worldserver bash -c "mkdir -p /azerothcore/data/sql/updates/$core_dir" >/dev/null 2>&1 || true
|
||||
|
||||
local counter=0
|
||||
local skipped=0
|
||||
local failed=0
|
||||
|
||||
local search_paths=(
|
||||
"$MODULES_DIR"/*/data/sql/"$db_type"
|
||||
"$MODULES_DIR"/*/data/sql/"$db_type"/base
|
||||
"$MODULES_DIR"/*/data/sql/"$db_type"/updates
|
||||
"$MODULES_DIR"/*/data/sql/"$legacy_name"
|
||||
"$MODULES_DIR"/*/data/sql/"$legacy_name"/base
|
||||
)
|
||||
|
||||
for module_dir in "${search_paths[@]}"; do
|
||||
for sql_file in "$module_dir"/*.sql; do
|
||||
[ -e "$sql_file" ] || continue
|
||||
|
||||
if [ ! -f "$sql_file" ] || [ ! -s "$sql_file" ]; then
|
||||
echo " ⚠️ Skipped empty or invalid: $(basename "$sql_file")"
|
||||
skipped=$((skipped + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
if grep -qE '^[[:space:]]*(system|exec|shell|!)' "$sql_file" 2>/dev/null; then
|
||||
echo " ❌ Security: Rejected $(basename "$(dirname "$module_dir")")/$(basename "$sql_file") (contains shell commands)"
|
||||
failed=$((failed + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
local module_name
|
||||
module_name="$(echo "$sql_file" | sed 's|.*/modules/||' | cut -d'/' -f1)"
|
||||
local base_name
|
||||
base_name="$(basename "$sql_file" .sql)"
|
||||
local update_identifier="MODULE_${module_name}_${base_name}"
|
||||
|
||||
if ! module_is_enabled "$module_name"; then
|
||||
echo " ⏭️ Skipped $module_name/$db_type/$(basename "$sql_file") (module disabled)"
|
||||
skipped=$((skipped + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
local hash_cmd=""
|
||||
if command -v sha1sum >/dev/null 2>&1; then
|
||||
hash_cmd="sha1sum"
|
||||
elif command -v md5sum >/dev/null 2>&1; then
|
||||
hash_cmd="md5sum"
|
||||
fi
|
||||
|
||||
local file_hash=""
|
||||
if [ -n "$hash_cmd" ]; then
|
||||
file_hash=$($hash_cmd "$sql_file" | awk '{print $1}')
|
||||
fi
|
||||
local ledger_key="$db_type|$module_name|$base_name"
|
||||
local target_name="MODULE_${module_name}_${base_name}.sql"
|
||||
if docker cp "$sql_file" "ac-worldserver:/azerothcore/data/sql/updates/$core_dir/$target_name" >/dev/null; then
|
||||
echo " ✓ Staged $module_name/$db_type/$(basename "$sql_file")"
|
||||
counter=$((counter + 1))
|
||||
if [ -n "$file_hash" ]; then
|
||||
local tmp_file="${MODULES_SQL_LEDGER_HOST}.tmp"
|
||||
grep -Fv "${ledger_key}|" "$MODULES_SQL_LEDGER_HOST" > "$tmp_file" 2>/dev/null || true
|
||||
printf '%s|%s\n' "$ledger_key" "$file_hash" >> "$tmp_file"
|
||||
mv "$tmp_file" "$MODULES_SQL_LEDGER_HOST" 2>/dev/null || true
|
||||
fi
|
||||
else
|
||||
echo " ❌ Failed to copy: $module_name/$(basename "$sql_file")"
|
||||
failed=$((failed + 1))
|
||||
fi
|
||||
done
|
||||
echo \$counter
|
||||
" 2>/dev/null | tee /tmp/stage-sql-output.txt || true
|
||||
done
|
||||
|
||||
staged_count=$((staged_count + counter))
|
||||
total_skipped=$((total_skipped + skipped))
|
||||
total_failed=$((total_failed + failed))
|
||||
|
||||
local count=$(tail -1 /tmp/stage-sql-output.txt 2>/dev/null || echo "0")
|
||||
staged_count=$((staged_count + count))
|
||||
done
|
||||
shopt -u nullglob
|
||||
|
||||
echo ""
|
||||
if [ "$staged_count" -gt 0 ]; then
|
||||
echo "✅ Staged $staged_count module SQL files to core updates directory"
|
||||
[ "$total_skipped" -gt 0 ] && echo "⚠️ Skipped $total_skipped empty/invalid file(s)"
|
||||
[ "$total_failed" -gt 0 ] && echo "❌ Failed to stage $total_failed file(s)"
|
||||
echo "🔄 Restart worldserver to apply: docker restart ac-worldserver"
|
||||
else
|
||||
echo "ℹ️ No module SQL files found to stage"
|
||||
fi
|
||||
}
|
||||
|
||||
get_module_dbc_path(){
|
||||
local module_name="$1"
|
||||
local manifest_file="$PROJECT_DIR/config/module-manifest.json"
|
||||
|
||||
if [ ! -f "$manifest_file" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if command -v jq >/dev/null 2>&1; then
|
||||
local dbc_path
|
||||
dbc_path=$(jq -r ".modules[] | select(.name == \"$module_name\") | .server_dbc_path // empty" "$manifest_file" 2>/dev/null)
|
||||
if [ -n "$dbc_path" ]; then
|
||||
echo "$dbc_path"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
stage_module_dbc_files(){
|
||||
show_staging_step "Module DBC Staging" "Deploying binary DBC files to server"
|
||||
|
||||
if ! docker ps --format '{{.Names}}' | grep -q "ac-worldserver"; then
|
||||
echo "⚠️ Worldserver container not found, skipping module DBC staging"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "📦 Staging module DBC files to server data directory..."
|
||||
echo " (Using manifest 'server_dbc_path' field to locate server-side DBC files)"
|
||||
|
||||
local staged_count=0
|
||||
local skipped=0
|
||||
local failed=0
|
||||
|
||||
shopt -s nullglob
|
||||
for module_path in "$MODULES_DIR"/*; do
|
||||
[ -d "$module_path" ] || continue
|
||||
local module_name="$(basename "$module_path")"
|
||||
|
||||
# Skip disabled modules
|
||||
if ! module_is_enabled "$module_name"; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Get DBC path from manifest
|
||||
local dbc_path
|
||||
if ! dbc_path=$(get_module_dbc_path "$module_name"); then
|
||||
# No server_dbc_path defined in manifest - skip this module
|
||||
continue
|
||||
fi
|
||||
|
||||
local dbc_dir="$module_path/$dbc_path"
|
||||
if [ ! -d "$dbc_dir" ]; then
|
||||
echo " ⚠️ $module_name: DBC directory not found at $dbc_path"
|
||||
skipped=$((skipped + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
for dbc_file in "$dbc_dir"/*.dbc; do
|
||||
[ -e "$dbc_file" ] || continue
|
||||
|
||||
if [ ! -f "$dbc_file" ] || [ ! -s "$dbc_file" ]; then
|
||||
echo " ⚠️ Skipped empty or invalid: $module_name/$(basename "$dbc_file")"
|
||||
skipped=$((skipped + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
local dbc_filename="$(basename "$dbc_file")"
|
||||
|
||||
# Copy to worldserver DBC directory
|
||||
if docker cp "$dbc_file" "ac-worldserver:/azerothcore/data/dbc/$dbc_filename" >/dev/null 2>&1; then
|
||||
echo " ✓ Staged $module_name → $dbc_filename"
|
||||
staged_count=$((staged_count + 1))
|
||||
else
|
||||
echo " ❌ Failed to copy: $module_name/$dbc_filename"
|
||||
failed=$((failed + 1))
|
||||
fi
|
||||
done
|
||||
done
|
||||
shopt -u nullglob
|
||||
|
||||
echo ""
|
||||
if [ "$staged_count" -gt 0 ]; then
|
||||
echo "✅ Staged $staged_count module DBC files to server data directory"
|
||||
[ "$skipped" -gt 0 ] && echo "⚠️ Skipped $skipped file(s) (no server_dbc_path in manifest)"
|
||||
[ "$failed" -gt 0 ] && echo "❌ Failed to stage $failed file(s)"
|
||||
echo "🔄 Restart worldserver to load new DBC data: docker restart ac-worldserver"
|
||||
else
|
||||
echo "ℹ️ No module DBC files found to stage (use 'server_dbc_path' in manifest to enable)"
|
||||
fi
|
||||
}
|
||||
|
||||
# Stage module SQL (this will also start the containers)
|
||||
stage_module_sql_to_core
|
||||
|
||||
# Stage module DBC files
|
||||
stage_module_dbc_files
|
||||
|
||||
printf '\n%b\n' "${GREEN}⚔️ Realm staging completed successfully! ⚔️${NC}"
|
||||
printf '%b\n' "${GREEN}🏰 Profile: services-$TARGET_PROFILE${NC}"
|
||||
printf '%b\n' "${GREEN}🗡️ Your realm is ready for adventure!${NC}"
|
||||
|
||||
@@ -33,7 +33,7 @@ info() {
|
||||
|
||||
ok() {
|
||||
echo -e "${GREEN}${ICON_SUCCESS}${NC} $*"
|
||||
((TESTS_PASSED++))
|
||||
((TESTS_PASSED+=1))
|
||||
}
|
||||
|
||||
warn() {
|
||||
@@ -42,11 +42,11 @@ warn() {
|
||||
|
||||
err() {
|
||||
echo -e "${RED}${ICON_ERROR}${NC} $*"
|
||||
((TESTS_FAILED++))
|
||||
((TESTS_FAILED+=1))
|
||||
}
|
||||
|
||||
test_header() {
|
||||
((TESTS_TOTAL++))
|
||||
((TESTS_TOTAL+=1))
|
||||
echo ""
|
||||
echo -e "${BOLD}${ICON_TEST} Test $TESTS_TOTAL: $*${NC}"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
@@ -192,7 +192,6 @@ fi
|
||||
# Test 7: Verify new scripts exist and are executable
|
||||
test_header "New Script Verification"
|
||||
scripts=(
|
||||
"scripts/bash/stage-module-sql.sh"
|
||||
"scripts/bash/verify-sql-updates.sh"
|
||||
"scripts/bash/backup-status.sh"
|
||||
"scripts/bash/db-health-check.sh"
|
||||
@@ -214,11 +213,17 @@ done
|
||||
|
||||
# Test 8: Test backup-status.sh (without running containers)
|
||||
test_header "Backup Status Script Test"
|
||||
if ./scripts/bash/backup-status.sh 2>&1 | head -10 | grep -q "BACKUP STATUS"; then
|
||||
ok "backup-status.sh executes successfully"
|
||||
backup_status_log="$(mktemp)"
|
||||
if ./scripts/bash/backup-status.sh >"$backup_status_log" 2>&1; then
|
||||
if grep -q "BACKUP STATUS" "$backup_status_log"; then
|
||||
ok "backup-status.sh executes successfully"
|
||||
else
|
||||
err "backup-status.sh output missing 'BACKUP STATUS' marker"
|
||||
fi
|
||||
else
|
||||
err "backup-status.sh failed to execute"
|
||||
fi
|
||||
rm -f "$backup_status_log"
|
||||
|
||||
# Test 9: Test db-health-check.sh help
|
||||
test_header "Database Health Check Script Test"
|
||||
@@ -231,11 +236,11 @@ fi
|
||||
# Test 10: Check modified scripts for new functionality
|
||||
test_header "Modified Script Verification"
|
||||
|
||||
# Check manage-modules.sh has staging function
|
||||
if grep -q "stage_module_sql_files()" scripts/bash/manage-modules.sh; then
|
||||
ok "manage-modules.sh contains SQL staging function"
|
||||
# Check stage-modules.sh has runtime SQL staging function
|
||||
if grep -q "stage_module_sql_to_core()" scripts/bash/stage-modules.sh; then
|
||||
ok "stage-modules.sh contains runtime SQL staging function"
|
||||
else
|
||||
err "manage-modules.sh missing SQL staging function"
|
||||
err "stage-modules.sh missing runtime SQL staging function"
|
||||
fi
|
||||
|
||||
# Check db-import-conditional.sh has playerbots support
|
||||
@@ -251,6 +256,13 @@ else
|
||||
warn "db-import-conditional.sh may have incorrect EnableDatabases value"
|
||||
fi
|
||||
|
||||
# Check for restore marker safety net
|
||||
if grep -q "verify_databases_populated" scripts/bash/db-import-conditional.sh; then
|
||||
ok "db-import-conditional.sh verifies live MySQL state before honoring restore markers"
|
||||
else
|
||||
err "db-import-conditional.sh missing restore marker safety check"
|
||||
fi
|
||||
|
||||
# Check for post-restore verification
|
||||
if grep -q "verify_and_update_restored_databases" scripts/bash/db-import-conditional.sh; then
|
||||
ok "db-import-conditional.sh has post-restore verification"
|
||||
@@ -258,7 +270,17 @@ else
|
||||
err "db-import-conditional.sh missing post-restore verification"
|
||||
fi
|
||||
|
||||
# Test 11: Docker Compose configuration check
|
||||
# Test 11: Restore + Module Staging Automation
|
||||
test_header "Restore + Module Staging Automation"
|
||||
if grep -q "restore-and-stage.sh" docker-compose.yml && \
|
||||
grep -q ".restore-prestaged" scripts/bash/restore-and-stage.sh && \
|
||||
grep -q "module-sql-ledger" scripts/bash/restore-and-stage.sh; then
|
||||
ok "restore-and-stage.sh wired into compose, refreshes ledger snapshot, and flags staging"
|
||||
else
|
||||
err "restore-and-stage.sh missing compose wiring or ledger/flag handling"
|
||||
fi
|
||||
|
||||
# Test 12: Docker Compose configuration check
|
||||
test_header "Docker Compose Configuration Check"
|
||||
if [ -f docker-compose.yml ]; then
|
||||
ok "docker-compose.yml exists"
|
||||
|
||||
Reference in New Issue
Block a user