diff --git a/.env.prebuilt b/.env.prebuilt new file mode 100644 index 0000000..68a9dc9 --- /dev/null +++ b/.env.prebuilt @@ -0,0 +1,321 @@ +# ================================================================================ +# 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 diff --git a/.github/workflows/build-and-publish.yml b/.github/workflows/build-and-publish.yml new file mode 100644 index 0000000..eb2263f --- /dev/null +++ b/.github/workflows/build-and-publish.yml @@ -0,0 +1,248 @@ +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 "
" >> $GITHUB_STEP_SUMMARY + echo "View enabled modules" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + grep '^MODULE_.*=1' .env | sed 's/=1//' || true >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "
" >> $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 diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml new file mode 100644 index 0000000..b2a5ada --- /dev/null +++ b/.github/workflows/create-release.yml @@ -0,0 +1,246 @@ +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 + cat > "${PACKAGE_NAME}/QUICKSTART.md" <> $GITHUB_ENV + + - name: Generate release notes + run: | + cat > release_notes.md <> $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 diff --git a/README.md b/README.md index 4453d59..3861b24 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,13 @@ 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) @@ -45,6 +47,25 @@ 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 diff --git a/docs/CICD.md b/docs/CICD.md new file mode 100644 index 0000000..898b936 --- /dev/null +++ b/docs/CICD.md @@ -0,0 +1,321 @@ +# 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): +- `/azerothcore-realmmaster:authserver-realmmaster-latest` ✅ Built nightly +- `/azerothcore-realmmaster:authserver-realmmaster-YYYYMMDD` ✅ Built nightly +- `/azerothcore-realmmaster:worldserver-realmmaster-latest` ✅ Built nightly +- `/azerothcore-realmmaster:worldserver-realmmaster-YYYYMMDD` ✅ Built nightly + +**Generic Tags** (backward compatibility, defaults to RealmMaster profile): +- `/azerothcore-realmmaster:authserver-latest` ✅ Built nightly +- `/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 /azerothcore-realmmaster:authserver-realmmaster-latest +docker pull /azerothcore-realmmaster:worldserver-realmmaster-latest + +# Or pull specific date-tagged images +docker pull /azerothcore-realmmaster:authserver-realmmaster-20260109 +docker pull /azerothcore-realmmaster:worldserver-realmmaster-20260109 + +# Or use generic latest tags (defaults to RealmMaster profile) +docker pull /azerothcore-realmmaster:authserver-latest +docker pull /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 diff --git a/docs/PREBUILT_IMAGES.md b/docs/PREBUILT_IMAGES.md new file mode 100644 index 0000000..f520cc1 --- /dev/null +++ b/docs/PREBUILT_IMAGES.md @@ -0,0 +1,339 @@ +# 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: +DOCKERHUB_USERNAME=your-dockerhub-username + +# To (example): +DOCKERHUB_USERNAME=uprightbass360 +``` + +### 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 diff --git a/docs/RELEASES.md b/docs/RELEASES.md new file mode 100644 index 0000000..5079da6 --- /dev/null +++ b/docs/RELEASES.md @@ -0,0 +1,213 @@ +# 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=uprightbass360 + +# 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. diff --git a/scripts/python/apply_module_profile.py b/scripts/python/apply_module_profile.py new file mode 100755 index 0000000..35c73a4 --- /dev/null +++ b/scripts/python/apply_module_profile.py @@ -0,0 +1,161 @@ +#!/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()