This commit introduces major enhancements to the module installation system, database management, and configuration handling for AzerothCore deployments. ## Module System Improvements ### Module SQL Staging & Installation - Refactor module SQL staging to properly handle AzerothCore's sql/ directory structure - Fix SQL staging path to use correct AzerothCore format (sql/custom/db_*/*) - Implement conditional module database importing based on enabled modules - Add support for both cpp-modules and lua-scripts module types - Handle rsync exit code 23 (permission warnings) gracefully during deployment ### Module Manifest & Automation - Add automated module manifest generation via GitHub Actions workflow - Implement Python-based module manifest updater with comprehensive validation - Add module dependency tracking and SQL file discovery - Support for blocked modules and module metadata management ## Database Management Enhancements ### Database Import System - Add db-guard container for continuous database health monitoring and verification - Implement conditional database import that skips when databases are current - Add backup restoration and SQL staging coordination - Support for Playerbots database (4th database) in all import operations - Add comprehensive database health checking and status reporting ### Database Configuration - Implement 10 new dbimport.conf settings from environment variables: - Database.Reconnect.Seconds/Attempts for connection reliability - Updates.AllowedModules for module auto-update control - Updates.Redundancy for data integrity checks - Worker/Synch thread settings for all three core databases - Auto-apply dbimport.conf settings via auto-post-install.sh - Add environment variable injection for db-import and db-guard containers ### Backup & Recovery - Fix backup scheduler to prevent immediate execution on container startup - Add backup status monitoring script with detailed reporting - Implement backup import/export utilities - Add database verification scripts for SQL update tracking ## User Import Directory - Add new import/ directory for user-provided database files and configurations - Support for custom SQL files, configuration overrides, and example templates - Automatic import of user-provided databases and configs during initialization - Documentation and examples for custom database imports ## Configuration & Environment - Eliminate CLIENT_DATA_VERSION warning by adding default value syntax - Improve CLIENT_DATA_VERSION documentation in .env.template - Add comprehensive database import settings to .env and .env.template - Update setup.sh to handle new configuration variables with proper defaults ## Monitoring & Debugging - Add status dashboard with Go-based terminal UI (statusdash.go) - Implement JSON status output (statusjson.sh) for programmatic access - Add comprehensive database health check script - Add repair-storage-permissions.sh utility for permission issues ## Testing & Documentation - Add Phase 1 integration test suite for module installation verification - Add comprehensive documentation for: - Database management (DATABASE_MANAGEMENT.md) - Module SQL analysis (AZEROTHCORE_MODULE_SQL_ANALYSIS.md) - Implementation mapping (IMPLEMENTATION_MAP.md) - SQL staging comparison and path coverage - Module assets and DBC file requirements - Update SCRIPTS.md, ADVANCED.md, and troubleshooting documentation - Update references from database-import/ to import/ directory ## Breaking Changes - Renamed database-import/ directory to import/ for clarity - Module SQL files now staged to AzerothCore-compatible paths - db-guard container now required for proper database lifecycle management ## Bug Fixes - Fix module SQL staging directory structure for AzerothCore compatibility - Handle rsync exit code 23 gracefully during deployments - Prevent backup from running immediately on container startup - Correct SQL staging paths for proper module installation
28 KiB
Phase 1: Module SQL Refactor - Implementation Context
Created: 2025-01-14 Status: Ready to Begin Estimated Duration: 2-3 days Risk Level: Medium-High (core functionality change)
Executive Summary
Phase 1 refactors module SQL management from manual execution to leveraging AzerothCore's native update system. This is the foundation for all subsequent improvements.
Key Goal: Stop manually executing module SQL; let AzerothCore's built-in updater handle it.
Impact:
- ✅ Reduces custom code by ~200 lines
- ✅ Adds proper update tracking with hash verification
- ✅ Prevents duplicate SQL execution
- ✅ Integrates playerbots database properly
- ✅ Enables automatic post-restore verification
Current State Analysis
How Module SQL Works Now (Manual Execution)
Flow:
1. Module enabled in .env
↓
2. manage-modules.sh clones module repo
↓
3. SQL files copied to /tmp/scripts/sql/custom/
↓
4. manage-modules-sql.sh MANUALLY executes SQL
↓
5. Success/failure tracked in bash arrays
↓
6. No permanent record of execution
Problems:
- No redundancy checking - SQL can run multiple times
- No update tracking - Not in
updatestable - No hash verification - Can't detect changes
- Custom execution logic - ~250 lines of bash
- Playerbots special handling - Template replacement
- No rollback capability - Can't undo SQL
- Manual state management - Bash arrays, not DB
Relevant Files (Current Implementation)
1. scripts/bash/manage-modules-sql.sh (381 lines)
# Key functions:
render_sql_file_for_execution() # Lines 16-46: Playerbots template replacement
mysql_exec() # Lines 60-72: MySQL wrapper
playerbots_table_exists() # Lines 74-79: Playerbots detection
run_custom_sql_group() # Lines 81-112: Main execution loop
execute_module_sql_scripts() # Lines 180-230: Orchestration
# SQL execution happens here:
mysql_exec "${target_db}" < "$rendered" # Line 102
2. scripts/bash/manage-modules.sh (616 lines)
# SQL helper invocation:
source "$SQL_HELPER_PATH" # Line 599
execute_module_sql_scripts # Line 603
# Module staging location:
MODULES_HOST_DIR="$staging_modules_dir" # Line 438
3. scripts/python/modules.py (546 lines)
# Module metadata management
class ModuleState:
key: str
name: str
repo: str
type: str # "cpp", "lua", "data", "tool"
enabled: bool
# NO SQL file tracking currently
4. scripts/bash/db-import-conditional.sh (340 lines)
# dbimport.conf generation:
cat > /azerothcore/env/dist/etc/dbimport.conf <<EOF
LoginDatabaseInfo = "..."
WorldDatabaseInfo = "..."
CharacterDatabaseInfo = "..."
Updates.EnableDatabases = 7 # Line 314: Missing playerbots
Updates.AutoSetup = 1 # Line 315
Updates.AllowedModules = "all" # Line 318
EOF
# Runs dbimport:
./dbimport # Line 331
5. scripts/bash/auto-post-install.sh (190 lines)
# Config updates:
sed -i "s|^LoginDatabaseInfo.*|..." authserver.conf # Line 139
sed -i "s|^WorldDatabaseInfo.*|..." worldserver.conf # Line 141
# Missing: PlayerbotsDatabaseInfo in dbimport
Target State (After Phase 1)
How Module SQL Will Work (AzerothCore Native)
Flow:
1. Module enabled in .env
↓
2. manage-modules.sh clones module repo
↓
3. stage-module-sql.sh copies SQL to AzerothCore structure:
modules/<module>/data/sql/updates/db_world/YYYYMMDD_HH_<desc>.sql
↓
4. dbimport (or worldserver startup) detects new SQL
↓
5. AzerothCore's updater applies SQL automatically
↓
6. Updates tracked in `updates` table with hash
↓
7. verify-sql-updates.sh confirms application
Benefits:
- ✅ Hash-based redundancy - Won't re-apply same SQL
- ✅ Automatic tracking - In
updatestable with state='MODULE' - ✅ Change detection - Hash mismatch triggers re-apply
- ✅ Standard mechanism - Uses AzerothCore's proven system
- ✅ No special cases - Playerbots handled same way
- ✅ Audit trail - timestamps, execution speed tracked
- ✅ Database-driven - State in DB, not files
Implementation Plan
Step 1: Create New Helper Scripts (Low Risk)
1.1 Create scripts/bash/stage-module-sql.sh
Purpose: Copy module SQL files to AzerothCore's update directory structure
Functions:
stage_module_sql() {
# Input: Module name, module repo path
# Output: SQL files in /azerothcore/modules/<name>/data/sql/
# 1. Discover SQL files in module repo
# 2. Generate timestamp-based filenames
# 3. Copy to proper database subdirectory
# 4. Validate SQL syntax
# 5. Log staging results
}
generate_sql_timestamp() {
# Create YYYYMMDD_HH format from current time
# Ensures unique, sequential naming
}
validate_sql_file() {
# Basic SQL syntax check
# Ensure no shell commands
# Check for playerbots references
}
discover_module_sql() {
# Find all .sql files in module
# Determine target database (auth/world/characters)
# Return list of files to stage
}
Target Directory Structure:
/azerothcore/modules/
├── mod-aoe-loot/
│ └── data/
│ └── sql/
│ └── updates/
│ └── db_world/
│ └── 20250114_01_aoe_loot_config.sql
├── mod-learn-spells/
│ └── data/
│ └── sql/
│ └── updates/
│ └── db_world/
│ └── 20250114_02_learn_spells_init.sql
└── [other modules...]
Estimated Lines: ~150
1.2 Create scripts/bash/verify-sql-updates.sh
Purpose: Verify SQL updates in updates table
Functions:
verify_module_sql() {
# Check if module SQL appears in updates table
# Parameters: module_name, database_name
mysql -e "SELECT name, hash, timestamp
FROM ${database}.updates
WHERE name LIKE '%${module}%'
AND state='MODULE'"
}
list_module_updates() {
# Show all module updates across all databases
# Group by module name
# Show counts and timestamps
}
check_update_applied() {
# Verify specific SQL file was applied
# Parameters: filename, expected_hash
# Returns: 0 if applied, 1 if missing, 2 if hash mismatch
}
verify_sql_hash() {
# Calculate hash of SQL file
# Compare with hash in updates table
# Report mismatches
}
generate_verification_report() {
# Summary of all module SQL status
# Missing updates
# Hash mismatches
# Application timestamps
}
Output Example:
🔍 Module SQL Verification Report
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ mod-aoe-loot (db_world)
- 20250114_01_aoe_loot_config.sql
Hash: 4B17F90847D05B7EDFBDC01F86560307226110AA ✓
Applied: 2025-01-14 14:30:22
Speed: 45ms
✅ mod-learn-spells (db_world)
- 20250114_02_learn_spells_init.sql
Hash: 8356D5D01BC87D838AFBB32A6062C15B5DFBACA5 ✓
Applied: 2025-01-14 14:30:25
Speed: 32ms
⚠️ mod-playerbots (db_playerbots)
- Missing: 20250114_03_playerbots_schema.sql
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Total: 2 applied, 1 missing, 0 hash mismatches
Estimated Lines: ~100
Step 2: Modify Python Module System (Medium Risk)
2.1 Update scripts/python/modules.py
Current ModuleState class:
@dataclass
class ModuleState:
key: str
name: str
repo: str
ref: str
type: str
status: str
enabled: bool
# ... other fields
Add SQL discovery:
@dataclass
class ModuleState:
# ... existing fields ...
sql_files: List[str] = field(default_factory=list)
sql_databases: Dict[str, List[str]] = field(default_factory=dict)
def discover_sql_files(module_path: Path) -> Dict[str, List[Path]]:
"""
Scan module for SQL files
Returns: {
'db_auth': [Path('file1.sql'), ...],
'db_world': [Path('file2.sql'), ...],
'db_characters': [Path('file3.sql'), ...]
}
"""
sql_files = {}
sql_base = module_path / 'data' / 'sql'
for db_type in ['db_auth', 'db_world', 'db_characters', 'db_playerbots']:
# Check base/
base_dir = sql_base / 'base' / db_type
if base_dir.exists():
sql_files.setdefault(db_type, []).extend(base_dir.glob('*.sql'))
# Check updates/
updates_dir = sql_base / 'updates' / db_type
if updates_dir.exists():
sql_files.setdefault(db_type, []).extend(updates_dir.glob('*.sql'))
# Check custom/
custom_dir = sql_base / 'custom' / db_type
if custom_dir.exists():
sql_files.setdefault(db_type, []).extend(custom_dir.glob('*.sql'))
return sql_files
Generate SQL staging manifest:
def generate_sql_manifest(state: ModuleCollectionState, output_dir: Path):
"""
Create manifest of SQL files to stage
Output: {
"modules": [
{
"name": "mod-aoe-loot",
"sql_files": {
"db_world": ["path/to/file1.sql", ...]
}
}
]
}
"""
Changes:
- Add
discover_sql_files()function (~30 lines) - Update
ModuleStatedataclass (+2 fields) - Add to
build_state()function (+10 lines) - Generate SQL manifest in
write_outputs()(+10 lines)
Total: +40 lines
Step 3: Update Module Management (Medium Risk)
3.1 Modify scripts/bash/manage-modules.sh
Current SQL handling (lines 472-606):
# Source SQL helper
if [ -f "$helper_path" ]; then
SQL_HELPER_PATH="$helper_path"
fi
# Execute SQL
if [ "${MODULES_SKIP_SQL:-0}" != "1" ]; then
source "$SQL_HELPER_PATH"
execute_module_sql_scripts
fi
New SQL handling:
# Stage SQL files instead of executing
stage_module_sql_files() {
local staging_dir="$1" # Module staging directory
local source_dir="$2" # AzerothCore source directory
# Read SQL manifest from modules.py output
local manifest="$staging_dir/.sql-manifest.json"
if [ ! -f "$manifest" ]; then
info "No SQL files to stage"
return 0
fi
# Call stage-module-sql.sh for each module
while read -r module_name; do
local module_repo="$staging_dir/$module_name"
local acore_modules="$source_dir/modules/$module_name"
info "Staging SQL for $module_name"
"$PROJECT_ROOT/scripts/bash/stage-module-sql.sh" \
--module-name "$module_name" \
--module-path "$module_repo" \
--acore-path "$acore_modules" \
--manifest "$manifest"
done < <(jq -r '.modules[].name' "$manifest")
}
# Replace SQL execution with staging
if [ "${MODULES_SKIP_SQL:-0}" != "1" ]; then
stage_module_sql_files "$staging_modules_dir" "$(get_acore_source_path)"
info "Module SQL staged for application by AzerothCore updater"
else
info "Skipping module SQL staging (MODULES_SKIP_SQL=1)"
fi
Changes:
- Replace
source "$SQL_HELPER_PATH"with staging call - Add
stage_module_sql_files()function (+30 lines) - Remove
execute_module_sql_scriptsinvocation (-10 lines) - Add verification call (+10 lines)
Total: +30 lines
3.2 Refactor scripts/bash/manage-modules-sql.sh
Current size: 381 lines
Remove (will become obsolete):
# Lines 16-46: render_sql_file_for_execution() - 31 lines
# Lines 60-72: mysql_exec() - 13 lines
# Lines 74-79: playerbots_table_exists() - 6 lines
# Lines 81-112: run_custom_sql_group() - 32 lines
# Lines 180-230: execute_module_sql_scripts() - 51 lines
# Total removed: ~133 lines
Keep (still useful):
# Logging functions
log_sql_success() # Lines 48-52
log_sql_failure() # Lines 54-58
# Module metadata loading
ensure_module_metadata() # Lines 114-178
Add (new functionality):
# Wrapper functions for backward compatibility
stage_sql_for_module() {
# Calls stage-module-sql.sh
# Maintains interface for existing callers
}
verify_staged_sql() {
# Calls verify-sql-updates.sh
# Reports verification results
}
New size: ~181 lines (-200 lines!)
Note: This file may eventually be removed entirely if no longer needed
Step 4: Integrate Playerbots Database (Low Risk)
4.1 Update scripts/bash/db-import-conditional.sh
Current dbimport.conf (lines 310-327):
cat > /azerothcore/env/dist/etc/dbimport.conf <<EOF
LoginDatabaseInfo = "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_AUTH_NAME}"
WorldDatabaseInfo = "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_WORLD_NAME}"
CharacterDatabaseInfo = "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_CHARACTERS_NAME}"
Updates.EnableDatabases = 7
Updates.AutoSetup = 1
TempDir = "${TEMP_DIR}"
MySQLExecutable = "${MYSQL_EXECUTABLE}"
Updates.AllowedModules = "all"
EOF
New dbimport.conf:
cat > /azerothcore/env/dist/etc/dbimport.conf <<EOF
LoginDatabaseInfo = "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_AUTH_NAME}"
WorldDatabaseInfo = "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_WORLD_NAME}"
CharacterDatabaseInfo = "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_CHARACTERS_NAME}"
PlayerbotsDatabaseInfo = "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_PLAYERBOTS_NAME}"
Updates.EnableDatabases = 15
Updates.AutoSetup = 1
TempDir = "${TEMP_DIR}"
MySQLExecutable = "${MYSQL_EXECUTABLE}"
Updates.AllowedModules = "all"
EOF
Changes:
- Add
PlayerbotsDatabaseInfoline (+1 line) - Change
Updates.EnableDatabases = 7to15(1 line change)- 7 = 1 (auth) + 2 (char) + 4 (world)
- 15 = 1 + 2 + 4 + 8 (playerbots)
Note: Requires AzerothCore source to support PlayerbotsDatabaseInfo. If not supported, this becomes a future enhancement.
4.2 Add Post-Restore Verification
Current restore completion (lines 283-290):
if restore_backup "$backup_path"; then
echo "$(date): Backup successfully restored from $backup_path" > "$RESTORE_SUCCESS_MARKER"
echo "🎉 Backup restoration completed successfully!"
exit 0
fi
New with verification:
if restore_backup "$backup_path"; then
echo "$(date): Backup successfully restored from $backup_path" > "$RESTORE_SUCCESS_MARKER"
echo "🎉 Backup restoration completed successfully!"
# Verify and apply missing updates
verify_and_update_restored_databases
exit 0
fi
verify_and_update_restored_databases() {
echo "🔍 Verifying restored database integrity..."
# Check if dbimport is available
if [ ! -f "/azerothcore/env/dist/bin/dbimport" ]; then
warn "dbimport not available, skipping verification"
return 0
fi
cd /azerothcore/env/dist/bin
# Run dbimport to check state (will apply missing updates)
echo "Running dbimport to apply any missing updates..."
if ./dbimport; then
ok "Database verification complete - all updates current"
else
warn "dbimport reported issues - check logs"
return 1
fi
# Verify critical tables exist
echo "Checking critical tables..."
local critical_tables=("account" "characters" "creature" "quest_template")
local missing_tables=0
for table in "${critical_tables[@]}"; do
# Determine database based on table
local db_name="$DB_WORLD_NAME"
case "$table" in
account) db_name="$DB_AUTH_NAME" ;;
characters) db_name="$DB_CHARACTERS_NAME" ;;
esac
if ! mysql -h ${CONTAINER_MYSQL} -u${MYSQL_USER} -p${MYSQL_ROOT_PASSWORD} \
-e "SELECT 1 FROM ${db_name}.${table} LIMIT 1" >/dev/null 2>&1; then
warn "Critical table missing: ${db_name}.${table}"
missing_tables=$((missing_tables + 1))
fi
done
if [ "$missing_tables" -gt 0 ]; then
warn "${missing_tables} critical tables missing after restore"
return 1
fi
ok "All critical tables verified"
return 0
}
Changes:
- Add
verify_and_update_restored_databases()function (+55 lines) - Call after successful restore (+3 lines)
- Check dbimport availability (+5 lines)
- Verify critical tables (+15 lines)
Total: +65 lines
4.3 Update scripts/bash/auto-post-install.sh
Current config updates (lines 139-143):
sed -i "s|^LoginDatabaseInfo.*|LoginDatabaseInfo = \"${MYSQL_HOST};...\"|" /azerothcore/config/authserver.conf
sed -i "s|^LoginDatabaseInfo.*|LoginDatabaseInfo = \"${MYSQL_HOST};...\"|" /azerothcore/config/worldserver.conf
sed -i "s|^WorldDatabaseInfo.*|WorldDatabaseInfo = \"${MYSQL_HOST};...\"|" /azerothcore/config/worldserver.conf
sed -i "s|^CharacterDatabaseInfo.*|CharacterDatabaseInfo = \"${MYSQL_HOST};...\"|" /azerothcore/config/worldserver.conf
Add playerbots to worldserver.conf:
# After existing database info updates
ensure_config_key /azerothcore/config/worldserver.conf \
"PlayerbotsDatabaseInfo" \
"\"${MYSQL_HOST};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_PLAYERBOTS_NAME}\""
Changes:
- Already has
ensure_config_key()function (lines 146-158) - Add one more call (+3 lines)
- Update comment (+2 lines)
Total: +5 lines
File Change Summary
| File | Current Lines | Changes | New Lines | Net |
|---|---|---|---|---|
stage-module-sql.sh |
0 (new) | +150 | 150 | +150 |
verify-sql-updates.sh |
0 (new) | +100 | 100 | +100 |
manage-modules-sql.sh |
381 | -200 | 181 | -200 |
manage-modules.sh |
616 | +30 | 646 | +30 |
modules.py |
546 | +40 | 586 | +40 |
db-import-conditional.sh |
340 | +65 | 405 | +65 |
auto-post-install.sh |
190 | +5 | 195 | +5 |
| TOTAL | 2,073 | 2,263 | +190 |
Note: While we add 190 net lines, we eliminate 200 lines of complex SQL execution logic and replace it with simple staging calls. The new code is cleaner and leverages AzerothCore's proven system.
Testing Strategy
Unit Tests (Per Component)
Test 1: SQL Staging (stage-module-sql.sh)
Test Cases:
- Stage SQL from module with only db_world files
- Stage SQL from module with multiple database types
- Handle module with no SQL files (graceful skip)
- Generate proper timestamp-based filenames
- Validate SQL syntax (catch obvious errors)
- Handle duplicate staging (idempotent)
Test Script:
# Create test module structure
mkdir -p /tmp/test-module/data/sql/updates/db_world
echo "CREATE TABLE test (id INT);" > /tmp/test-module/data/sql/updates/db_world/test.sql
# Run staging
./scripts/bash/stage-module-sql.sh \
--module-name test-module \
--module-path /tmp/test-module \
--acore-path /tmp/acore-test
# Verify staged files exist
ls /tmp/acore-test/data/sql/updates/db_world/ | grep "test-module"
# Cleanup
rm -rf /tmp/test-module /tmp/acore-test
Test 2: SQL Verification (verify-sql-updates.sh)
Test Cases:
- Verify SQL with proper hash match
- Detect missing SQL (in files but not in updates table)
- Detect hash mismatch (file changed after application)
- List all module updates across databases
- Generate verification report
Requires: Running MySQL with test data
Test 3: Module SQL Discovery (modules.py)
Test Cases:
def test_discover_sql_files():
# Create test module structure
test_module = Path('/tmp/test-module')
(test_module / 'data/sql/updates/db_world').mkdir(parents=True)
(test_module / 'data/sql/updates/db_world/test.sql').write_text('SELECT 1;')
# Run discovery
sql_files = discover_sql_files(test_module)
# Verify results
assert 'db_world' in sql_files
assert len(sql_files['db_world']) == 1
assert sql_files['db_world'][0].name == 'test.sql'
Integration Tests (Full Flow)
Integration Test 1: Fresh Module Install
Scenario: Install module with SQL for the first time
Steps:
- Enable new module in .env (e.g.,
MODULE_AOE_LOOT=1) - Run
./scripts/bash/manage-modules.sh - Verify SQL staged to
/azerothcore/modules/mod-aoe-loot/data/sql/ - Start worldserver
- Check
updatestable for module SQL:SELECT * FROM acore_world.updates WHERE name LIKE '%aoe-loot%' AND state='MODULE'; - Verify module functionality works
Expected Result:
- SQL staged correctly
- Updates applied on server startup
- Tracked in
updatestable - Module functions correctly
Integration Test 2: Module Reinstall (Idempotency)
Scenario: Reinstall same module (should not re-apply SQL)
Steps:
- Module already installed (from Test 1)
- Run
./scripts/bash/manage-modules.shagain - Start worldserver again
- Check logs for "already applied" or "skipped" messages
Expected Result:
- SQL not re-applied (hash matches)
- No errors in logs
- Module still works
Integration Test 3: Playerbots Integration
Scenario: Install playerbots module with SQL
Steps:
- Enable
MODULE_PLAYERBOTS=1 - Run module installation
- Verify playerbots SQL staged
- Check dbimport.conf has
PlayerbotsDatabaseInfo - Check
Updates.EnableDatabases = 15 - Start worldserver
- Query playerbots database updates:
SELECT * FROM acore_playerbots.updates WHERE state='MODULE';
Expected Result:
- Playerbots SQL applied to playerbots database
- No template replacement needed
- Tracked in updates table
Integration Test 4: Post-Restore Verification
Scenario: Restore old backup, verify updates applied
Steps:
- Create backup with current state
- Add new module (e.g.,
MODULE_FIREWORKS=1) - Let SQL apply
- Restore old backup (before new module)
- System should detect missing SQL
- dbimport should apply missing updates
Expected Result:
- Backup restored successfully
- Verification detects missing updates
- Updates applied automatically
- Server starts with all modules working
Regression Tests
Regression Test 1: Existing Modules Still Work
Modules to Test:
- mod-aoe-loot
- mod-learn-spells
- mod-autobalance
- mod-playerbots
Verification:
- All modules load without errors
- SQL properly applied (check updates table)
- In-game functionality works
Regression Test 2: Backup/Restore Still Works
Test:
- Create backup with new system
- Restore backup
- Verify all databases restored
- Verify modules work after restore
Performance Tests
Performance Test 1: Module Installation Time
Measure:
- Time to install 10 modules
- Before refactor (manual execution): X seconds
- After refactor (staging only): Y seconds
Expected: Faster (no SQL execution, just file copies)
Performance Test 2: Server Startup Time
Measure:
- Time for worldserver to become ready
- With 0 modules, 5 modules, 10 modules
- Monitor dbimport execution time
Expected: Slightly longer first time (applying all module SQL), then same or faster (cached in updates table)
Rollback Plan
If Phase 1 Fails
Immediate Rollback Steps:
-
Revert code changes:
git checkout HEAD -- scripts/bash/manage-modules-sql.sh git checkout HEAD -- scripts/bash/manage-modules.sh git checkout HEAD -- scripts/python/modules.py git checkout HEAD -- scripts/bash/db-import-conditional.sh git checkout HEAD -- scripts/bash/auto-post-install.sh rm scripts/bash/stage-module-sql.sh rm scripts/bash/verify-sql-updates.sh -
Clear staged SQL:
# Remove staged SQL from AzerothCore modules rm -rf local-storage/source/azerothcore-*/modules/mod-*/data/sql/ -
Restore SQL to old location:
# Re-run module installation with old code ./scripts/bash/manage-modules.sh -
Verify rollback:
- Check modules work
- Verify SQL execution logs
- Test module functionality in-game
Partial Rollback (Keep Some Changes)
If only specific parts fail:
Keep:
- Quick win scripts (health check, backup status)
- Documentation
Revert:
- Module SQL staging
- dbimport.conf playerbots integration
Selectively revert:
# Keep post-restore verification, revert staging
git checkout HEAD -- scripts/bash/manage-modules-sql.sh
git checkout HEAD -- scripts/bash/manage-modules.sh
# Keep db-import-conditional.sh changes (verification)
Success Criteria
Must Have (Phase 1 Complete)
✅ Functionality:
- Module SQL applied via AzerothCore updater (not manual execution)
- SQL tracked in
updatestable withstate='MODULE' - Hash verification prevents duplicate execution
- Playerbots database integrated into dbimport
- Post-restore verification applies missing updates
- All existing modules still work
✅ Code Quality:
manage-modules-sql.shreduced by ~200 lines- No regression in existing functionality
- Tests pass (unit + integration)
- Error handling improved
- Logging comprehensive
✅ Documentation:
- Changes documented in CHANGELOG
- Implementation map updated
- Migration guide for users
Nice to Have (Can Defer)
🔲 Module SQL rollback capability 🔲 SQL syntax validation (beyond basic) 🔲 Automated performance benchmarks 🔲 Migration tool for existing installations
Risk Mitigation
High Risk: Module SQL Not Applied
Mitigation:
- Comprehensive testing with multiple modules
- Fallback to manual execution if staging fails
- Clear error messages with recovery steps
- Verification script to detect missing SQL
Detection:
- Health check shows missing module updates
- Modules don't work in-game
- Logs show "command not found" for module features
Recovery:
- Manually apply SQL from module repo
- Re-stage SQL files
- Check dbimport logs for errors
Medium Risk: Playerbots Database Issues
Mitigation:
- Make playerbots integration optional (env var)
- Fallback to old behavior if not supported
- Test with and without playerbots enabled
Detection:
- dbimport fails with "unknown database" error
- Playerbots module doesn't install
Recovery:
- Revert playerbots integration
- Use separate SQL execution for playerbots
- Document as future enhancement
Medium Risk: Performance Regression
Mitigation:
- Benchmark before and after
- Monitor server startup times
- Limit concurrent SQL application
Detection:
- Server takes longer to start
- dbimport runs slowly
Recovery:
- Optimize SQL file count
- Batch updates
- Use
Updates.ArchivedRedundancy = 0
Dependencies & Prerequisites
Software Requirements
- ✅ Python 3.x with jq available
- ✅ AzerothCore source with dbimport tool
- ✅ MySQL client (docker exec or host)
- ✅ Bash 4.0+
Environment Requirements
- ✅
.envfile configured - ✅ Module manifest exists
- ✅ MySQL container running
- ✅ AzerothCore source directory accessible
Data Requirements
- ✅ At least one module with SQL to test
- ✅ Backup available for restore testing
- ✅ Test database for unit tests
Timeline
Day 1: Foundation
Morning (4 hours):
- Create
stage-module-sql.sh(150 lines) - Unit test SQL staging
- Fix any issues
Afternoon (4 hours):
- Create
verify-sql-updates.sh(100 lines) - Unit test verification
- Test with sample SQL
Evening (2 hours):
- Documentation
- Code review
- Commit: "Add SQL staging and verification helpers"
Day 2: Integration
Morning (4 hours):
- Update
modules.pySQL discovery (+40 lines) - Test SQL discovery with real modules
- Update
manage-modules.shstaging calls (+30 lines)
Afternoon (4 hours):
- Refactor
manage-modules-sql.sh(-200 lines) - Test with single module end-to-end
- Fix any integration issues
Evening (2 hours):
- Integration testing (3-5 modules)
- Document any issues
- Commit: "Integrate SQL staging into module management"
Day 3: Finalization
Morning (4 hours):
- Update
db-import-conditional.shverification (+65 lines) - Update
auto-post-install.shplayerbots (+5 lines) - Test backup/restore flow
Afternoon (4 hours):
- Full regression testing
- Performance testing
- Documentation updates
Evening (2 hours):
- Final review
- Create migration guide
- Commit: "Complete Phase 1 - Module SQL refactor"
- Tag:
v1.0-phase1
Next Steps After Phase 1
- Monitor production usage (1 week)
- Collect feedback from any issues
- Begin Phase 2 (Verification & Monitoring)
- Document lessons learned
End of Phase 1 Context