1 Commits

Author SHA1 Message Date
uprightbass360
9960444425 cleanup: better variable handling 2026-01-02 01:50:18 -05:00
29 changed files with 105 additions and 2388 deletions

View File

@@ -1,321 +0,0 @@
# ================================================================================
# AzerothCore RealmMaster - Pre-Built Images Configuration
# ================================================================================
# Use this minimal configuration file to deploy pre-built RealmMaster images
# from Docker Hub. No local building required!
#
# Quick Start:
# 1. Copy this file: cp .env.prebuilt .env
# 2. Set your DOCKERHUB_USERNAME below
# 3. Run: ./deploy.sh
#
# The pre-built images include 32 modules from the RealmMaster profile:
# - Playerbots, Transmog, Solo LFG, Eluna, NPC Buffer, and 27 more
# - See config/module-profiles/RealmMaster.json for full list
# ================================================================================
# =====================
# REQUIRED: Docker Hub Configuration
# =====================
# Set this to your Docker Hub username where the images are published
DOCKERHUB_USERNAME=your-dockerhub-username
# =====================
# Project Configuration
# =====================
COMPOSE_PROJECT_NAME=azerothcore-realmmaster
# =====================
# Module Profile Selection
# =====================
# Choose which module profile build to use:
# - realmmaster: 32 modules (playerbots, transmog, solo-lfg, eluna, etc.) - ✅ Available now (Recommended)
#
# Additional profiles (available soon - will be built on demand):
# - suggested-modules: Alternative suggested module set
# - all-modules: All supported modules
# - playerbots-only: Just playerbots
#
# Note: Only 'realmmaster' images are currently published to Docker Hub.
# Other profiles will be available when built via GitHub Actions workflow.
MODULE_PROFILE=realmmaster
# =====================
# Pre-Built Images from Docker Hub
# =====================
# These images are built nightly with different module profiles
# Using profile-specific tags ensures you get the exact module set you want
AC_AUTHSERVER_IMAGE_MODULES=${DOCKERHUB_USERNAME}/${COMPOSE_PROJECT_NAME}:authserver-${MODULE_PROFILE}-latest
AC_WORLDSERVER_IMAGE_MODULES=${DOCKERHUB_USERNAME}/${COMPOSE_PROJECT_NAME}:worldserver-${MODULE_PROFILE}-latest
# Alternative: Use date-tagged images for version pinning
# AC_AUTHSERVER_IMAGE_MODULES=${DOCKERHUB_USERNAME}/${COMPOSE_PROJECT_NAME}:authserver-${MODULE_PROFILE}-20260109
# AC_WORLDSERVER_IMAGE_MODULES=${DOCKERHUB_USERNAME}/${COMPOSE_PROJECT_NAME}:worldserver-${MODULE_PROFILE}-20260109
# Alternative: Use generic latest tags (default: realmmaster profile)
# AC_AUTHSERVER_IMAGE_MODULES=${DOCKERHUB_USERNAME}/${COMPOSE_PROJECT_NAME}:authserver-latest
# AC_WORLDSERVER_IMAGE_MODULES=${DOCKERHUB_USERNAME}/${COMPOSE_PROJECT_NAME}:worldserver-latest
# Standard images (fallback if modules images not available)
AC_AUTHSERVER_IMAGE=acore/ac-wotlk-authserver:master
AC_WORLDSERVER_IMAGE=acore/ac-wotlk-worldserver:master
# Playerbots images (referenced by docker-compose, even if using modules profile)
AC_AUTHSERVER_IMAGE_PLAYERBOTS=${COMPOSE_PROJECT_NAME}:authserver-playerbots
AC_WORLDSERVER_IMAGE_PLAYERBOTS=${COMPOSE_PROJECT_NAME}:worldserver-playerbots
AC_CLIENT_DATA_IMAGE_PLAYERBOTS=${COMPOSE_PROJECT_NAME}:client-data-playerbots
# Database and client data images
AC_DB_IMPORT_IMAGE=acore/ac-wotlk-db-import:master
AC_CLIENT_DATA_IMAGE=acore/ac-wotlk-client-data:master
# Helper images
ALPINE_IMAGE=alpine:latest
MYSQL_IMAGE=mysql:8.0
# =====================
# Storage Paths
# =====================
STORAGE_PATH=./storage
STORAGE_PATH_LOCAL=./local-storage
STORAGE_CONFIG_PATH=${STORAGE_PATH}/config
STORAGE_LOGS_PATH=${STORAGE_PATH}/logs
STORAGE_MODULES_PATH=${STORAGE_PATH}/modules
STORAGE_LUA_SCRIPTS_PATH=${STORAGE_PATH}/lua_scripts
STORAGE_MODULE_SQL_PATH=${STORAGE_PATH}/module-sql-updates
STORAGE_INSTALL_MARKERS_PATH=${STORAGE_PATH}/install-markers
STORAGE_CLIENT_DATA_PATH=${STORAGE_PATH}/client-data
BACKUP_PATH=${STORAGE_PATH}/backups
# =====================
# Timezone
# =====================
HOST_ZONEINFO_PATH=/usr/share/zoneinfo
TZ=UTC
# =====================
# Networking
# =====================
NETWORK_NAME=azerothcore
NETWORK_SUBNET=172.20.0.0/16
NETWORK_GATEWAY=172.20.0.1
# =====================
# Server Address & Realm
# =====================
# Change this to your server's public IP or domain name
SERVER_ADDRESS=127.0.0.1
REALM_PORT=8215
# =====================
# Ports
# =====================
# Authentication server
AUTH_EXTERNAL_PORT=3784
AUTH_PORT=3724
# World server
WORLD_EXTERNAL_PORT=8215
WORLD_PORT=8085
# SOAP/Remote access
SOAP_EXTERNAL_PORT=7778
SOAP_PORT=7878
# MySQL database (for external access)
MYSQL_EXTERNAL_PORT=64306
# phpMyAdmin web interface
PMA_EXTERNAL_PORT=8081
# Keira3 editor interface
KEIRA3_EXTERNAL_PORT=4201
# =====================
# MySQL Database Configuration
# =====================
MYSQL_IMAGE=mysql:8.0
CONTAINER_MYSQL=ac-mysql
MYSQL_HOST=ac-mysql
MYSQL_PORT=3306
# Security: Change these passwords!
MYSQL_ROOT_PASSWORD=azerothcore123
MYSQL_ROOT_HOST=%
MYSQL_USER=root
# Database names
DB_AUTH_NAME=acore_auth
DB_WORLD_NAME=acore_world
DB_CHARACTERS_NAME=acore_characters
DB_PLAYERBOTS_NAME=acore_playerbots
# Database performance settings
MYSQL_CHARACTER_SET=utf8mb4
MYSQL_COLLATION=utf8mb4_unicode_ci
MYSQL_MAX_CONNECTIONS=1000
MYSQL_INNODB_BUFFER_POOL_SIZE=256M
MYSQL_INNODB_LOG_FILE_SIZE=64M
MYSQL_INNODB_REDO_LOG_CAPACITY=512M
# MySQL tmpfs (RAM disk) for performance
MYSQL_RUNTIME_TMPFS_SIZE=8G
MYSQL_DISABLE_BINLOG=1
# Database connection settings
DB_WAIT_RETRIES=60
DB_WAIT_SLEEP=10
DB_RECONNECT_SECONDS=5
DB_RECONNECT_ATTEMPTS=5
# Database worker threads
DB_LOGIN_WORKER_THREADS=1
DB_WORLD_WORKER_THREADS=1
DB_CHARACTER_WORKER_THREADS=1
DB_LOGIN_SYNCH_THREADS=1
DB_WORLD_SYNCH_THREADS=1
DB_CHARACTER_SYNCH_THREADS=1
# =====================
# Automated Backups
# =====================
BACKUP_RETENTION_DAYS=3
BACKUP_RETENTION_HOURS=6
BACKUP_DAILY_TIME=09:00
BACKUP_INTERVAL_MINUTES=60
BACKUP_EXTRA_DATABASES=
BACKUP_HEALTHCHECK_MAX_MINUTES=1440
BACKUP_HEALTHCHECK_GRACE_SECONDS=4500
# =====================
# Module Configuration (Pre-Built)
# =====================
# These settings tell the system that modules are already built into the images
STACK_IMAGE_MODE=modules
STACK_SOURCE_VARIANT=playerbots
# Key modules enabled (needed for profile detection)
# The RealmMaster profile includes playerbots, so we need this set for deploy.sh to use the correct profile
MODULE_PLAYERBOTS=1
# Note: MODULES_ENABLED_LIST varies by profile - the list below is for the 'realmmaster' profile
# For other profiles, see the corresponding JSON in config/module-profiles/
MODULES_ENABLED_LIST=MODULE_PLAYERBOTS,MODULE_TRANSMOG,MODULE_SOLO_LFG,MODULE_ELUNA,MODULE_AIO,MODULE_NPC_BUFFER,MODULE_NPC_BEASTMASTER,MODULE_SOLOCRAFT,MODULE_1V1_ARENA,MODULE_ACCOUNT_ACHIEVEMENTS,MODULE_ACTIVE_CHAT,MODULE_ARAC,MODULE_ASSISTANT,MODULE_AUTO_REVIVE,MODULE_BLACK_MARKET_AUCTION_HOUSE,MODULE_BOSS_ANNOUNCER,MODULE_BREAKING_NEWS,MODULE_ELUNA_SCRIPTS,MODULE_EVENT_SCRIPTS,MODULE_FIREWORKS,MODULE_GAIN_HONOR_GUARD,MODULE_GLOBAL_CHAT,MODULE_GUILDHOUSE,MODULE_INSTANCE_RESET,MODULE_ITEM_LEVEL_UP,MODULE_LEARN_SPELLS,MODULE_MORPHSUMMON,MODULE_NPC_ENCHANTER,MODULE_NPC_FREE_PROFESSIONS,MODULE_RANDOM_ENCHANTS,MODULE_REAGENT_BANK,MODULE_TIME_IS_TIME
MODULES_CPP_LIST=
MODULES_REQUIRES_CUSTOM_BUILD=0
MODULES_REQUIRES_PLAYERBOT_SOURCE=1
# =====================
# Playerbot Runtime Configuration
# =====================
# Enable/disable playerbots and set population
PLAYERBOT_ENABLED=1
PLAYERBOT_MIN_BOTS=40
PLAYERBOT_MAX_BOTS=200
# =====================
# Client Data
# =====================
# Client data version (auto-detected when blank)
CLIENT_DATA_VERSION=
CLIENT_DATA_PATH=
# =====================
# Server Configuration Preset
# =====================
# Apply a configuration preset during deployment
# Options: none, blizzlike, fast-leveling, hardcore-pvp, casual-pve
SERVER_CONFIG_PRESET=none
# =====================
# Eluna Lua Scripting
# =====================
AC_ELUNA_ENABLED=1
AC_ELUNA_TRACE_BACK=1
AC_ELUNA_AUTO_RELOAD=1
AC_ELUNA_BYTECODE_CACHE=1
AC_ELUNA_SCRIPT_PATH=lua_scripts
AC_ELUNA_REQUIRE_PATHS=
AC_ELUNA_REQUIRE_CPATHS=
AC_ELUNA_AUTO_RELOAD_INTERVAL=1
# =====================
# Container Management
# =====================
CONTAINER_USER=0:0
CONTAINER_DB_IMPORT=ac-db-import
CONTAINER_DB_INIT=ac-db-init
CONTAINER_DB_GUARD=ac-db-guard
CONTAINER_BACKUP=ac-backup
CONTAINER_MODULES=ac-modules
CONTAINER_POST_INSTALL=ac-post-install
# =====================
# Database Guard
# =====================
DB_GUARD_RECHECK_SECONDS=120
DB_GUARD_RETRY_SECONDS=10
DB_GUARD_WAIT_ATTEMPTS=60
DB_GUARD_HEALTH_MAX_AGE=180
DB_GUARD_HEALTHCHECK_INTERVAL=30s
DB_GUARD_HEALTHCHECK_TIMEOUT=10s
DB_GUARD_HEALTHCHECK_RETRIES=5
DB_GUARD_VERIFY_INTERVAL_SECONDS=86400
# =====================
# Health Checks
# =====================
# MySQL health checks
MYSQL_HEALTHCHECK_INTERVAL=20s
MYSQL_HEALTHCHECK_TIMEOUT=15s
MYSQL_HEALTHCHECK_RETRIES=25
MYSQL_HEALTHCHECK_START_PERIOD=120s
# Auth server health checks
AUTH_HEALTHCHECK_INTERVAL=30s
AUTH_HEALTHCHECK_TIMEOUT=10s
AUTH_HEALTHCHECK_RETRIES=3
AUTH_HEALTHCHECK_START_PERIOD=60s
# World server health checks
WORLD_HEALTHCHECK_INTERVAL=30s
WORLD_HEALTHCHECK_TIMEOUT=10s
WORLD_HEALTHCHECK_RETRIES=3
WORLD_HEALTHCHECK_START_PERIOD=120s
# Backup health checks
BACKUP_HEALTHCHECK_INTERVAL=60s
BACKUP_HEALTHCHECK_TIMEOUT=30s
BACKUP_HEALTHCHECK_RETRIES=3
BACKUP_HEALTHCHECK_START_PERIOD=120s
# =====================
# Management Tools
# =====================
# phpMyAdmin configuration
PMA_HOST=ac-mysql
PMA_PORT=3306
PMA_USER=root
PMA_ARBITRARY=1
PMA_ABSOLUTE_URI=
PMA_UPLOAD_LIMIT=300M
PMA_MEMORY_LIMIT=512M
PMA_MAX_EXECUTION_TIME=600
# Keira3 configuration
KEIRA_DATABASE_HOST=ac-mysql
KEIRA_DATABASE_PORT=3306
# =====================
# Compose Overrides
# =====================
# Enable optional compose overrides (set to 1 to enable)
COMPOSE_OVERRIDE_MYSQL_EXPOSE_ENABLED=0
COMPOSE_OVERRIDE_WORLDSERVER_DEBUG_LOGGING_ENABLED=0
# =====================
# DO NOT MODIFY BELOW (Build-related, not used with pre-built images)
# =====================
AUTO_REBUILD_ON_DEPLOY=0
DB_UPDATES_ALLOWED_MODULES=all
DB_UPDATES_REDUNDANCY=1

