mirror of
https://github.com/uprightbass360/AzerothCore-RealmMaster.git
synced 2026-01-13 00:58:34 +00:00
Introduce dynamic overrides and rename module manifest
This commit is contained in:
@@ -8,7 +8,7 @@ from pathlib import Path
|
||||
|
||||
def load_module_state(root: Path) -> dict:
|
||||
env_path = root / ".env"
|
||||
manifest_path = root / "config" / "modules.json"
|
||||
manifest_path = root / "config" / "module-manifest.json"
|
||||
modules_py = root / "scripts" / "modules.py"
|
||||
|
||||
try:
|
||||
|
||||
@@ -7,6 +7,7 @@ set -euo pipefail
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/.."
|
||||
DEFAULT_COMPOSE_FILE="$ROOT_DIR/docker-compose.yml"
|
||||
ENV_FILE="$ROOT_DIR/.env"
|
||||
source "$ROOT_DIR/scripts/lib/compose_overrides.sh"
|
||||
declare -a COMPOSE_FILE_ARGS=()
|
||||
|
||||
BLUE='\033[0;34m'
|
||||
@@ -46,15 +47,7 @@ resolve_project_name(){
|
||||
}
|
||||
|
||||
init_compose_files(){
|
||||
COMPOSE_FILE_ARGS=(-f "$DEFAULT_COMPOSE_FILE")
|
||||
if [ "$(read_env MYSQL_EXPOSE_PORT "0")" = "1" ]; then
|
||||
local extra_file="$ROOT_DIR/docker-compose.mysql-expose.yml"
|
||||
if [ -f "$extra_file" ]; then
|
||||
COMPOSE_FILE_ARGS+=(-f "$extra_file")
|
||||
else
|
||||
warn "MYSQL_EXPOSE_PORT=1 but $extra_file missing; skipping port override."
|
||||
fi
|
||||
fi
|
||||
compose_overrides::build_compose_args "$ROOT_DIR" "$ENV_FILE" "$DEFAULT_COMPOSE_FILE" COMPOSE_FILE_ARGS
|
||||
}
|
||||
|
||||
init_compose_files
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
# Post-Install Hooks Refactoring Summary
|
||||
|
||||
## What Was Accomplished
|
||||
|
||||
### 1. **Legacy System Issues**
|
||||
- Hardcoded hooks in `manage-modules.sh` (only 2 implemented)
|
||||
- 26 undefined hooks from Eluna modules causing warnings
|
||||
- No extensibility or maintainability
|
||||
|
||||
### 2. **New Architecture Implemented**
|
||||
|
||||
#### **External Hook Scripts** (`scripts/hooks/`)
|
||||
- `copy-standard-lua` - Generic Lua script copying for Eluna modules
|
||||
- `copy-aio-lua` - AIO-specific Lua script handling
|
||||
- `mod-ale-patches` - mod-ale compatibility patches
|
||||
- `black-market-setup` - Black Market specific setup
|
||||
- `README.md` - Complete documentation
|
||||
|
||||
#### **Manifest-Driven Configuration**
|
||||
- All hooks now defined in `config/modules.json`
|
||||
- Standardized hook names (kebab-case)
|
||||
- No more undefined hooks
|
||||
|
||||
#### **Refactored Hook Runner** (`manage-modules.sh`)
|
||||
- External script execution with environment variables
|
||||
- Proper error handling (exit codes 0/1/2)
|
||||
- Environment cleanup
|
||||
- Removed legacy fallback code
|
||||
|
||||
### 3. **Hook Mapping Applied**
|
||||
- **24 Eluna modules** → `copy-standard-lua`
|
||||
- **2 AIO modules** → `copy-aio-lua`
|
||||
- **1 mod-ale module** → `mod-ale-patches`
|
||||
- **1 Black Market module** → `black-market-setup`
|
||||
|
||||
### 4. **Benefits Achieved**
|
||||
- ✅ **Maintainable** - Hooks are separate, reusable scripts
|
||||
- ✅ **Extensible** - Easy to add new hooks without code changes
|
||||
- ✅ **Reliable** - No more undefined hook warnings
|
||||
- ✅ **Documented** - Clear interface and usage patterns
|
||||
- ✅ **Clean** - Removed legacy code and hardcoded cases
|
||||
|
||||
## Files Modified
|
||||
- `scripts/hooks/` (new directory with 5 files)
|
||||
- `scripts/manage-modules.sh` (refactored hook runner)
|
||||
- `config/modules.json` (updated all 28 hook definitions)
|
||||
|
||||
## Testing Ready
|
||||
The system is ready for testing with the modules container to ensure all Lua scripts are properly copied to `/azerothcore/lua_scripts` during module installation.
|
||||
101
scripts/lib/compose_overrides.sh
Normal file
101
scripts/lib/compose_overrides.sh
Normal file
@@ -0,0 +1,101 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Helper utilities for dynamically including docker compose override files
|
||||
# based on FEATURE_NAME_ENABLED style environment flags.
|
||||
|
||||
compose_overrides::trim() {
|
||||
local value="$1"
|
||||
# shellcheck disable=SC2001
|
||||
value="$(echo "$value" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
|
||||
printf '%s' "$value"
|
||||
}
|
||||
|
||||
compose_overrides::derive_flag_from_name() {
|
||||
local file="$1"
|
||||
local base
|
||||
base="$(basename "$file")"
|
||||
base="${base%.*}"
|
||||
base="${base//[^[:alnum:]]/_}"
|
||||
base="${base^^}"
|
||||
printf 'COMPOSE_OVERRIDE_%s_ENABLED' "$base"
|
||||
}
|
||||
|
||||
compose_overrides::extract_tag() {
|
||||
local file="$1" tag="$2"
|
||||
local line
|
||||
line="$(grep -m1 "^# *${tag}:" "$file" 2>/dev/null || true)"
|
||||
if [ -z "$line" ]; then
|
||||
return 1
|
||||
fi
|
||||
line="${line#*:}"
|
||||
compose_overrides::trim "$line"
|
||||
}
|
||||
|
||||
compose_overrides::extract_all_tags() {
|
||||
local file="$1" tag="$2"
|
||||
grep "^# *${tag}:" "$file" 2>/dev/null | cut -d':' -f2- | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'
|
||||
}
|
||||
|
||||
compose_overrides::read_env_value() {
|
||||
local env_path="$1" key="$2" default="${3:-}"
|
||||
local value=""
|
||||
if [ -f "$env_path" ]; then
|
||||
value="$(grep -E "^${key}=" "$env_path" | tail -n1 | cut -d'=' -f2- | tr -d '\r')"
|
||||
fi
|
||||
if [ -z "$value" ]; then
|
||||
value="$default"
|
||||
fi
|
||||
printf '%s' "$value"
|
||||
}
|
||||
|
||||
compose_overrides::list_enabled_files() {
|
||||
local root_dir="$1" env_path="$2" result_var="$3"
|
||||
local overrides_dir="${root_dir}/compose-overrides"
|
||||
local -n __result="$result_var"
|
||||
__result=()
|
||||
|
||||
[ -d "$overrides_dir" ] || return 0
|
||||
|
||||
local -a override_files=()
|
||||
while IFS= read -r -d '' file; do
|
||||
override_files+=("$file")
|
||||
done < <(find "$overrides_dir" -maxdepth 1 -type f \( -name '*.yml' -o -name '*.yaml' \) -print0 | sort -z)
|
||||
|
||||
local file flag flag_value legacy_default legacy_flags legacy_flag
|
||||
for file in "${override_files[@]}"; do
|
||||
flag="$(compose_overrides::extract_tag "$file" "override-flag" || true)"
|
||||
if [ -z "$flag" ]; then
|
||||
flag="$(compose_overrides::derive_flag_from_name "$file")"
|
||||
fi
|
||||
|
||||
legacy_default="0"
|
||||
legacy_flags="$(compose_overrides::extract_all_tags "$file" "legacy-flag" || true)"
|
||||
if [ -n "$legacy_flags" ]; then
|
||||
while IFS= read -r legacy_flag; do
|
||||
[ -z "$legacy_flag" ] && continue
|
||||
legacy_default="$(compose_overrides::read_env_value "$env_path" "$legacy_flag" "$legacy_default")"
|
||||
# Stop at first legacy flag that yields a value
|
||||
if [ -n "$legacy_default" ]; then
|
||||
break
|
||||
fi
|
||||
done <<< "$legacy_flags"
|
||||
fi
|
||||
|
||||
flag_value="$(compose_overrides::read_env_value "$env_path" "$flag" "$legacy_default")"
|
||||
if [ "$flag_value" = "1" ]; then
|
||||
__result+=("$file")
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
compose_overrides::build_compose_args() {
|
||||
local root_dir="$1" env_path="$2" default_compose="$3" result_var="$4"
|
||||
local -n __result="$result_var"
|
||||
__result=(-f "$default_compose")
|
||||
|
||||
local -a enabled_files=()
|
||||
compose_overrides::list_enabled_files "$root_dir" "$env_path" enabled_files
|
||||
for file in "${enabled_files[@]}"; do
|
||||
__result+=(-f "$file")
|
||||
done
|
||||
}
|
||||
@@ -130,7 +130,7 @@ ensure_module_metadata(){
|
||||
fi
|
||||
done
|
||||
|
||||
local manifest_path="${MANIFEST_PATH:-${MODULES_MANIFEST_PATH:-/tmp/config/modules.json}}"
|
||||
local manifest_path="${MANIFEST_PATH:-${MODULES_MANIFEST_PATH:-/tmp/config/module-manifest.json}}"
|
||||
local env_path="${ENV_PATH:-${MODULES_ENV_PATH:-/tmp/.env}}"
|
||||
local state_env_candidate="${STATE_DIR:-${MODULES_ROOT:-/modules}}/modules.env"
|
||||
if [ -f "$state_env_candidate" ]; then
|
||||
|
||||
@@ -55,22 +55,22 @@ resolve_manifest_path(){
|
||||
return
|
||||
fi
|
||||
local candidate
|
||||
candidate="$PROJECT_ROOT/config/modules.json"
|
||||
candidate="$PROJECT_ROOT/config/module-manifest.json"
|
||||
if [ -f "$candidate" ]; then
|
||||
echo "$candidate"
|
||||
return
|
||||
fi
|
||||
candidate="$SCRIPT_DIR/../config/modules.json"
|
||||
candidate="$SCRIPT_DIR/../config/module-manifest.json"
|
||||
if [ -f "$candidate" ]; then
|
||||
echo "$candidate"
|
||||
return
|
||||
fi
|
||||
candidate="/tmp/config/modules.json"
|
||||
candidate="/tmp/config/module-manifest.json"
|
||||
if [ -f "$candidate" ]; then
|
||||
echo "$candidate"
|
||||
return
|
||||
fi
|
||||
err "Unable to locate module manifest (set MODULES_MANIFEST_PATH or ensure config/modules.json exists)"
|
||||
err "Unable to locate module manifest (set MODULES_MANIFEST_PATH or ensure config/module-manifest.json exists)"
|
||||
}
|
||||
|
||||
setup_git_config(){
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"""
|
||||
Module manifest helper.
|
||||
|
||||
Reads config/modules.json and .env to produce canonical module state that
|
||||
Reads config/module-manifest.json and .env to produce canonical module state that
|
||||
downstream shell scripts can consume for staging, rebuild detection, and
|
||||
dependency validation.
|
||||
"""
|
||||
@@ -466,8 +466,8 @@ def configure_parser() -> argparse.ArgumentParser:
|
||||
)
|
||||
parser.add_argument(
|
||||
"--manifest",
|
||||
default="config/modules.json",
|
||||
help="Path to module manifest (default: config/modules.json)",
|
||||
default="config/module-manifest.json",
|
||||
help="Path to module manifest (default: config/module-manifest.json)",
|
||||
)
|
||||
|
||||
subparsers = parser.add_subparsers(dest="command", required=True)
|
||||
|
||||
@@ -179,7 +179,7 @@ ensure_module_state(){
|
||||
local storage_root
|
||||
storage_root="$(resolve_local_storage_path)"
|
||||
MODULE_STATE_DIR="${storage_root}/modules"
|
||||
if ! python3 "$MODULE_HELPER" --env-path "$ENV_FILE" --manifest "$PROJECT_DIR/config/modules.json" generate --output-dir "$MODULE_STATE_DIR"; then
|
||||
if ! python3 "$MODULE_HELPER" --env-path "$ENV_FILE" --manifest "$PROJECT_DIR/config/module-manifest.json" generate --output-dir "$MODULE_STATE_DIR"; then
|
||||
echo "❌ Module manifest validation failed. See details above."
|
||||
exit 1
|
||||
fi
|
||||
@@ -463,7 +463,7 @@ remove_sentinel(){
|
||||
fi
|
||||
if command -v docker >/dev/null 2>&1; then
|
||||
local db_image
|
||||
db_image="$(read_env AC_DB_IMPORT_IMAGE "acore/ac-wotlk-db-import:14.0.0-dev")"
|
||||
db_image="$(read_env AC_DB_IMPORT_IMAGE "acore/ac-wotlk-db-import:master")"
|
||||
if docker image inspect "$db_image" >/dev/null 2>&1; then
|
||||
local mount_dir
|
||||
mount_dir="$(dirname "$sentinel_path")"
|
||||
|
||||
@@ -65,7 +65,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
ENV_FILE="$PROJECT_DIR/.env"
|
||||
DEFAULT_COMPOSE_FILE="$PROJECT_DIR/docker-compose.yml"
|
||||
EXTRA_COMPOSE_FILE="$PROJECT_DIR/docker-compose.mysql-expose.yml"
|
||||
source "$PROJECT_DIR/scripts/lib/compose_overrides.sh"
|
||||
|
||||
usage(){
|
||||
cat <<EOF
|
||||
@@ -116,12 +116,10 @@ resolve_project_name(){
|
||||
|
||||
if [ -z "${COMPOSE_FILE:-}" ]; then
|
||||
compose_files=("$DEFAULT_COMPOSE_FILE")
|
||||
if [ "$(read_env MYSQL_EXPOSE_PORT "0")" = "1" ]; then
|
||||
if [ -f "$EXTRA_COMPOSE_FILE" ]; then
|
||||
compose_files+=("$EXTRA_COMPOSE_FILE")
|
||||
else
|
||||
echo "⚠️ MYSQL_EXPOSE_PORT=1 but ${EXTRA_COMPOSE_FILE} not found; continuing without port exposure override."
|
||||
fi
|
||||
declare -a enabled_overrides=()
|
||||
compose_overrides::list_enabled_files "$PROJECT_DIR" "$ENV_FILE" enabled_overrides
|
||||
if [ "${#enabled_overrides[@]}" -gt 0 ]; then
|
||||
compose_files+=("${enabled_overrides[@]}")
|
||||
fi
|
||||
COMPOSE_FILE="$(IFS=:; echo "${compose_files[*]}")"
|
||||
export COMPOSE_FILE
|
||||
|
||||
@@ -15,7 +15,7 @@ from pathlib import Path
|
||||
root = Path(sys.argv[1])
|
||||
modules_py = root / "scripts" / "modules.py"
|
||||
env_path = root / ".env"
|
||||
manifest_path = root / "config" / "modules.json"
|
||||
manifest_path = root / "config" / "module-manifest.json"
|
||||
|
||||
state = json.loads(subprocess.check_output([
|
||||
sys.executable,
|
||||
|
||||
@@ -13,6 +13,7 @@ err(){ echo -e "${RED}❌ $*${NC}"; }
|
||||
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
COMPOSE_FILE="$PROJECT_DIR/docker-compose.yml"
|
||||
ENV_FILE=""
|
||||
source "$PROJECT_DIR/scripts/lib/compose_overrides.sh"
|
||||
PROFILES=(db services-standard client-data modules tools)
|
||||
SKIP_DEPLOY=false
|
||||
QUICK=false
|
||||
@@ -73,15 +74,13 @@ run_compose(){
|
||||
compose_args+=(--env-file "$ENV_FILE")
|
||||
fi
|
||||
compose_args+=(-f "$COMPOSE_FILE")
|
||||
if [ "$(read_env_value MYSQL_EXPOSE_PORT "0")" = "1" ]; then
|
||||
local extra_file
|
||||
extra_file="$(dirname "$COMPOSE_FILE")/docker-compose.mysql-expose.yml"
|
||||
if [ -f "$extra_file" ]; then
|
||||
compose_args+=(-f "$extra_file")
|
||||
else
|
||||
warn "MYSQL_EXPOSE_PORT=1 but ${extra_file} missing; skipping port exposure override."
|
||||
fi
|
||||
fi
|
||||
local env_path
|
||||
env_path="$(env_file_path)"
|
||||
declare -a enabled_overrides=()
|
||||
compose_overrides::list_enabled_files "$PROJECT_DIR" "$env_path" enabled_overrides
|
||||
for file in "${enabled_overrides[@]}"; do
|
||||
compose_args+=(-f "$file")
|
||||
done
|
||||
docker compose "${compose_args[@]}" "$@"
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user