1 Commits

Author SHA1 Message Date
uprightbass360
ae23bc2146 adds workflow build for RealmMaster profile 2026-01-09 18:35:14 -05:00
6 changed files with 1381 additions and 0 deletions

306
.env.prebuilt Normal file
View File

@@ -0,0 +1,306 @@
# ================================================================================
# 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.) - Recommended
# - suggested-modules: Alternative suggested module set
# - all-modules: All supported modules
# - playerbots-only: Just playerbots
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
# 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
# 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

240
.github/workflows/build-and-publish.yml vendored Normal file
View File

@@ -0,0 +1,240 @@
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"
- 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//' || true >> $GITHUB_STEP_SUMMARY
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

@@ -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

316
docs/CICD.md Normal file
View File

@@ -0,0 +1,316 @@
# 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`
- `<dockerhub-username>/azerothcore-realmmaster:authserver-realmmaster-YYYYMMDD`
- `<dockerhub-username>/azerothcore-realmmaster:worldserver-realmmaster-latest`
- `<dockerhub-username>/azerothcore-realmmaster:worldserver-realmmaster-YYYYMMDD`
**Generic Tags** (backward compatibility, defaults to RealmMaster profile):
- `<dockerhub-username>/azerothcore-realmmaster:authserver-latest`
- `<dockerhub-username>/azerothcore-realmmaster:worldserver-latest`
The profile name in the tag tells you which module set is included (e.g., `realmmaster`, `suggested-modules`, `all-modules`).
## 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

337
docs/PREBUILT_IMAGES.md Normal file
View File

@@ -0,0 +1,337 @@
# 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 available profiles (if built):
- **`:authserver-suggested-modules-latest`** - Suggested modules profile
- **`:authserver-all-modules-latest`** - All modules profile
- **`:authserver-playerbots-only-latest`** - Playerbots only
### 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

@@ -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()