View File

@@ -155,7 +155,6 @@ MYSQL_MAX_CONNECTIONS=1000
MYSQL_INNODB_BUFFER_POOL_SIZE=256M
MYSQL_INNODB_LOG_FILE_SIZE=64M
MYSQL_INNODB_REDO_LOG_CAPACITY=512M
# MySQL runs on tmpfs (RAM) for performance, with sync to persistent storage on shutdown
MYSQL_RUNTIME_TMPFS_SIZE=8G
MYSQL_DISABLE_BINLOG=1
MYSQL_CONFIG_DIR=${STORAGE_CONFIG_PATH}/mysql/conf.d
@@ -557,7 +556,3 @@ MODULE_MOD_MATERIAL_BANK=0
MODULE_MOD_PROGRESSION_BLIZZLIKE=0
MODULE_MOD_PYTHON_ENGINE=0
MODULE_WRATH_OF_THE_VANILLA_V2=0
MODULE_DUELS=0
MODULE_WOW_CORE=0
MODULE_CLANCENTAUR=0
MODULE_DELVES=0

View File

@@ -1,248 +0,0 @@
name: Build and Publish
# This workflow builds AzerothCore with configurable module profiles
# and publishes profile-tagged Docker images to Docker Hub for easy deployment.
#
# Default Profile: RealmMaster (32 modules including playerbots, transmog, solo-lfg, eluna, etc.)
# Available Profiles: RealmMaster, suggested-modules, all-modules, playerbots-only, or custom
# Profile Configuration: See config/module-profiles/
# Documentation: See docs/CICD.md
#
# Published Image Tags:
# - authserver-{profile}-latest (e.g., authserver-realmmaster-latest)
# - authserver-{profile}-YYYYMMDD (e.g., authserver-realmmaster-20260109)
# - authserver-latest (generic tag, defaults to RealmMaster)
# - worldserver-{profile}-latest
# - worldserver-{profile}-YYYYMMDD
# - worldserver-latest (generic tag, defaults to RealmMaster)
on:
schedule:
# Run nightly at 2 AM UTC
- cron: '0 2 * * *'
workflow_dispatch:
inputs:
module_profile:
description: 'Module profile to build (e.g., RealmMaster, suggested-modules, all-modules)'
required: false
type: string
default: 'RealmMaster'
force_rebuild:
description: 'Force rebuild even if no changes detected'
required: false
type: boolean
default: false
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 120
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Git
run: |
# Configure git for module repository cloning
git config --global user.name "GitHub Actions Bot"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git --version
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Prepare build environment
env:
TERM: xterm
run: |
# Determine which module profile to use
if [ "${{ github.event_name }}" = "schedule" ]; then
MODULE_PROFILE="RealmMaster"
else
MODULE_PROFILE="${{ github.event.inputs.module_profile }}"
MODULE_PROFILE="${MODULE_PROFILE:-RealmMaster}"
fi
echo "📋 Using module profile: ${MODULE_PROFILE}"
echo "🔧 Running setup.sh to generate proper .env file..."
# Use setup.sh to generate .env with proper configuration
# Benefits of this approach:
# - Uses the same setup logic as local builds (consistency)
# - Handles all path variables correctly (no manual sed patching needed)
# - Automatically determines source variant (standard vs playerbots)
# - Applies module profile and dependencies correctly
# - Centralizes configuration logic in one place (setup.sh)
./setup.sh \
--non-interactive \
--module-config "${MODULE_PROFILE}" \
--deployment-type local \
--force
echo "✅ Environment configuration generated successfully"
# Extract values for GitHub environment
PROJECT_NAME=$(grep '^COMPOSE_PROJECT_NAME=' .env | cut -d'=' -f2 | tr -d '\r' | sed 's/[[:space:]]*#.*//' | sed 's/[[:space:]]*$//')
echo "PROJECT_NAME=${PROJECT_NAME}" >> $GITHUB_ENV
# Store profile name for image tagging (lowercase, replace underscores with hyphens)
PROFILE_TAG=$(echo "${MODULE_PROFILE}" | tr '[:upper:]' '[:lower:]' | tr '_' '-')
echo "PROFILE_TAG=${PROFILE_TAG}" >> $GITHUB_ENV
echo "MODULE_PROFILE=${MODULE_PROFILE}" >> $GITHUB_ENV
# Count enabled modules
MODULE_COUNT=$(grep -c '^MODULE_.*=1' .env || echo "0")
echo "MODULE_COUNT=${MODULE_COUNT}" >> $GITHUB_ENV
# Display configuration summary
echo ""
echo "📊 Build Configuration Summary:"
echo " Project: ${PROJECT_NAME}"
echo " Profile: ${MODULE_PROFILE}"
echo " Profile Tag: ${PROFILE_TAG}"
echo " Modules: ${MODULE_COUNT} enabled"
echo ""
echo "Enabled modules (first 10):"
grep '^MODULE_.*=1' .env | head -10 || true
echo ""
# Show key paths for verification
echo "📂 Key Paths:"
grep '^STORAGE_PATH_LOCAL=' .env || echo " STORAGE_PATH_LOCAL not found"
grep '^MODULES_REBUILD_SOURCE_PATH=' .env || echo " MODULES_REBUILD_SOURCE_PATH not found"
grep '^STACK_SOURCE_VARIANT=' .env || echo " STACK_SOURCE_VARIANT not found"
echo ""
# Verify all Docker images are configured
echo "🐳 Docker Images (that we build and push):"
grep -E '^AC_AUTHSERVER_IMAGE_PLAYERBOTS=' .env || echo " AC_AUTHSERVER_IMAGE_PLAYERBOTS not found"
grep -E '^AC_WORLDSERVER_IMAGE_PLAYERBOTS=' .env || echo " AC_WORLDSERVER_IMAGE_PLAYERBOTS not found"
grep -E '^AC_AUTHSERVER_IMAGE_MODULES=' .env || echo " AC_AUTHSERVER_IMAGE_MODULES not found"
grep -E '^AC_WORLDSERVER_IMAGE_MODULES=' .env || echo " AC_WORLDSERVER_IMAGE_MODULES not found"
- name: Cache Go build cache
uses: actions/cache@v4
with:
path: .gocache
key: ${{ runner.os }}-gocache-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-gocache-
- name: Cache local storage
uses: actions/cache@v4
with:
path: local-storage/source
key: ${{ runner.os }}-source-${{ github.sha }}
restore-keys: |
${{ runner.os }}-source-
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Run build
run: |
# The build.sh script will automatically:
# 1. Generate module state from the enabled modules in .env
# 2. Set up the AzerothCore source repository
# 3. Fetch and clone all enabled module repositories from GitHub
# 4. Stage modules to the source directory
# 5. Compile AzerothCore with all modules
# 6. Tag the resulting Docker images
BUILD_ARGS="--yes"
# Add force flag if manually triggered with force_rebuild
if [ "${{ github.event.inputs.force_rebuild }}" = "true" ]; then
BUILD_ARGS="${BUILD_ARGS} --force"
fi
echo "🔨 Starting build process with ${BUILD_ARGS}..."
echo "This will fetch and build all ${MODULE_COUNT} enabled modules from the ${MODULE_PROFILE} profile"
./build.sh ${BUILD_ARGS}
- name: Tag images for Docker Hub
run: |
DATE_TAG=$(date +%Y%m%d)
# Tag authserver images with profile name
docker tag ${PROJECT_NAME}:authserver-modules-latest \
${{ secrets.DOCKERHUB_USERNAME }}/${PROJECT_NAME}:authserver-${PROFILE_TAG}-latest
docker tag ${PROJECT_NAME}:authserver-modules-latest \
${{ secrets.DOCKERHUB_USERNAME }}/${PROJECT_NAME}:authserver-${PROFILE_TAG}-${DATE_TAG}
# Also tag as generic 'latest' for backward compatibility
docker tag ${PROJECT_NAME}:authserver-modules-latest \
${{ secrets.DOCKERHUB_USERNAME }}/${PROJECT_NAME}:authserver-latest
# Tag worldserver images with profile name
docker tag ${PROJECT_NAME}:worldserver-modules-latest \
${{ secrets.DOCKERHUB_USERNAME }}/${PROJECT_NAME}:worldserver-${PROFILE_TAG}-latest
docker tag ${PROJECT_NAME}:worldserver-modules-latest \
${{ secrets.DOCKERHUB_USERNAME }}/${PROJECT_NAME}:worldserver-${PROFILE_TAG}-${DATE_TAG}
# Also tag as generic 'latest' for backward compatibility
docker tag ${PROJECT_NAME}:worldserver-modules-latest \
${{ secrets.DOCKERHUB_USERNAME }}/${PROJECT_NAME}:worldserver-latest
echo "Tagged images with profile '${PROFILE_TAG}' and date '${DATE_TAG}'"
- name: Push images to Docker Hub
run: |
DATE_TAG=$(date +%Y%m%d)
# Push authserver images (all tags)
docker push ${{ secrets.DOCKERHUB_USERNAME }}/${PROJECT_NAME}:authserver-${PROFILE_TAG}-latest
docker push ${{ secrets.DOCKERHUB_USERNAME }}/${PROJECT_NAME}:authserver-${PROFILE_TAG}-${DATE_TAG}
docker push ${{ secrets.DOCKERHUB_USERNAME }}/${PROJECT_NAME}:authserver-latest
# Push worldserver images (all tags)
docker push ${{ secrets.DOCKERHUB_USERNAME }}/${PROJECT_NAME}:worldserver-${PROFILE_TAG}-latest
docker push ${{ secrets.DOCKERHUB_USERNAME }}/${PROJECT_NAME}:worldserver-${PROFILE_TAG}-${DATE_TAG}
docker push ${{ secrets.DOCKERHUB_USERNAME }}/${PROJECT_NAME}:worldserver-latest
echo "✅ Pushed all image tags to Docker Hub"
- name: Build summary
run: |
DATE_TAG=$(date +%Y%m%d)
echo "## Build Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "✅ Build completed successfully" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Configuration" >> $GITHUB_STEP_SUMMARY
echo "- **Module Profile**: ${MODULE_PROFILE}" >> $GITHUB_STEP_SUMMARY
echo "- **Enabled Modules**: ${MODULE_COUNT}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "<details>" >> $GITHUB_STEP_SUMMARY
echo "<summary>View enabled modules</summary>" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
grep '^MODULE_.*=1' .env | sed 's/=1//' >> $GITHUB_STEP_SUMMARY || true
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "</details>" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Published Images" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "#### Profile-Specific Tags" >> $GITHUB_STEP_SUMMARY
echo "- \`${{ secrets.DOCKERHUB_USERNAME }}/${PROJECT_NAME}:authserver-${PROFILE_TAG}-latest\`" >> $GITHUB_STEP_SUMMARY
echo "- \`${{ secrets.DOCKERHUB_USERNAME }}/${PROJECT_NAME}:authserver-${PROFILE_TAG}-${DATE_TAG}\`" >> $GITHUB_STEP_SUMMARY
echo "- \`${{ secrets.DOCKERHUB_USERNAME }}/${PROJECT_NAME}:worldserver-${PROFILE_TAG}-latest\`" >> $GITHUB_STEP_SUMMARY
echo "- \`${{ secrets.DOCKERHUB_USERNAME }}/${PROJECT_NAME}:worldserver-${PROFILE_TAG}-${DATE_TAG}\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "#### Generic Tags (backward compatibility)" >> $GITHUB_STEP_SUMMARY
echo "- \`${{ secrets.DOCKERHUB_USERNAME }}/${PROJECT_NAME}:authserver-latest\`" >> $GITHUB_STEP_SUMMARY
echo "- \`${{ secrets.DOCKERHUB_USERNAME }}/${PROJECT_NAME}:worldserver-latest\`" >> $GITHUB_STEP_SUMMARY

View File

@@ -1,246 +0,0 @@
name: Create Release
on:
workflow_dispatch:
inputs:
version:
description: 'Release version (e.g., v1.0.0)'
required: true
type: string
profile:
description: 'Module profile for this release'
required: false
type: string
default: 'RealmMaster'
prerelease:
description: 'Mark as pre-release'
required: false
type: boolean
default: false
jobs:
create-release:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Prepare release variables
run: |
VERSION="${{ github.event.inputs.version }}"
PROFILE="${{ github.event.inputs.profile }}"
PROFILE_TAG=$(echo "${PROFILE}" | tr '[:upper:]' '[:lower:]' | tr '_' '-')
echo "VERSION=${VERSION}" >> $GITHUB_ENV
echo "PROFILE=${PROFILE}" >> $GITHUB_ENV
echo "PROFILE_TAG=${PROFILE_TAG}" >> $GITHUB_ENV
# Get build date from Docker Hub image (or use current date)
BUILD_DATE=$(date +%Y%m%d)
echo "BUILD_DATE=${BUILD_DATE}" >> $GITHUB_ENV
# Get AzerothCore commit from local-storage if available
if [ -d "local-storage/source/azerothcore-playerbots" ]; then
ACORE_COMMIT=$(cd local-storage/source/azerothcore-playerbots && git rev-parse --short HEAD)
else
ACORE_COMMIT="unknown"
fi
echo "ACORE_COMMIT=${ACORE_COMMIT}" >> $GITHUB_ENV
- name: Read module list from profile
run: |
PROFILE_FILE="config/module-profiles/${PROFILE}.json"
if [ ! -f "$PROFILE_FILE" ]; then
echo "ERROR: Profile file not found: $PROFILE_FILE"
exit 1
fi
# Extract module count
MODULE_COUNT=$(python3 -c "import json; data=json.load(open('$PROFILE_FILE')); print(len(data.get('modules', [])))")
echo "MODULE_COUNT=${MODULE_COUNT}" >> $GITHUB_ENV
# Extract modules for release notes
python3 -c "import json; data=json.load(open('$PROFILE_FILE')); print('\n'.join(['- ' + m for m in data.get('modules', [])]))" > modules.txt
- name: Create deployment package
run: |
PACKAGE_NAME="azerothcore-realmmaster-${VERSION}-${PROFILE_TAG}"
mkdir -p "${PACKAGE_NAME}"
# Copy essential deployment files
cp .env.prebuilt "${PACKAGE_NAME}/.env.prebuilt"
cp docker-compose.yml "${PACKAGE_NAME}/docker-compose.yml"
cp deploy.sh "${PACKAGE_NAME}/deploy.sh"
cp status.sh "${PACKAGE_NAME}/status.sh"
cp cleanup.sh "${PACKAGE_NAME}/cleanup.sh"
cp README.md "${PACKAGE_NAME}/README.md"
# Copy scripts directory
cp -r scripts "${PACKAGE_NAME}/scripts"
# Copy config directory
cp -r config "${PACKAGE_NAME}/config"
# Copy docs directory
cp -r docs "${PACKAGE_NAME}/docs"
# Create a quick start guide specific to this release
{
echo "# Quick Start - AzerothCore RealmMaster ${VERSION}"
echo ""
echo "## Module Profile: ${PROFILE}"
echo "${MODULE_COUNT} modules included"
echo ""
echo "## Docker Images"
echo "This release uses the following pre-built images:"
echo "- \`\${DOCKERHUB_USERNAME}/azerothcore-realmmaster:authserver-${PROFILE_TAG}-${BUILD_DATE}\`"
echo "- \`\${DOCKERHUB_USERNAME}/azerothcore-realmmaster:worldserver-${PROFILE_TAG}-${BUILD_DATE}\`"
echo ""
echo "Or use the latest tags:"
echo "- \`\${DOCKERHUB_USERNAME}/azerothcore-realmmaster:authserver-${PROFILE_TAG}-latest\`"
echo "- \`\${DOCKERHUB_USERNAME}/azerothcore-realmmaster:worldserver-${PROFILE_TAG}-latest\`"
echo ""
echo "## Installation"
echo ""
echo "1. **Edit .env.prebuilt**:"
echo " \`\`\`bash"
echo " nano .env.prebuilt"
echo " # Set: DOCKERHUB_USERNAME=your-dockerhub-username"
echo " \`\`\`"
echo ""
echo "2. **Rename to .env**:"
echo " \`\`\`bash"
echo " mv .env.prebuilt .env"
echo " \`\`\`"
echo ""
echo "3. **Deploy**:"
echo " \`\`\`bash"
echo " chmod +x deploy.sh status.sh cleanup.sh"
echo " ./deploy.sh"
echo " \`\`\`"
echo ""
echo "4. **Check status**:"
echo " \`\`\`bash"
echo " ./status.sh"
echo " \`\`\`"
echo ""
echo "## Documentation"
echo "- [Pre-Built Images Guide](docs/PREBUILT_IMAGES.md)"
echo "- [Getting Started](docs/GETTING_STARTED.md)"
echo "- [Troubleshooting](docs/TROUBLESHOOTING.md)"
echo ""
echo "## Support"
echo "- GitHub Issues: https://github.com/uprightbass360/AzerothCore-RealmMaster/issues"
echo "- AzerothCore Discord: https://discord.gg/gkt4y2x"
} > "${PACKAGE_NAME}/QUICKSTART.md"
# Make scripts executable
chmod +x "${PACKAGE_NAME}/deploy.sh"
chmod +x "${PACKAGE_NAME}/status.sh"
chmod +x "${PACKAGE_NAME}/cleanup.sh"
# Create zip archive
zip -r "${PACKAGE_NAME}.zip" "${PACKAGE_NAME}"
echo "PACKAGE_NAME=${PACKAGE_NAME}" >> $GITHUB_ENV
- name: Generate release notes
run: |
{
echo "# AzerothCore RealmMaster ${VERSION} - ${PROFILE} Profile"
echo ""
echo "## 🎯 Module Profile: ${PROFILE}"
echo "${MODULE_COUNT} modules included"
echo ""
echo "## 📦 Docker Images"
echo ""
echo "Pull these pre-built images from Docker Hub:"
echo ""
echo "**Date-specific (recommended for production)**:"
echo "\`\`\`bash"
echo "docker pull \${DOCKERHUB_USERNAME}/azerothcore-realmmaster:authserver-${PROFILE_TAG}-${BUILD_DATE}"
echo "docker pull \${DOCKERHUB_USERNAME}/azerothcore-realmmaster:worldserver-${PROFILE_TAG}-${BUILD_DATE}"
echo "\`\`\`"
echo ""
echo "**Latest (auto-updated nightly)**:"
echo "\`\`\`bash"
echo "docker pull \${DOCKERHUB_USERNAME}/azerothcore-realmmaster:authserver-${PROFILE_TAG}-latest"
echo "docker pull \${DOCKERHUB_USERNAME}/azerothcore-realmmaster:worldserver-${PROFILE_TAG}-latest"
echo "\`\`\`"
echo ""
echo "## 🚀 Quick Start"
echo ""
echo "\`\`\`bash"
echo "# Download and extract"
echo "wget https://github.com/uprightbass360/AzerothCore-RealmMaster/releases/download/${VERSION}/${PACKAGE_NAME}.zip"
echo "unzip ${PACKAGE_NAME}.zip"
echo "cd ${PACKAGE_NAME}"
echo ""
echo "# Configure Docker Hub username"
echo "nano .env.prebuilt"
echo "# Set: DOCKERHUB_USERNAME=your-dockerhub-username"
echo ""
echo "# Deploy"
echo "mv .env.prebuilt .env"
echo "./deploy.sh"
echo "\`\`\`"
echo ""
echo "Full documentation in \`docs/PREBUILT_IMAGES.md\`"
echo ""
echo "## 📋 Included Modules"
echo ""
cat modules.txt
echo ""
echo "## 📊 Build Information"
echo ""
echo "- **Built**: ${BUILD_DATE}"
echo "- **AzerothCore Commit**: ${ACORE_COMMIT}"
echo "- **Source Variant**: playerbots (for MODULE_PLAYERBOTS support)"
echo "- **Profile**: ${PROFILE}"
echo "- **Module Count**: ${MODULE_COUNT}"
echo ""
echo "## 📖 Documentation"
echo ""
echo "Full documentation available in the \`docs/\` directory of the release package:"
echo "- [Pre-Built Images Guide](https://github.com/uprightbass360/AzerothCore-RealmMaster/blob/${VERSION}/docs/PREBUILT_IMAGES.md)"
echo "- [Getting Started Guide](https://github.com/uprightbass360/AzerothCore-RealmMaster/blob/${VERSION}/docs/GETTING_STARTED.md)"
echo "- [Module Catalog](https://github.com/uprightbass360/AzerothCore-RealmMaster/blob/${VERSION}/docs/MODULES.md)"
echo "- [Troubleshooting](https://github.com/uprightbass360/AzerothCore-RealmMaster/blob/${VERSION}/docs/TROUBLESHOOTING.md)"
echo ""
echo "## 🐛 Known Issues"
echo ""
echo "None at this time. Report issues at: https://github.com/uprightbass360/AzerothCore-RealmMaster/issues"
echo ""
echo "## 💬 Support"
echo ""
echo "- **GitHub Issues**: https://github.com/uprightbass360/AzerothCore-RealmMaster/issues"
echo "- **AzerothCore Discord**: https://discord.gg/gkt4y2x"
echo "- **Documentation**: https://github.com/uprightbass360/AzerothCore-RealmMaster/tree/${VERSION}/docs"
} > release_notes.md
- name: Create GitHub Release
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ env.VERSION }}
name: "RealmMaster ${{ env.VERSION }} - ${{ env.PROFILE }} Profile"
body_path: release_notes.md
files: |
${{ env.PACKAGE_NAME }}.zip
prerelease: ${{ github.event.inputs.prerelease }}
draft: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Release summary
run: |
echo "## Release Created Successfully! 🎉" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Version**: ${{ env.VERSION }}" >> $GITHUB_STEP_SUMMARY
echo "**Profile**: ${{ env.PROFILE }}" >> $GITHUB_STEP_SUMMARY
echo "**Modules**: ${{ env.MODULE_COUNT }}" >> $GITHUB_STEP_SUMMARY
echo "**Package**: ${{ env.PACKAGE_NAME }}.zip" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "📦 Release available at:" >> $GITHUB_STEP_SUMMARY
echo "https://github.com/${{ github.repository }}/releases/tag/${{ env.VERSION }}" >> $GITHUB_STEP_SUMMARY

40
.gitignore vendored
View File

@@ -1,27 +1,25 @@
# ===================================
# Environment & Configuration
# ===================================
.env
.claude/
.mcp*/
# ===================================
# Storage & Data Directories
# ===================================
database-import/*.sql
database-import/*.sql.gz
database-import/*/
database-import/ImportBackup*/
db_*/
source/*
local-data-tools/
changelogs/
storage/
local-storage/
db_*/
# ===================================
# Build Artifacts & Cache
# ===================================
.gocache/
statusdash
.claude/
images/
node_modules/
.mcp*/
scripts/__pycache__/*
scripts/bash/__pycache__/*
scripts/python/__pycache__/*
# ===================================
# Logs & Runtime State
# ===================================
.env
package-lock.json
package.json
todo.md
.gocache/
.module-ledger/
deploy.log
statusdash

View File

@@ -11,13 +11,11 @@ A complete containerized deployment of AzerothCore WoW 3.3.5a (Wrath of the Lich
- [Quick Start](#quick-start)
- [What You Get](#what-you-get)
- [Getting Started](#getting-started) → **[docs/GETTING_STARTED.md](docs/GETTING_STARTED.md)**
- [Using Pre-Built Images](#using-pre-built-images-no-build-required) → **[docs/PREBUILT_IMAGES.md](docs/PREBUILT_IMAGES.md)**
- [Complete Module Catalog](#complete-module-catalog) → **[docs/MODULES.md](docs/MODULES.md)**
- [Management & Operations](#management--operations) → **[docs/GETTING_STARTED.md](docs/GETTING_STARTED.md)**
- [Advanced Configuration](#advanced-configuration) → **[docs/ADVANCED.md](docs/ADVANCED.md)**
- [Custom NPCs Guide](#custom-npcs-guide) → **[docs/NPCS.md](docs/NPCS.md)**
- [Script Reference](#script-reference) → **[docs/SCRIPTS.md](docs/SCRIPTS.md)**
- [CI/CD & Pre-Built Images](#cicd--pre-built-images) → **[docs/CICD.md](docs/CICD.md)**
- [Troubleshooting](#troubleshooting) → **[docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md)**
- [Credits & Next Steps](#credits--next-steps)
@@ -28,7 +26,7 @@ A complete containerized deployment of AzerothCore WoW 3.3.5a (Wrath of the Lich
### Reccomendations
- **Docker** with Docker Compose 2
- **16GB+ RAM** and **64GB+ storage**
- **Linux/macOS/WSL2** Fully tested with Ubuntu 24.04 - Debian 12 might work but permissions can require manual intervention
- **Linux/macOS/WSL2** Fully tested with Ubuntu 24.04 and Debian 12
### Three Simple Steps
@@ -47,25 +45,6 @@ cd AzerothCore-RealmMaster
**First deployment takes 30-60 minutes** for database setup and client data download. Subsequent starts are much faster.
### Using Pre-Built Images (No Build Required!)
Skip the build process and deploy with pre-built Docker images:
```bash
# 1. Clone the repository
git clone https://github.com/uprightbass360/AzerothCore-RealmMaster.git
cd AzerothCore-RealmMaster
# 2. Use pre-built configuration
cp .env.prebuilt .env
# 3. Edit .env and set DOCKERHUB_USERNAME
# 4. Deploy
./deploy.sh
```
Pre-built images include the **RealmMaster profile** (32 modules) and are automatically built nightly. See **[docs/PREBUILT_IMAGES.md](docs/PREBUILT_IMAGES.md)** for details.
See [Getting Started](#getting-started) for detailed walkthrough.
## What You Get

View File

@@ -38,7 +38,6 @@ Build AzerothCore with custom modules and create deployment-ready images.
Options:
--yes, -y Auto-confirm all prompts
--force Force rebuild even if no changes detected
--force-update Force update source repository to latest commits
--source-path PATH Custom source repository path
--skip-source-setup Skip automatic source repository setup
-h, --help Show this help
@@ -54,7 +53,6 @@ Examples:
./build.sh Interactive build
./build.sh --yes Auto-confirm build
./build.sh --force Force rebuild regardless of state
./build.sh --force-update Update source to latest and build
EOF
}
@@ -62,7 +60,6 @@ while [[ $# -gt 0 ]]; do
case "$1" in
--yes|-y) ASSUME_YES=1; shift;;
--force) FORCE_REBUILD=1; shift;;
--force-update) FORCE_UPDATE=1; shift;;
--source-path) CUSTOM_SOURCE_PATH="$2"; shift 2;;
--skip-source-setup) SKIP_SOURCE_SETUP=1; shift;;
-h|--help) usage; exit 0;;
@@ -243,13 +240,6 @@ ensure_source_repo(){
src_path="${src_path//\/.\//\/}"
if [ -d "$src_path/.git" ]; then
if [ "${FORCE_UPDATE:-0}" = "1" ]; then
info "Force update requested - updating source repository to latest" >&2
if ! (cd "$ROOT_DIR" && ./scripts/bash/setup-source.sh) >&2; then
err "Failed to update source repository" >&2
exit 1
fi
fi
echo "$src_path"
return
fi
@@ -550,10 +540,6 @@ stage_modules(){
rm -f "$staging_modules_dir/.modules_state" "$staging_modules_dir/.requires_rebuild" 2>/dev/null || true
fi
# Export environment variables needed by module hooks
export STACK_SOURCE_VARIANT="$(read_env STACK_SOURCE_VARIANT "core")"
export MODULES_REBUILD_SOURCE_PATH="$(read_env MODULES_REBUILD_SOURCE_PATH "")"
if ! (cd "$local_modules_dir" && bash "$ROOT_DIR/scripts/bash/manage-modules.sh"); then
err "Module staging failed; aborting build"
return 1

View File

@@ -5489,62 +5489,6 @@
"requires": [],
"post_install_hooks": [],
"config_cleanup": []
},
{
"key": "MODULE_DUELS",
"name": "Duels",
"repo": "https://github.com/VikasMahajan370/Duels.git",
"description": "\u2694\ufe0f Experience engaging duels with a feature-rich plugin for Paper 1.21+ servers, featuring 1.8 Legacy combat, matchmaking, custom kits, and more.",
"type": "cpp",
"category": "uncategorized",
"notes": "Discovered via GitHub topic 'azerothcore-module'",
"status": "active",
"order": 5000,
"requires": [],
"post_install_hooks": [],
"config_cleanup": []
},
{
"key": "MODULE_WOW_CORE",
"name": "wow-core",
"repo": "https://github.com/Wow-Libre/wow-core.git",
"description": "Complete management platform for private World of Warcraft servers.",
"type": "tool",
"category": "tooling",
"notes": "Discovered via GitHub topic 'azerothcore-tools'",
"status": "active",
"order": 5000,
"requires": [],
"post_install_hooks": [],
"config_cleanup": []
},
{
"key": "MODULE_DELVES",
"name": "Delves",
"repo": "https://github.com/araxiaonline/Delves.git",
"description": "List of the Custom Made Single Player Delves for Araxia Online",
"type": "lua",
"category": "scripting",
"notes": "Discovered via GitHub topic 'azerothcore-module'",
"status": "active",
"order": 5000,
"requires": [],
"post_install_hooks": [],
"config_cleanup": []
},
{
"key": "MODULE_CLANCENTAUR",
"name": "ClanCentaur",
"repo": "https://github.com/araxiaonline/ClanCentaur.git",
"description": "Custom SQL modifications and patch notes for new faction rewards, reputation items, and unique vendors on the Araxia WoW 3.3.5a server.",
"type": "sql",
"category": "database",
"notes": "Discovered via GitHub topic 'azerothcore-module'",
"status": "active",
"order": 5000,
"requires": [],
"post_install_hooks": [],
"config_cleanup": []
}
]
}

View File

@@ -22,6 +22,7 @@
"MODULE_ASSISTANT",
"MODULE_REAGENT_BANK",
"MODULE_BLACK_MARKET_AUCTION_HOUSE",
"MODULE_ELUNA_TS",
"MODULE_ELUNA",
"MODULE_AIO",
"MODULE_ELUNA_SCRIPTS",

View File

@@ -1,6 +1,6 @@
{
"modules": [
"MODULE_ELUNA"
],
"label": "\ud83d\udd30 AzerothCore Main - Mod Free",
"description": "Pure AzerothCore with no optional modules enabled",

View File

@@ -1,7 +1,8 @@
{
"modules": [
"MODULE_PLAYERBOTS",
"MODULE_ELUNA"
"MODULE_ELUNA",
"MODULE_ELUNA_TS"
],
"label": "\ud83e\udde9 Playerbots Only",
"description": "Minimal preset that only enables playerbot prerequisites",

View File

@@ -8,10 +8,11 @@
"MODULE_NPC_BUFFER",
"MODULE_LEARN_SPELLS",
"MODULE_FIREWORKS",
"MODULE_ELUNA_TS",
"MODULE_ELUNA",
"MODULE_AIO"
],
"label": "\ud83e\udd16 Suggested modules (Playerbots)",
"label": "\ud83e\udd16 Playerbots + Suggested modules",
"description": "Suggested stack plus playerbots enabled",
"order": 1
}

View File

@@ -1,5 +1,6 @@
{
"modules": [
"MODULE_ELUNA_TS",
"MODULE_ELUNA",
"MODULE_AIO",
"MODULE_SOLO_LFG",
@@ -10,7 +11,7 @@
"MODULE_LEARN_SPELLS",
"MODULE_FIREWORKS"
],
"label": "\u2b50 Suggested Modules (Main)",
"label": "\u2b50 Suggested Modules",
"description": "Baseline solo-friendly quality of life mix (no playerbots)",
"order": 2
}

View File

@@ -26,7 +26,6 @@ services:
MYSQL_INNODB_BUFFER_POOL_SIZE: ${MYSQL_INNODB_BUFFER_POOL_SIZE}
MYSQL_INNODB_LOG_FILE_SIZE: ${MYSQL_INNODB_LOG_FILE_SIZE}
MYSQL_BINLOG_EXPIRE_LOGS_SECONDS: 86400
MYSQL_DISABLE_BINLOG: ${MYSQL_DISABLE_BINLOG}
TZ: "${TZ}"
entrypoint:
- /usr/local/bin/mysql-entrypoint.sh
@@ -51,7 +50,6 @@ services:
- --expire_logs_days=0
- --binlog_expire_logs_seconds=86400
- --binlog_expire_logs_auto_purge=ON
stop_grace_period: 2m
restart: unless-stopped
logging: *logging-default
healthcheck:

View File

@@ -152,7 +152,7 @@ storage/
├── client-data/ # Unpacked WoW client data & DBC overrides
├── logs/ # Server log files
├── modules/ # Downloaded module source code
├── lua_scripts/ # ALE Lua scripts (auto-loaded)
├── lua_scripts/ # Eluna Lua scripts (auto-loaded)
├── install-markers/ # Module installation state tracking
└── backups/ # Automated database backups
├── daily/ # Daily backups (retained per BACKUP_RETENTION_DAYS)
@@ -190,26 +190,6 @@ The build system is optimized for development and production deployments with Do
- Build artifact caching for faster rebuilds
- Support for custom patches and modifications
### Module Build Source Path
**`MODULES_REBUILD_SOURCE_PATH`** - Path to AzerothCore source used for C++ module compilation.
**Default:** `${STORAGE_PATH_LOCAL}/source/azerothcore`
Auto-selects the appropriate fork:
- Playerbots enabled → `./local-storage/source/azerothcore-playerbots`
- Standard build → `./local-storage/source/azerothcore`
**Custom Override:**
```bash
MODULES_REBUILD_SOURCE_PATH=/path/to/custom/azerothcore
```
**Notes:**
- Must be a valid AzerothCore git repository
- Cannot be inside `STORAGE_PATH` (performance)
- Auto-managed by `setup-source.sh` and `rebuild-with-modules.sh`
## Custom Configuration
Advanced customization options for specialized deployments and development environments.

View File

@@ -1,321 +0,0 @@
# CI/CD Documentation
This document describes the continuous integration and deployment workflows configured for the AzerothCore RealmMaster project.
## Build and Publish Workflow
The `build-and-publish.yml` workflow automatically builds AzerothCore with your configured modules and publishes Docker images to Docker Hub.
### Trigger Schedule
- **Nightly builds**: Runs automatically at 2 AM UTC every day
- **Manual trigger**: Can be triggered manually via GitHub Actions UI with optional force rebuild
### What It Does
1. **Checks out the repository** - Gets the RealmMaster project code
2. **Sets up Git** - Configures git for module repository cloning
3. **Sets up Docker Buildx** - Enables optimized Docker builds
4. **Logs in to Docker Hub** - Authenticates for image publishing
5. **Prepares the build environment**:
- Runs `./setup.sh --non-interactive --module-config RealmMaster --force`
- Uses the same setup process as local builds (ensures consistency)
- Applies the **RealmMaster module profile** from `config/module-profiles/RealmMaster.json`
- Creates `.env` with proper paths and configured modules (32 modules)
- Automatically selects correct source variant (standard or playerbots)
6. **Caches build artifacts** to speed up subsequent builds:
- Go build cache (`.gocache`)
- Source repository (`local-storage/source`)
7. **Sets up Python 3.11** - Required for module management scripts
8. **Runs `./build.sh --yes`** - This is where the magic happens:
- **Step 1**: Sets up the AzerothCore source repository
- **Step 2**: Detects build requirements
- **Step 3**: Syncs module metadata
- **Step 4**: **Fetches all module repositories** - Automatically clones all 32 enabled module repos from GitHub
- **Step 5**: **Compiles AzerothCore** with all fetched modules integrated
- **Step 6**: Tags the compiled images
9. **Tags images for Docker Hub** - Prepares `latest` and date-based tags
10. **Pushes images to Docker Hub** - Publishes the built images
11. **Generates a build summary** - Shows enabled modules and published images
### Module Fetching Process
The workflow **automatically fetches all module repositories** during the build. Here's how it works:
- The `build.sh` script reads the enabled modules from `.env` (set by the RealmMaster profile)
- For each enabled module, it clones the repository from GitHub (all modules are public repos)
- Module repositories are cloned into the AzerothCore source tree under `modules/`
- Examples of fetched repositories:
- `mod-playerbots` from https://github.com/mod-playerbots/mod-playerbots.git
- `mod-transmog` from https://github.com/azerothcore/mod-transmog.git
- `mod-solo-lfg` from https://github.com/azerothcore/mod-solo-lfg.git
- ...and 29 more
**No manual module setup required!** The build process handles everything automatically.
### Published Images
The workflow publishes images with **profile-specific tags** so you know exactly which modules are included:
**Profile-Tagged Images** (recommended):
- `<dockerhub-username>/azerothcore-realmmaster:authserver-realmmaster-latest` ✅ Built nightly
- `<dockerhub-username>/azerothcore-realmmaster:authserver-realmmaster-YYYYMMDD` ✅ Built nightly
- `<dockerhub-username>/azerothcore-realmmaster:worldserver-realmmaster-latest` ✅ Built nightly
- `<dockerhub-username>/azerothcore-realmmaster:worldserver-realmmaster-YYYYMMDD` ✅ Built nightly
**Generic Tags** (backward compatibility, defaults to RealmMaster profile):
- `<dockerhub-username>/azerothcore-realmmaster:authserver-latest` ✅ Built nightly
- `<dockerhub-username>/azerothcore-realmmaster:worldserver-latest` ✅ Built nightly
**Other Profile Tags** (built on-demand via manual workflow trigger):
- `authserver-suggested-modules-latest` - Available when built
- `authserver-all-modules-latest` - Available when built
- `authserver-playerbots-only-latest` - Available when built
**Note**: Only the RealmMaster profile is built automatically on schedule. Other profiles can be built by manually triggering the workflow with different profile names.
## Required GitHub Secrets
To enable the build and publish workflow, you must configure the following secrets in your GitHub repository:
### Setting Up Secrets
1. Go to your GitHub repository
2. Click **Settings****Secrets and variables****Actions**
3. Click **New repository secret**
4. Add the following secrets:
#### DOCKERHUB_USERNAME
Your Docker Hub username.
**Example**: `yourusername`
#### DOCKERHUB_TOKEN
A Docker Hub access token (recommended) or your Docker Hub password.
**How to create a Docker Hub access token**:
1. Log in to [Docker Hub](https://hub.docker.com/)
2. Click on your username in the top right → **Account Settings**
3. Go to **Security****Personal Access Tokens****Generate New Token**
4. Give it a description (e.g., "GitHub Actions")
5. Set permissions: **Read & Write**
6. Click **Generate**
7. Copy the token (you won't be able to see it again)
8. Add this token as the `DOCKERHUB_TOKEN` secret in GitHub
## Module Configuration
### Default Profile: RealmMaster
The workflow uses the **RealmMaster** module profile by default, which includes 32 carefully selected modules:
- MODULE_PLAYERBOTS - AI-controlled player characters
- MODULE_TRANSMOG - Transmogrification system
- MODULE_SOLO_LFG - Solo dungeon finder
- MODULE_NPC_BUFFER - Buff NPC
- MODULE_ELUNA - Lua scripting engine
- MODULE_AIO - All-in-one interface
- ...and 26 more modules
See the full list in `config/module-profiles/RealmMaster.json`.
### Customizing the Module Profile
To use a different module profile in the CI/CD workflow:
1. **Choose or create a profile** in `config/module-profiles/`:
- `RealmMaster.json` - Default (32 modules)
- `suggested-modules.json` - Alternative suggested set
- `playerbots-only.json` - Just playerbots
- `all-modules.json` - All supported modules
- Create your own JSON file
2. **Edit the workflow** at `.github/workflows/build-and-publish.yml`:
```yaml
# Change this line in the "Prepare build environment" step:
python3 scripts/python/apply_module_profile.py RealmMaster \
# To use a different profile:
python3 scripts/python/apply_module_profile.py suggested-modules \
```
3. **Update the build summary** (optional):
```yaml
# Change this line in the "Build summary" step:
echo "- **Module Profile**: RealmMaster" >> $GITHUB_STEP_SUMMARY
# To:
echo "- **Module Profile**: suggested-modules" >> $GITHUB_STEP_SUMMARY
```
### Testing Module Profiles Locally
You can test the module profile script locally before committing:
```bash
# List modules that will be enabled
python3 scripts/python/apply_module_profile.py RealmMaster --list-modules
# Apply a profile to create .env
python3 scripts/python/apply_module_profile.py RealmMaster
# Verify the result
grep '^MODULE_.*=1' .env | wc -l
```
## Cache Strategy
The workflow uses GitHub Actions cache to speed up builds:
- **Go build cache**: Cached in `.gocache` directory
- **Source repository**: Cached in `local-storage/source` directory
This significantly reduces build times for subsequent runs.
## Manual Workflow Trigger
To manually trigger the workflow:
1. Go to **Actions** tab in your GitHub repository
2. Click on **Build and Publish** workflow
3. Click **Run workflow**
4. **Choose module profile** (default: RealmMaster):
- Enter profile name (e.g., `RealmMaster`, `suggested-modules`, `all-modules`, `playerbots-only`)
- Profile must exist in `config/module-profiles/`
5. Optionally check **Force rebuild** to rebuild even if no changes detected
6. Click **Run workflow**
The workflow will build with the selected profile and tag images accordingly (e.g., `authserver-realmmaster-latest` for RealmMaster profile).
## Troubleshooting
### Build fails with "missing required command"
The workflow runs on Ubuntu and has Docker and Python 3.11 pre-installed. If you see missing command errors, ensure the build script dependencies are available.
### Authentication errors
If you see Docker Hub authentication errors:
- Verify `DOCKERHUB_USERNAME` and `DOCKERHUB_TOKEN` secrets are set correctly
- Ensure the Docker Hub token has **Read & Write** permissions
- Check that the token hasn't expired
### Build timeout
The workflow has a 120-minute timeout. If builds consistently exceed this:
- Consider optimizing the build process
- Check if all module sources are accessible
- Review cache effectiveness
## Using Pre-Built Images
After images are published to Docker Hub, users can deploy RealmMaster **without building locally**!
### For End Users
See the complete guide at **[docs/PREBUILT_IMAGES.md](PREBUILT_IMAGES.md)** for step-by-step instructions.
**Quick start for users**:
```bash
# Clone the repository
git clone https://github.com/uprightbass360/AzerothCore-RealmMaster.git
cd AzerothCore-RealmMaster
# Use pre-built configuration
cp .env.prebuilt .env
# Edit .env and set DOCKERHUB_USERNAME=your-dockerhub-username
# Deploy (no build required!)
./deploy.sh
```
### For Developers
To test the published images:
```bash
# Pull latest RealmMaster profile images
docker pull <dockerhub-username>/azerothcore-realmmaster:authserver-realmmaster-latest
docker pull <dockerhub-username>/azerothcore-realmmaster:worldserver-realmmaster-latest
# Or pull specific date-tagged images
docker pull <dockerhub-username>/azerothcore-realmmaster:authserver-realmmaster-20260109
docker pull <dockerhub-username>/azerothcore-realmmaster:worldserver-realmmaster-20260109
# Or use generic latest tags (defaults to RealmMaster profile)
docker pull <dockerhub-username>/azerothcore-realmmaster:authserver-latest
docker pull <dockerhub-username>/azerothcore-realmmaster:worldserver-latest
```
### Pre-Built Configuration File
The `.env.prebuilt` template provides a minimal configuration that:
- References Docker Hub images instead of local builds
- Removes all build-related variables
- Includes only runtime configuration
- Is ready to use with minimal editing (just set DOCKERHUB_USERNAME)
**Benefits of pre-built images**:
- ✅ Skip 15-45 minute build time
- ✅ No build dependencies required
- ✅ Same 32 RealmMaster modules included
- ✅ Automatic nightly updates available
- ✅ Date-tagged versions for stability
- ✅ Profile-tagged images for clear identification
## Building Multiple Profiles
You can build different module profiles by manually triggering the workflow:
### Example: Build All Modules Profile
1. Go to **Actions** → **Build and Publish**
2. Click **Run workflow**
3. Set **module_profile** to `all-modules`
4. Click **Run workflow**
This will create:
- `authserver-all-modules-latest`
- `authserver-all-modules-YYYYMMDD`
- `worldserver-all-modules-latest`
- `worldserver-all-modules-YYYYMMDD`
### Creating Custom Profile Builds
To build a custom profile:
1. **Create profile JSON** in `config/module-profiles/my-custom-profile.json`:
```json
{
"modules": [
"MODULE_PLAYERBOTS",
"MODULE_TRANSMOG",
"MODULE_SOLO_LFG"
],
"label": "My Custom Profile",
"description": "Custom module selection",
"order": 100
}
```
2. **Trigger workflow** with profile name `my-custom-profile`
3. **Images created**:
- `authserver-my-custom-profile-latest`
- `worldserver-my-custom-profile-latest`
### Scheduled Builds
The nightly scheduled build always uses the **RealmMaster** profile. To schedule builds for different profiles, you can:
1. Create additional workflow files (e.g., `.github/workflows/build-all-modules.yml`)
2. Set different cron schedules
3. Hardcode the profile name in the workflow

View File

@@ -187,8 +187,6 @@ Because MySQL stores its hot data in a tmpfs (`/var/lib/mysql-runtime`) while pe
- If **any tables exist**, the script logs `Backup restoration completed successfully` and skips the expensive restore just as before.
- If **no tables are found or the query fails**, the script logs `Restoration marker found, but databases are empty - forcing re-import`, automatically clears the stale marker, and reruns the backup restore + `dbimport` pipeline so services always start with real data.
On graceful shutdown, the MySQL container now syncs the tmpfs datadir back into `/var/lib/mysql-persistent` so a normal restart keeps the latest state. Unclean shutdowns (host reboot, OOM kill) can still lose recent changes, so the backup restore path remains the safety net.
To complement that one-shot safety net, the long-running `ac-db-guard` service now watches the runtime tmpfs. It polls MySQL, and if it ever finds those schemas empty (the usual symptom after a daemon restart), it automatically reruns `db-import-conditional.sh` to rehydrate from the most recent backup before marking itself healthy. All auth/world services now depend on `ac-db-guard`'s health check, guaranteeing that AzerothCore never boots without real tables in memory. The guard also mounts the working SQL tree from `local-storage/source/azerothcore-playerbots/data/sql` into the db containers so that every `dbimport` run uses the exact SQL that matches your checked-out source, even if the Docker image was built earlier.
Because new features sometimes require schema changes even when the databases already contain data, `ac-db-guard` now performs a `dbimport` verification sweep (configurable via `DB_GUARD_VERIFY_INTERVAL_SECONDS`) to proactively apply any outstanding updates from the mounted SQL tree. By default it runs once per bootstrap and then every 24 hours, so the auth/world servers always see the columns/tables expected by their binaries without anyone having to run host scripts manually.

View File

@@ -158,7 +158,7 @@ The module collection is organized into the following categories:
| **[eluna-scripts](https://github.com/Isidorsson/Eluna-scripts.git)** | Collection of Lua scripts for creating custom gameplay mechanics and features |
| **[eluna-ts](https://github.com/azerothcore/eluna-ts.git)** | Adds a TS-to-Lua workflow so Eluna scripts can be authored with modern tooling |
| **[mod-aio](https://github.com/Rochet2/AIO.git)** | Pure Lua server-client communication system for bidirectional data transmission |
| **[mod-ale](https://github.com/azerothcore/mod-ale.git)** | ALE (AzerothCore Lua Engine) - Lua scripting engine for custom gameplay mechanics (formerly Eluna) |
| **[mod-ale](https://github.com/azerothcore/mod-ale.git)** | Adds Eluna Lua scripting engine for creating custom gameplay mechanics |
## Admin Tools

View File

@@ -1,336 +0,0 @@
# Deploying Pre-Built RealmMaster Images
This guide explains how to deploy AzerothCore RealmMaster using pre-built Docker images from Docker Hub. **No local building required!**
## What's Included in Pre-Built Images
The pre-built images are automatically built nightly with the **RealmMaster module profile**, which includes **32 carefully selected modules**:
- **MODULE_PLAYERBOTS** - AI-controlled player characters
- **MODULE_TRANSMOG** - Transmogrification system
- **MODULE_SOLO_LFG** - Solo dungeon finder
- **MODULE_ELUNA** - Lua scripting engine
- **MODULE_AIO** - All-in-one interface
- **MODULE_NPC_BUFFER** - Buff NPC
- **MODULE_NPC_BEASTMASTER** - Pet management
- **MODULE_SOLOCRAFT** - Solo dungeon scaling
- **MODULE_1V1_ARENA** - 1v1 arena system
- **MODULE_ACCOUNT_ACHIEVEMENTS** - Account-wide achievements
- ...and 22 more modules!
See `config/module-profiles/RealmMaster.json` for the complete list.
## Prerequisites
- Docker with Docker Compose v2
- 16GB+ RAM
- 64GB+ storage
- Linux/macOS/WSL2
## Quick Start
### 1. Clone the Repository
```bash
git clone https://github.com/uprightbass360/AzerothCore-RealmMaster.git
cd AzerothCore-RealmMaster
```
### 2. Create Configuration File
```bash
# Copy the pre-built images template
cp .env.prebuilt .env
```
### 3. Configure Docker Hub Username
Edit `.env` and set your Docker Hub username:
```bash
# Change this line to your Docker Hub username:
DOCKERHUB_USERNAME=your-dockerhub-username
```
### 4. Optional: Customize Settings
Edit `.env` to customize:
- **Server address**: `SERVER_ADDRESS=your-server-ip`
- **Passwords**: `MYSQL_ROOT_PASSWORD=your-password`
- **Playerbot population**: `PLAYERBOT_MIN_BOTS` and `PLAYERBOT_MAX_BOTS`
- **Server preset**: `SERVER_CONFIG_PRESET=fast-leveling` (or blizzlike, hardcore-pvp, casual-pve)
### 5. Deploy
```bash
./deploy.sh
```
The deployment will:
- Pull pre-built images from Docker Hub
- Set up MySQL database with all module SQL
- Configure client data
- Start all services
**First deployment takes 30-60 minutes** for database setup and client data download.
## Image Tags
The CI/CD workflow publishes images with **profile-specific tags** so you know exactly which modules are included:
### Profile-Tagged Images (Recommended)
Each module profile gets its own tag:
- **`:authserver-realmmaster-latest`** - RealmMaster profile (32 modules)
- **`:worldserver-realmmaster-latest`** - RealmMaster profile (32 modules)
- **`:authserver-realmmaster-YYYYMMDD`** - Date-tagged RealmMaster builds
- **`:worldserver-realmmaster-YYYYMMDD`** - Date-tagged RealmMaster builds
Other profiles (available when built via GitHub Actions):
- **`:authserver-suggested-modules-latest`** - Suggested modules profile (not yet published)
- **`:authserver-all-modules-latest`** - All modules profile (not yet published)
- **`:authserver-playerbots-only-latest`** - Playerbots only (not yet published)
**Note**: Currently only the RealmMaster profile is built nightly. Other profiles can be built on-demand by manually triggering the CI/CD workflow.
### Generic Tags (Backward Compatibility)
- **`:authserver-latest`** - Latest build (defaults to RealmMaster profile)
- **`:worldserver-latest`** - Latest build (defaults to RealmMaster profile)
### Choosing a Profile
In `.env.prebuilt`, set the `MODULE_PROFILE` variable:
```bash
# Choose your profile
MODULE_PROFILE=realmmaster # 32 modules (default, recommended)
# MODULE_PROFILE=suggested-modules # Alternative module set
# MODULE_PROFILE=all-modules # All supported modules
# MODULE_PROFILE=playerbots-only # Just playerbots
# Images automatically reference the selected profile
AC_AUTHSERVER_IMAGE_MODULES=${DOCKERHUB_USERNAME}/${COMPOSE_PROJECT_NAME}:authserver-${MODULE_PROFILE}-latest
AC_WORLDSERVER_IMAGE_MODULES=${DOCKERHUB_USERNAME}/${COMPOSE_PROJECT_NAME}:worldserver-${MODULE_PROFILE}-latest
```
### Using Date-Tagged Images
To pin to a specific build date, edit `.env`:
```bash
# Set your profile
MODULE_PROFILE=realmmaster
# Pin to a specific date (example: January 9, 2026)
AC_AUTHSERVER_IMAGE_MODULES=${DOCKERHUB_USERNAME}/${COMPOSE_PROJECT_NAME}:authserver-${MODULE_PROFILE}-20260109
AC_WORLDSERVER_IMAGE_MODULES=${DOCKERHUB_USERNAME}/${COMPOSE_PROJECT_NAME}:worldserver-${MODULE_PROFILE}-20260109
```
## Differences from Local Build
### What You DON'T Need
When using pre-built images, you **skip**:
- ❌ Running `./setup.sh` (module selection)
- ❌ Running `./build.sh` (compilation)
- ❌ 15-45 minute build time
- ❌ Build dependencies (Go compiler, etc.)
### What's the Same
Everything else works identically:
- ✅ Database setup and migrations
- ✅ Module SQL installation
- ✅ Configuration management
- ✅ Backup system
- ✅ All management commands
- ✅ phpMyAdmin and Keira3 tools
## Verifying Your Deployment
After deployment completes:
### 1. Check Container Status
```bash
./status.sh
```
You should see all services running:
- ✅ ac-mysql
- ✅ ac-authserver
- ✅ ac-worldserver
- ✅ ac-phpmyadmin
- ✅ ac-keira3
### 2. Verify Modules Are Loaded
Check the worldserver logs:
```bash
docker logs ac-worldserver | grep "module"
```
You should see messages about 32 modules being loaded.
### 3. Access Management Tools
- **phpMyAdmin**: http://localhost:8081
- **Keira3**: http://localhost:4201
## Post-Installation
### Create Admin Account
1. Attach to the worldserver container:
```bash
docker attach ac-worldserver
```
2. Create an account and set GM level:
```
account create admin password
account set gmlevel admin 3 -1
```
3. Detach: Press `Ctrl+P` then `Ctrl+Q`
### Configure Client
Edit your WoW 3.3.5a client's `realmlist.wtf`:
```
set realmlist 127.0.0.1
```
(Replace `127.0.0.1` with your server's IP if remote)
## Updating to Latest Images
To update to the latest nightly build:
```bash
# Pull latest images
docker compose pull
# Restart services
docker compose down
docker compose up -d
```
**Note**: Database schema updates will be applied automatically on restart.
## Switching Between Pre-Built and Local Build
### From Pre-Built to Local Build
If you want to customize modules and build locally:
```bash
# Remove pre-built .env
rm .env
# Run interactive setup
./setup.sh
# Build with your custom modules
./build.sh
# Deploy
./deploy.sh
```
### From Local Build to Pre-Built
If you want to use pre-built images instead:
```bash
# Back up your current .env
mv .env .env.custom
# Use pre-built configuration
cp .env.prebuilt .env
# Edit DOCKERHUB_USERNAME in .env
# Deploy
./deploy.sh
```
## Troubleshooting
### Image Pull Errors
**Problem**: `Error response from daemon: manifest not found`
**Solutions**:
1. Verify `DOCKERHUB_USERNAME` is set correctly in `.env`
2. Check that the images exist at: https://hub.docker.com/u/your-username
3. Ensure the CI/CD workflow has run successfully
### Module SQL Not Applied
**Problem**: Modules don't seem to be working
**Solution**: The module SQL is automatically applied during deployment. Check:
```bash
# Verify module SQL staging
ls -la storage/module-sql-updates/
# Check database for module tables
docker exec -it ac-mysql mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "SHOW TABLES" acore_world | grep -i module
```
### Performance Issues
**Problem**: Server is slow or laggy
**Solutions**:
1. Increase MySQL tmpfs size in `.env`: `MYSQL_RUNTIME_TMPFS_SIZE=16G`
2. Reduce playerbot population: `PLAYERBOT_MAX_BOTS=100`
3. Check system resources: `docker stats`
## Advanced Configuration
### Custom Module Selection
Pre-built images include all RealmMaster modules. To disable specific modules:
1. Edit server configuration files in `storage/config/`
2. Set module enable flags to 0
3. Restart worldserver: `docker compose restart ac-worldserver`
**Note**: You can only disable modules, not add new ones (requires local build).
### Server Configuration Presets
Apply configuration presets for different server types:
```bash
# In .env, set one of these presets:
SERVER_CONFIG_PRESET=blizzlike # Authentic WotLK experience (1x rates)
SERVER_CONFIG_PRESET=fast-leveling # 3x XP rates, QoL improvements
SERVER_CONFIG_PRESET=hardcore-pvp # Competitive PvP (1.5x rates)
SERVER_CONFIG_PRESET=casual-pve # Relaxed PvE (2x rates)
```
Restart after changing: `docker compose restart ac-worldserver`
## Getting Help
- **Documentation**: See other guides in `docs/`
- **GitHub Issues**: https://github.com/uprightbass360/AzerothCore-RealmMaster/issues
- **AzerothCore Discord**: https://discord.gg/gkt4y2x
## Next Steps
- [Database Management](DATABASE_MANAGEMENT.md) - Backups, restores, migrations
- [Getting Started Guide](GETTING_STARTED.md) - Detailed walkthrough
- [Troubleshooting](TROUBLESHOOTING.md) - Common issues and solutions
- [Module Catalog](MODULES.md) - Complete list of available modules

View File

@@ -1,213 +0,0 @@
# Release Strategy
This document explains how AzerothCore RealmMaster releases work and what they contain.
## Release Philosophy
Since **Docker images are stored on Docker Hub**, GitHub releases serve as **deployment packages** rather than source distributions. Each release contains everything users need to deploy pre-built images without building from source.
## What's in a Release?
### Release Assets (ZIP Archive)
Each release includes a downloadable `.zip` file containing:
```
azerothcore-realmmaster-v1.0.0-realmmaster.zip
├── .env.prebuilt # Pre-configured for Docker Hub images
├── docker-compose.yml # Service definitions
├── deploy.sh # Deployment script
├── status.sh # Status monitoring
├── cleanup.sh # Cleanup utilities
├── scripts/ # Required Python/Bash scripts
├── config/ # Module manifest and presets
├── docs/ # Complete documentation
├── QUICKSTART.md # Release-specific quick start
└── README.md # Project overview
```
### Release Notes
Each release includes:
- Module profile and count
- Docker Hub image tags (date-specific and latest)
- Quick start instructions
- Complete module list
- Build information (commit, date, source variant)
- Links to documentation
- Known issues
## Release Types
### 1. Profile-Based Releases
Each module profile gets its own release variant:
- **v1.0.0-realmmaster** - RealmMaster profile (32 modules, recommended)
- **v1.0.0-suggested-modules** - Alternative suggested module set
- **v1.0.0-all-modules** - All supported modules
- **v1.0.0-playerbots-only** - Just playerbots
Users choose the release that matches their desired module set.
### 2. Version Numbering
We use semantic versioning:
- **Major** (v1.0.0 → v2.0.0): Breaking changes, major feature additions
- **Minor** (v1.0.0 → v1.1.0): New modules, feature enhancements
- **Patch** (v1.0.0 → v1.0.1): Bug fixes, documentation updates
## Docker Hub Image Tags
Releases reference specific Docker Hub tags:
### Date-Tagged Images (Recommended for Production)
```
uprightbass360/azerothcore-realmmaster:authserver-realmmaster-20260109
uprightbass360/azerothcore-realmmaster:worldserver-realmmaster-20260109
```
- **Immutable**: Never change
- **Stable**: Guaranteed to match the release
- **Recommended**: For production deployments
### Latest Tags (Auto-Updated)
```
uprightbass360/azerothcore-realmmaster:authserver-realmmaster-latest
uprightbass360/azerothcore-realmmaster:worldserver-realmmaster-latest
```
- **Mutable**: Updated nightly by CI/CD
- **Convenient**: Always get the newest build
- **Use case**: Development, testing, staying current
## Creating a Release
### Automated (Recommended)
Use the GitHub Actions workflow:
1. Go to **Actions****Create Release**
2. Click **Run workflow**
3. Fill in:
- **Version**: `v1.0.0`
- **Profile**: `RealmMaster` (or other profile)
- **Pre-release**: Check if beta/RC
4. Click **Run workflow**
The workflow automatically:
- Creates deployment package with all files
- Generates release notes with module list
- Uploads ZIP archive as release asset
- Creates GitHub release with proper tags
### Manual
If you need to create a release manually:
```bash
# 1. Tag the release
git tag -a v1.0.0 -m "Release v1.0.0 - RealmMaster Profile"
git push origin v1.0.0
# 2. Create deployment package
./scripts/create-release-package.sh v1.0.0 RealmMaster
# 3. Create GitHub release
# Go to GitHub → Releases → Draft a new release
# - Tag: v1.0.0
# - Title: RealmMaster v1.0.0 - RealmMaster Profile
# - Upload: azerothcore-realmmaster-v1.0.0-realmmaster.zip
# - Add release notes
```
## Release Checklist
Before creating a release:
- [ ] Verify CI/CD build succeeded
- [ ] Test Docker Hub images work correctly
- [ ] Update CHANGELOG.md
- [ ] Update version in documentation if needed
- [ ] Verify all module SQL migrations are included
- [ ] Test deployment on clean system
- [ ] Update known issues section
## For Users: Using a Release
### Quick Start
```bash
# 1. Download release
wget https://github.com/uprightbass360/AzerothCore-RealmMaster/releases/download/v1.0.0/azerothcore-realmmaster-v1.0.0-realmmaster.zip
# 2. Extract
unzip azerothcore-realmmaster-v1.0.0-realmmaster.zip
cd azerothcore-realmmaster-v1.0.0-realmmaster
# 3. Configure
nano .env.prebuilt
# Set: DOCKERHUB_USERNAME=your-dockerhub-username
# 4. Deploy
mv .env.prebuilt .env
./deploy.sh
```
### Upgrading Between Releases
```bash
# 1. Backup your data
./scripts/bash/backup.sh
# 2. Download new release
wget https://github.com/.../releases/download/v1.1.0/...
# 3. Extract to new directory
unzip azerothcore-realmmaster-v1.1.0-realmmaster.zip
# 4. Copy your .env and data
cp old-version/.env new-version/.env
cp -r old-version/storage new-version/storage
# 5. Deploy new version
cd new-version
./deploy.sh
```
## Release Schedule
- **Nightly Builds**: Images built automatically at 2 AM UTC
- **Releases**: Created as needed when significant changes accumulate
- **LTS Releases**: Planned quarterly for long-term support
## Support
- **Release Issues**: https://github.com/uprightbass360/AzerothCore-RealmMaster/issues
- **Documentation**: Included in each release ZIP
- **Discord**: https://discord.gg/gkt4y2x
## FAQ
### Why are images on Docker Hub and not in releases?
Docker images can be 1-2GB each. GitHub has a 2GB file limit and releases should be lightweight. Docker Hub is designed for hosting images, GitHub releases are for deployment packages.
### Can I use latest tags in production?
We recommend **date-tagged images** for production (e.g., `authserver-realmmaster-20260109`). Latest tags are updated nightly and may have untested changes.
### How do I know which image version a release uses?
Check the release notes - they include the specific Docker Hub tags (date-stamped) that were tested with that release.
### What if I want to build from source instead?
Clone the repository and use `./setup.sh` + `./build.sh` instead of using pre-built releases. See [GETTING_STARTED.md](GETTING_STARTED.md) for instructions.
### Are releases required?
No! You can:
1. **Use releases**: Download ZIP, deploy pre-built images (easiest)
2. **Use nightly images**: Pull latest tags directly from Docker Hub
3. **Build from source**: Clone repo, build locally (most flexible)
Releases are just convenient snapshots for users who want stability.

View File

@@ -96,7 +96,7 @@ Comprehensive cleanup with multiple destruction levels and safety checks.
Starts all configured containers using appropriate profiles.
#### `scripts/bash/stop-containers.sh` - Graceful Shutdown
Stops all containers with proper cleanup and data protection. The MySQL container performs a shutdown-time sync from tmpfs to persistent storage.
Stops all containers with proper cleanup and data protection.
#### `status.sh` - Service Health Monitoring
```bash
@@ -415,51 +415,6 @@ Comprehensive deployment verification with health checks and service validation.
./scripts/bash/verify-deployment.sh --quick # Quick health check only
```
#### `scripts/bash/validate-env.sh` - Environment Configuration Validator
Validates `.env` configuration for required and optional variables with detailed reporting.
```bash
./scripts/bash/validate-env.sh # Basic validation (required vars only)
./scripts/bash/validate-env.sh --strict # Validate required + optional vars
./scripts/bash/validate-env.sh --quiet # Errors only, suppress success messages
```
**Exit Codes:**
- `0` - All required variables present (and optional if --strict)
- `1` - Missing required variables
- `2` - Missing optional variables (only in --strict mode)
**Validates:**
- **Project Configuration:** `COMPOSE_PROJECT_NAME`, `NETWORK_NAME`
- **Repository URLs:** Standard and playerbots AzerothCore repositories
- **Storage Paths:** `STORAGE_PATH`, `STORAGE_PATH_LOCAL`, `MODULES_REBUILD_SOURCE_PATH`
- **Database Settings:** MySQL credentials, ports, database names
- **Container Config:** Container names and user permissions
- **Build Paths:** Module rebuild source paths (optional)
- **Performance Tuning:** MySQL buffer pool, InnoDB settings (optional)
- **Image References:** Docker image tags (optional)
**Use Cases:**
- Pre-deployment validation
- Troubleshooting configuration issues
- CI/CD pipeline checks
- Documentation of environment requirements
**Example Output:**
```
Validating environment configuration...
✅ Loaded environment from /path/to/.env
Checking required variables...
✅ COMPOSE_PROJECT_NAME=azerothcore-realmmaster
✅ NETWORK_NAME=azerothcore
✅ STORAGE_PATH=./storage
✅ MYSQL_ROOT_PASSWORD=********
✅ All required variables are set
✅ Environment validation passed ✨
```
### Backup System Scripts
#### `scripts/bash/backup-scheduler.sh` - Automated Backup Service

View File

@@ -75,7 +75,7 @@ services:
| Upstream Concept | RealmMaster Equivalent | Notes |
| ---------------- | ---------------------- | ----- |
| MySQL container with bind-mounted storage | `ac-mysql` + `ac-storage-init` | Bind mounts live under `storage/` and `local-storage/`; tmpfs keeps runtime data fast and is synced to disk on graceful shutdown. |
| MySQL container with bind-mounted storage | `ac-mysql` + `ac-storage-init` | Bind mounts live under `storage/` and `local-storage/`; tmpfs keeps runtime data fast and is checkpointed to disk automatically. |
| Manual DB import container | `ac-db-import` & `ac-db-init` | Automatically imports schemas or restores from backups; disable by skipping the `db` profile if you truly want manual control. |
| World/Auth servers with optional DBC overrides | `ac-authserver-*` / `ac-worldserver-*` | Profile-based builds cover vanilla, playerbots, and custom module binaries. DBC overrides go into the shared client data mount just like upstream. |
| Client data bind mounts | `ac-client-data-standard` (or `-playerbots`) | Runs `scripts/bash/download-client-data.sh`, caches releases, and mounts them read-only into the worldserver. |

View File

@@ -449,7 +449,7 @@ if [ -n "$backup_path" ]; then
echo "⚠️ Backup restoration failed, will proceed with fresh database setup"
fi
else
echo " No valid SQL backups found - proceeding with fresh setup"
echo " No valid backups found - proceeding with fresh setup"
echo "$(date): No backup found - fresh setup needed" > "$RESTORE_FAILED_MARKER"
fi

View File

@@ -141,10 +141,6 @@ run_post_install_hooks(){
export MODULES_ROOT="${MODULES_ROOT:-/modules}"
export LUA_SCRIPTS_TARGET="/azerothcore/lua_scripts"
# Pass build environment variables to hooks
export STACK_SOURCE_VARIANT="${STACK_SOURCE_VARIANT:-}"
export MODULES_REBUILD_SOURCE_PATH="${MODULES_REBUILD_SOURCE_PATH:-}"
# Execute the hook script
if "$hook_script"; then
ok "Hook '$hook' completed successfully"
@@ -178,18 +174,7 @@ install_enabled_modules(){
continue
fi
if [ -d "$dir/.git" ]; then
info "$dir already present; checking for updates"
(cd "$dir" && git fetch origin >/dev/null 2>&1 || warn "Failed to fetch updates for $dir")
local current_branch
current_branch=$(cd "$dir" && git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "master")
if (cd "$dir" && git pull origin "$current_branch" 2>&1 | grep -q "Already up to date"); then
info "$dir is already up to date"
else
ok "$dir updated from remote"
fi
if [ -n "$ref" ]; then
(cd "$dir" && git checkout "$ref") || warn "Unable to checkout ref $ref for $dir"
fi
info "$dir already present; skipping clone"
elif [ -d "$dir" ]; then
warn "$dir exists but is not a git repository; leaving in place"
else

View File

@@ -11,67 +11,67 @@ if ! command -v "$ORIGINAL_ENTRYPOINT" >/dev/null 2>&1; then
fi
TARGET_SPEC="${MYSQL_RUNTIME_USER:-${CONTAINER_USER:-}}"
target_group_name=""
if [ -n "${TARGET_SPEC:-}" ] && [ "${TARGET_SPEC}" != "0:0" ]; then
if [[ "$TARGET_SPEC" != *:* ]]; then
echo "mysql-entrypoint: Expected MYSQL_RUNTIME_USER/CONTAINER_USER in uid:gid form, got '${TARGET_SPEC}'" >&2
exit 1
fi
IFS=':' read -r TARGET_UID TARGET_GID <<< "$TARGET_SPEC"
if ! [[ "$TARGET_UID" =~ ^[0-9]+$ ]] || ! [[ "$TARGET_GID" =~ ^[0-9]+$ ]]; then
echo "mysql-entrypoint: UID/GID must be numeric (received uid='${TARGET_UID}' gid='${TARGET_GID}')" >&2
exit 1
fi
if ! id mysql >/dev/null 2>&1; then
echo "mysql-entrypoint: mysql user not found in container" >&2
exit 1
fi
current_uid="$(id -u mysql)"
current_gid="$(id -g mysql)"
# Adjust group if needed
if [ "$current_gid" != "$TARGET_GID" ]; then
if groupmod -g "$TARGET_GID" mysql 2>/dev/null; then
target_group_name="mysql"
else
existing_group="$(getent group "$TARGET_GID" | cut -d: -f1 || true)"
if [ -z "$existing_group" ]; then
existing_group="mysql-host"
if ! getent group "$existing_group" >/dev/null 2>&1; then
groupadd -g "$TARGET_GID" "$existing_group"
fi
fi
usermod -g "$existing_group" mysql
target_group_name="$existing_group"
fi
else
target_group_name="$(getent group mysql | cut -d: -f1)"
fi
if [ -z "$target_group_name" ]; then
target_group_name="$(getent group "$TARGET_GID" | cut -d: -f1 || true)"
fi
# Adjust user UID if needed
if [ "$current_uid" != "$TARGET_UID" ]; then
if getent passwd "$TARGET_UID" >/dev/null 2>&1 && [ "$(getent passwd "$TARGET_UID" | cut -d: -f1)" != "mysql" ]; then
echo "mysql-entrypoint: UID ${TARGET_UID} already in use by $(getent passwd "$TARGET_UID" | cut -d: -f1)." >&2
echo "mysql-entrypoint: Please choose a different CONTAINER_USER or adjust the image." >&2
exit 1
fi
usermod -u "$TARGET_UID" mysql
fi
# Ensure group lookup after potential changes
target_group_name="$(getent group "$TARGET_GID" | cut -d: -f1 || echo "$target_group_name")"
else
target_group_name="$(getent group mysql | cut -d: -f1 || echo mysql)"
if [ -z "${TARGET_SPEC:-}" ] || [ "${TARGET_SPEC}" = "0:0" ]; then
exec "$ORIGINAL_ENTRYPOINT" "$@"
fi
if [[ "$TARGET_SPEC" != *:* ]]; then
echo "mysql-entrypoint: Expected MYSQL_RUNTIME_USER/CONTAINER_USER in uid:gid form, got '${TARGET_SPEC}'" >&2
exit 1
fi
IFS=':' read -r TARGET_UID TARGET_GID <<< "$TARGET_SPEC"
if ! [[ "$TARGET_UID" =~ ^[0-9]+$ ]] || ! [[ "$TARGET_GID" =~ ^[0-9]+$ ]]; then
echo "mysql-entrypoint: UID/GID must be numeric (received uid='${TARGET_UID}' gid='${TARGET_GID}')" >&2
exit 1
fi
if ! id mysql >/dev/null 2>&1; then
echo "mysql-entrypoint: mysql user not found in container" >&2
exit 1
fi
current_uid="$(id -u mysql)"
current_gid="$(id -g mysql)"
# Adjust group if needed
target_group_name=""
if [ "$current_gid" != "$TARGET_GID" ]; then
if groupmod -g "$TARGET_GID" mysql 2>/dev/null; then
target_group_name="mysql"
else
existing_group="$(getent group "$TARGET_GID" | cut -d: -f1 || true)"
if [ -z "$existing_group" ]; then
existing_group="mysql-host"
if ! getent group "$existing_group" >/dev/null 2>&1; then
groupadd -g "$TARGET_GID" "$existing_group"
fi
fi
usermod -g "$existing_group" mysql
target_group_name="$existing_group"
fi
else
target_group_name="$(getent group mysql | cut -d: -f1)"
fi
if [ -z "$target_group_name" ]; then
target_group_name="$(getent group "$TARGET_GID" | cut -d: -f1 || true)"
fi
# Adjust user UID if needed
if [ "$current_uid" != "$TARGET_UID" ]; then
if getent passwd "$TARGET_UID" >/dev/null 2>&1 && [ "$(getent passwd "$TARGET_UID" | cut -d: -f1)" != "mysql" ]; then
echo "mysql-entrypoint: UID ${TARGET_UID} already in use by $(getent passwd "$TARGET_UID" | cut -d: -f1)." >&2
echo "mysql-entrypoint: Please choose a different CONTAINER_USER or adjust the image." >&2
exit 1
fi
usermod -u "$TARGET_UID" mysql
fi
# Ensure group lookup after potential changes
target_group_name="$(getent group "$TARGET_GID" | cut -d: -f1 || echo "$target_group_name")"
# Update ownership on relevant directories if they exist
for path in /var/lib/mysql-runtime /var/lib/mysql /var/lib/mysql-persistent /backups; do
if [ -e "$path" ]; then
@@ -79,91 +79,6 @@ for path in /var/lib/mysql-runtime /var/lib/mysql /var/lib/mysql-persistent /bac
fi
done
# Minimal fix: Restore data from persistent storage on startup and sync on shutdown only
RUNTIME_DIR="/var/lib/mysql-runtime"
PERSISTENT_DIR="/var/lib/mysql-persistent"
sync_datadir() {
if [ ! -d "$RUNTIME_DIR" ]; then
echo "⚠️ Runtime directory not found: $RUNTIME_DIR"
return 1
fi
if [ ! -d "$PERSISTENT_DIR" ]; then
echo "⚠️ Persistent directory not found: $PERSISTENT_DIR"
return 1
fi
user_schema_count="$(find "$RUNTIME_DIR" -mindepth 1 -maxdepth 1 -type d \
! -name mysql \
! -name performance_schema \
! -name information_schema \
! -name sys \
! -name "#innodb_temp" \
! -name "#innodb_redo" 2>/dev/null | wc -l | tr -d ' ')"
if [ "${user_schema_count:-0}" -eq 0 ]; then
echo "⚠️ Runtime data appears empty (system schemas only); skipping sync"
return 0
fi
echo "📦 Syncing MySQL data to persistent storage..."
if command -v rsync >/dev/null 2>&1; then
rsync -a --delete \
--exclude='.restore-completed' \
--exclude='.restore-failed' \
--exclude='.import-completed' \
--exclude='backup.sql' \
"$RUNTIME_DIR"/ "$PERSISTENT_DIR"/
else
# Mirror the runtime state while preserving marker files.
find "$PERSISTENT_DIR" -mindepth 1 -maxdepth 1 \
! -name ".restore-completed" \
! -name ".restore-failed" \
! -name ".import-completed" \
! -name "backup.sql" \
-exec rm -rf {} + 2>/dev/null || true
cp -a "$RUNTIME_DIR"/. "$PERSISTENT_DIR"/
fi
chown -R mysql:"$target_group_name" "$PERSISTENT_DIR"
echo "✅ Sync completed"
}
handle_shutdown() {
echo "🔻 Shutdown signal received"
if command -v mysqladmin >/dev/null 2>&1; then
if mysqladmin -h localhost -u root -p"${MYSQL_ROOT_PASSWORD:-}" shutdown 2>/dev/null; then
echo "✅ MySQL shutdown complete"
sync_datadir || true
else
echo "⚠️ mysqladmin shutdown failed; skipping sync to avoid corruption"
fi
else
echo "⚠️ mysqladmin not found; skipping sync"
fi
if [ -n "${child_pid:-}" ] && kill -0 "$child_pid" 2>/dev/null; then
wait "$child_pid" || true
fi
exit 0
}
# Simple startup restoration
if [ -d "$PERSISTENT_DIR" ]; then
# Check for MySQL data files (exclude marker files starting with .)
if find "$PERSISTENT_DIR" -maxdepth 1 -name "*" ! -name ".*" ! -path "$PERSISTENT_DIR" | grep -q .; then
if [ -d "$RUNTIME_DIR" ] && [ -z "$(ls -A "$RUNTIME_DIR" 2>/dev/null)" ]; then
echo "🔄 Restoring MySQL data from persistent storage..."
cp -a "$PERSISTENT_DIR"/* "$RUNTIME_DIR/" 2>/dev/null || true
chown -R mysql:"$target_group_name" "$RUNTIME_DIR"
echo "✅ Data restored from persistent storage"
fi
fi
fi
# Simple approach: restore on startup only
# Data loss window exists but prevents complete loss on restart
trap handle_shutdown TERM INT
disable_binlog="${MYSQL_DISABLE_BINLOG:-}"
if [ "${disable_binlog}" = "1" ]; then
add_skip_flag=1
@@ -178,6 +93,4 @@ if [ "${disable_binlog}" = "1" ]; then
fi
fi
"$ORIGINAL_ENTRYPOINT" "$@" &
child_pid=$!
wait "$child_pid"
exec "$ORIGINAL_ENTRYPOINT" "$@"

View File

@@ -41,68 +41,9 @@ Reads patch definitions from module metadata.
## Module-Specific Hooks
Module-specific hooks are named after their primary module and handle unique setup requirements.
### `mod-ale-patches`
Applies compatibility patches for mod-ale (ALE - AzerothCore Lua Engine, formerly Eluna) when building with the AzerothCore playerbots fork.
**Auto-Detection:**
The hook automatically detects if you're building with the playerbots fork by checking:
1. `STACK_SOURCE_VARIANT=playerbots` environment variable
2. `MODULES_REBUILD_SOURCE_PATH` contains "azerothcore-playerbots"
**Patches Applied:**
#### SendTrainerList Compatibility Fix
**When Applied:** Automatically for playerbots fork (or when `APPLY_SENDTRAINERLIST_PATCH=1`)
**What it fixes:** Adds missing `GetGUID()` call to fix trainer list display
**File:** `src/LuaEngine/methods/PlayerMethods.h`
**Change:**
```cpp
// Before (broken)
player->GetSession()->SendTrainerList(obj);
// After (fixed)
player->GetSession()->SendTrainerList(obj->GetGUID());
```
#### MovePath Compatibility Fix
**When Applied:** Only when explicitly enabled with `APPLY_MOVEPATH_PATCH=1` (disabled by default)
**What it fixes:** Updates deprecated waypoint movement API
**File:** `src/LuaEngine/methods/CreatureMethods.h`
**Change:**
```cpp
// Before (deprecated)
MoveWaypoint(creature->GetWaypointPath(), true);
// After (updated API)
MovePath(creature->GetWaypointPath(), FORCED_MOVEMENT_RUN);
```
**Note:** Currently disabled by default as testing shows it's not required for normal operation.
**Feature Flags:**
```bash
# Automatically set for playerbots fork
APPLY_SENDTRAINERLIST_PATCH=1
# Disabled by default - enable if needed
APPLY_MOVEPATH_PATCH=0
```
**Debug Output:**
The hook provides detailed debug information during builds:
```
🔧 mod-ale-patches: Applying playerbots fork compatibility fixes to mod-ale
✅ Playerbots detected via MODULES_REBUILD_SOURCE_PATH
✅ Applied SendTrainerList compatibility fix
✅ Applied 1 compatibility patch(es)
```
**Why This Exists:**
The playerbots fork has slightly different API signatures in certain WorldSession methods. These patches ensure mod-ale (Eluna) compiles and functions correctly with both standard AzerothCore and the playerbots fork.
### `black-market-setup`
Black Market specific setup tasks.
Module-specific hooks are named after their primary module:
- `mod-ale-patches` - Apply mod-ale compatibility fixes
- `black-market-setup` - Black Market specific setup
## Usage in Manifest

View File

@@ -1,6 +1,5 @@
#!/bin/bash
# Module-specific hook for mod-ale compatibility patches
# NOTE: These patches are primarily needed for the AzerothCore playerbots fork
set -e
# Hook environment
@@ -8,44 +7,12 @@ MODULE_KEY="${MODULE_KEY:-}"
MODULE_DIR="${MODULE_DIR:-}"
MODULE_NAME="${MODULE_NAME:-}"
# Detect if we're building with playerbots fork
IS_PLAYERBOTS_FORK=0
# Method 1: Check STACK_SOURCE_VARIANT environment variable
if [ "${STACK_SOURCE_VARIANT:-}" = "playerbots" ]; then
IS_PLAYERBOTS_FORK=1
echo " ✅ Playerbots detected via STACK_SOURCE_VARIANT"
# Method 2: Check MODULES_REBUILD_SOURCE_PATH
elif [ -n "${MODULES_REBUILD_SOURCE_PATH:-}" ] && echo "${MODULES_REBUILD_SOURCE_PATH}" | grep -q "azerothcore-playerbots"; then
IS_PLAYERBOTS_FORK=1
echo " ✅ Playerbots detected via MODULES_REBUILD_SOURCE_PATH"
else
echo " ❌ Playerbots fork not detected"
echo " 🔍 Debug: STACK_SOURCE_VARIANT='${STACK_SOURCE_VARIANT:-}'"
echo " 🔍 Debug: MODULES_REBUILD_SOURCE_PATH='${MODULES_REBUILD_SOURCE_PATH:-}'"
fi
# Feature flags (set to 0 to disable specific patches)
APPLY_MOVEPATH_PATCH="${APPLY_MOVEPATH_PATCH:-0}" # Disabled by default - appears unnecessary
# SendTrainerList patch: auto-detect based on fork, but can be overridden
if [ -z "${APPLY_SENDTRAINERLIST_PATCH:-}" ]; then
APPLY_SENDTRAINERLIST_PATCH="$IS_PLAYERBOTS_FORK" # Only needed for playerbots fork
else
APPLY_SENDTRAINERLIST_PATCH="${APPLY_SENDTRAINERLIST_PATCH}"
fi
# Override keyword patch: always apply (C++11 best practice)
APPLY_OVERRIDE_PATCH="${APPLY_OVERRIDE_PATCH:-1}"
if [ -z "$MODULE_DIR" ] || [ ! -d "$MODULE_DIR" ]; then
echo "❌ mod-ale-patches: Invalid module directory: $MODULE_DIR"
exit 2
fi
if [ "$IS_PLAYERBOTS_FORK" = "1" ]; then
echo "🔧 mod-ale-patches: Applying playerbots fork compatibility fixes to $MODULE_NAME"
else
echo "🔧 mod-ale-patches: Checking compatibility fixes for $MODULE_NAME"
fi
echo "🔧 mod-ale-patches: Applying compatibility fixes to $MODULE_NAME"
# Apply MovePath compatibility patch
apply_movepath_patch() {
@@ -70,85 +37,10 @@ apply_movepath_patch() {
fi
}
# Apply override keyword patch
apply_override_patch() {
local found_files=()
# Search for .cpp and .h files that need override keyword
while IFS= read -r -d '' file; do
if grep -l 'void OnPlayerLogin(Player\* player)' "$file" >/dev/null 2>&1; then
found_files+=("$file")
fi
done < <(find "$MODULE_DIR" -name "*.cpp" -o -name "*.h" -print0)
if [ ${#found_files[@]} -eq 0 ]; then
echo " ✅ No files need override keyword fix"
return 0
fi
local patch_count=0
for file in "${found_files[@]}"; do
# Check if OnPlayerLogin exists without override keyword
if grep -q 'void OnPlayerLogin(Player\* player) {' "$file" && ! grep -q 'void OnPlayerLogin(Player\* player) override {' "$file"; then
if sed -i 's/void OnPlayerLogin(Player\* player) {/void OnPlayerLogin(Player* player) override {/' "$file"; then
echo " ✅ Applied override keyword fix to $(basename "$file")"
patch_count=$((patch_count + 1))
else
echo " ❌ Failed to apply override keyword fix to $(basename "$file")"
return 2
fi
fi
done
if [ $patch_count -eq 0 ]; then
echo " ✅ Override keyword fix already present"
else
echo " ✅ Applied override keyword fix to $patch_count file(s)"
fi
return 0
}
# Apply SendTrainerList compatibility patch
apply_sendtrainerlist_patch() {
local target_file="$MODULE_DIR/src/LuaEngine/methods/PlayerMethods.h"
if [ ! -f "$target_file" ]; then
echo " ⚠️ SendTrainerList patch target file missing: $target_file"
return 1
fi
# Check if the buggy code exists (with ->GetGUID())
if grep -q 'player->GetSession()->SendTrainerList(obj->GetGUID());' "$target_file"; then
# Apply the fix by casting to Creature* instead of using GetGUID()
if sed -i 's/player->GetSession()->SendTrainerList(obj->GetGUID());/if (Creature* creature = obj->ToCreature()) player->GetSession()->SendTrainerList(creature);/' "$target_file"; then
echo " ✅ Applied SendTrainerList compatibility fix"
return 0
else
echo " ❌ Failed to apply SendTrainerList compatibility fix"
return 2
fi
else
echo " ✅ SendTrainerList compatibility fix already present"
return 0
fi
}
# Apply all patches
patch_count=0
if [ "$APPLY_OVERRIDE_PATCH" = "1" ]; then
if apply_override_patch; then
patch_count=$((patch_count + 1))
fi
fi
if [ "$APPLY_MOVEPATH_PATCH" = "1" ]; then
if apply_movepath_patch; then
patch_count=$((patch_count + 1))
fi
fi
if [ "$APPLY_SENDTRAINERLIST_PATCH" = "1" ]; then
if apply_sendtrainerlist_patch; then
patch_count=$((patch_count + 1))
fi
if apply_movepath_patch; then
patch_count=$((patch_count + 1))
fi
if [ $patch_count -eq 0 ]; then

View File

@@ -1,161 +0,0 @@
#!/usr/bin/env python3
"""
Apply a module profile to .env file for CI/CD builds.
This script reads a module profile JSON and enables the specified modules
in the .env file, ready for automated builds.
"""
import argparse
import json
import sys
from pathlib import Path
from typing import List, Set
def load_profile(profile_path: Path) -> List[str]:
"""Load module list from a profile JSON file."""
try:
with open(profile_path, 'r') as f:
data = json.load(f)
except FileNotFoundError:
print(f"ERROR: Profile not found: {profile_path}", file=sys.stderr)
sys.exit(1)
except json.JSONDecodeError as e:
print(f"ERROR: Invalid JSON in profile: {e}", file=sys.stderr)
sys.exit(1)
modules = data.get('modules', [])
if not isinstance(modules, list):
print("ERROR: 'modules' must be a list in profile JSON", file=sys.stderr)
sys.exit(1)
return [m.strip() for m in modules if m.strip()]
def read_env_template(template_path: Path) -> List[str]:
"""Read the .env.template file."""
try:
with open(template_path, 'r') as f:
return f.readlines()
except FileNotFoundError:
print(f"ERROR: Template not found: {template_path}", file=sys.stderr)
sys.exit(1)
def apply_profile_to_env(template_lines: List[str], enabled_modules: Set[str]) -> List[str]:
"""
Process template lines and enable specified modules.
Sets MODULE_* variables to 1 if they're in enabled_modules, otherwise keeps template value.
"""
output_lines = []
for line in template_lines:
stripped = line.strip()
# Check if this is a MODULE_ variable line
if stripped.startswith('MODULE_') and '=' in stripped:
# Extract the module name (before the =)
module_name = stripped.split('=')[0].strip()
if module_name in enabled_modules:
# Enable this module
output_lines.append(f"{module_name}=1\n")
else:
# Keep original line (usually =0 or commented)
output_lines.append(line)
else:
# Not a module line, keep as-is
output_lines.append(line)
return output_lines
def write_env_file(env_path: Path, lines: List[str]):
"""Write the processed lines to .env file."""
try:
with open(env_path, 'w') as f:
f.writelines(lines)
print(f"✅ Applied profile to {env_path}")
except IOError as e:
print(f"ERROR: Failed to write .env file: {e}", file=sys.stderr)
sys.exit(1)
def main():
parser = argparse.ArgumentParser(
description='Apply a module profile to .env file for automated builds'
)
parser.add_argument(
'profile',
help='Name of the profile (e.g., RealmMaster) or path to profile JSON'
)
parser.add_argument(
'--env-template',
default='.env.template',
help='Path to .env.template file (default: .env.template)'
)
parser.add_argument(
'--env-output',
default='.env',
help='Path to output .env file (default: .env)'
)
parser.add_argument(
'--profiles-dir',
default='config/module-profiles',
help='Directory containing profile JSON files (default: config/module-profiles)'
)
parser.add_argument(
'--list-modules',
action='store_true',
help='List modules that will be enabled and exit'
)
args = parser.parse_args()
# Resolve profile path
profile_path = Path(args.profile)
if not profile_path.exists():
# Try treating it as a profile name
profile_path = Path(args.profiles_dir) / f"{args.profile}.json"
if not profile_path.exists():
print(f"ERROR: Profile not found: {args.profile}", file=sys.stderr)
print(f" Tried: {Path(args.profile)}", file=sys.stderr)
print(f" Tried: {profile_path}", file=sys.stderr)
sys.exit(1)
# Load the profile
print(f"📋 Loading profile: {profile_path.name}")
enabled_modules = set(load_profile(profile_path))
if args.list_modules:
print(f"\nModules to be enabled ({len(enabled_modules)}):")
for module in sorted(enabled_modules):
print(f"{module}")
return
print(f"✓ Found {len(enabled_modules)} modules in profile")
# Read template
template_path = Path(args.env_template)
template_lines = read_env_template(template_path)
# Apply profile
output_lines = apply_profile_to_env(template_lines, enabled_modules)
# Write output
env_path = Path(args.env_output)
write_env_file(env_path, output_lines)
print(f"✓ Profile '{profile_path.stem}' applied successfully")
print(f"\nEnabled modules:")
for module in sorted(enabled_modules)[:10]: # Show first 10
print(f"{module}")
if len(enabled_modules) > 10:
print(f" ... and {len(enabled_modules) - 10} more")
if __name__ == '__main__':
main()

View File

@@ -185,7 +185,7 @@ readonly DEFAULT_DOMAIN_PLACEHOLDER="your-domain.com"
# Module preset names (not in template)
readonly DEFAULT_PRESET_SUGGESTED="suggested-modules"
readonly DEFAULT_PRESET_PLAYERBOTS="suggested-modules-playerbots"
readonly DEFAULT_PRESET_PLAYERBOTS="playerbots-suggested-modules"
# Health check configuration (loaded via loop)
readonly -a HEALTHCHECK_KEYS=(
@@ -1487,16 +1487,11 @@ fi
MODULES_CPP_LIST="$(IFS=','; printf '%s' "${enabled_cpp_module_keys[*]}")"
fi
# Determine source variant based ONLY on playerbots module
local STACK_IMAGE_MODE="standard"
local STACK_SOURCE_VARIANT="core"
if [ "$MODULE_PLAYERBOTS" = "1" ] || [ "$PLAYERBOT_ENABLED" = "1" ]; then
STACK_SOURCE_VARIANT="playerbots"
fi
# Determine image mode based on source variant and build requirements
local STACK_IMAGE_MODE="standard"
if [ "$STACK_SOURCE_VARIANT" = "playerbots" ]; then
STACK_IMAGE_MODE="playerbots"
STACK_SOURCE_VARIANT="playerbots"
elif [ "$NEEDS_CXX_REBUILD" = "1" ]; then
STACK_IMAGE_MODE="modules"
fi
@@ -1592,7 +1587,7 @@ fi
fi
local default_source_rel="${LOCAL_STORAGE_ROOT}/source/azerothcore"
if [ "$STACK_SOURCE_VARIANT" = "playerbots" ]; then
if [ "$MODULE_PLAYERBOTS" = "1" ]; then
default_source_rel="${LOCAL_STORAGE_ROOT}/source/azerothcore-playerbots"
fi