refactor: separate standalone and managed room configs
- veins → shunts rename - add cfg/standalone/ and cfg/<room>/ structure - remove old data/*.json (moved to cfg/<room>/data/) - update build.py and ctrl scripts
This commit is contained in:
172
build.py
172
build.py
@@ -8,18 +8,23 @@ Both dev and deploy modes copy files (no symlinks) for Docker compatibility.
|
||||
After editing source files, re-run `python build.py dev` to update gen/.
|
||||
|
||||
Usage:
|
||||
python build.py dev # Build gen/ from source
|
||||
python build.py dev --cfg amar # Include amar room config
|
||||
python build.py dev # Build gen/standalone/
|
||||
python build.py dev --cfg amar # Build gen/amar/
|
||||
python build.py dev --all # Build all (standalone + rooms)
|
||||
python build.py deploy --output /path/ # Build for production
|
||||
python build.py models # Only regenerate models
|
||||
|
||||
Examples:
|
||||
# Set up dev environment
|
||||
# Set up dev environment (standalone)
|
||||
python build.py dev
|
||||
cd gen && .venv/bin/python run.py
|
||||
cd gen/standalone && .venv/bin/python run.py
|
||||
|
||||
# With room config
|
||||
python build.py dev --cfg amar
|
||||
cd gen/amar && .venv/bin/python run.py
|
||||
|
||||
# Build all targets
|
||||
python build.py dev --all
|
||||
|
||||
# Build for deployment
|
||||
python build.py deploy --output ../deploy/soleprint/
|
||||
@@ -72,13 +77,15 @@ def count_files(path: Path) -> int:
|
||||
return sum(1 for _ in path.rglob("*") if _.is_file())
|
||||
|
||||
|
||||
def generate_models(output_dir: Path):
|
||||
def generate_models(output_dir: Path, cfg_name: str | None = None):
|
||||
"""Generate models using modelgen tool.
|
||||
|
||||
Args:
|
||||
output_dir: Directory where models/pydantic/__init__.py will be created
|
||||
cfg_name: Room config name (e.g., 'amar'), or None for standalone
|
||||
"""
|
||||
config_path = SPR_ROOT / "cfg" / "soleprint.config.json"
|
||||
room = cfg_name or "standalone"
|
||||
config_path = SPR_ROOT / "cfg" / room / "config.json"
|
||||
|
||||
if not config_path.exists():
|
||||
log.warning(f"Config not found at {config_path}")
|
||||
@@ -111,62 +118,64 @@ def copy_cfg(output_dir: Path, cfg_name: str | None):
|
||||
|
||||
Args:
|
||||
output_dir: Target directory
|
||||
cfg_name: Name of room config (e.g., 'amar'), or None for base only
|
||||
cfg_name: Name of room config (e.g., 'amar'), or None for standalone
|
||||
"""
|
||||
room = cfg_name or "standalone"
|
||||
room_cfg = SPR_ROOT / "cfg" / room
|
||||
|
||||
if not room_cfg.exists():
|
||||
log.warning(f"Room config '{room}' not found at {room_cfg}")
|
||||
return
|
||||
|
||||
log.info(f"\nCopying {room} room config...")
|
||||
|
||||
# Copy config.json to cfg/
|
||||
cfg_dir = output_dir / "cfg"
|
||||
ensure_dir(cfg_dir)
|
||||
room_config = room_cfg / "config.json"
|
||||
if room_config.exists():
|
||||
copy_path(room_config, cfg_dir / "config.json")
|
||||
|
||||
# Always copy base config
|
||||
base_config = SPR_ROOT / "cfg" / "soleprint.config.json"
|
||||
if base_config.exists():
|
||||
copy_path(base_config, cfg_dir / "soleprint.config.json")
|
||||
# Copy data/ to output data/
|
||||
room_data = room_cfg / "data"
|
||||
if room_data.exists():
|
||||
log.info(f" Copying {room} data files...")
|
||||
copy_path(room_data, output_dir / "data")
|
||||
|
||||
# Copy room-specific config if specified
|
||||
if cfg_name:
|
||||
room_cfg = SPR_ROOT / "cfg" / cfg_name
|
||||
if room_cfg.exists() and room_cfg.is_dir():
|
||||
log.info(f"\nCopying {cfg_name} room config...")
|
||||
for item in room_cfg.iterdir():
|
||||
if item.name == ".env.example":
|
||||
# Copy .env.example to output root as template
|
||||
copy_path(item, output_dir / ".env.example")
|
||||
elif item.is_dir():
|
||||
copy_path(item, cfg_dir / cfg_name / item.name)
|
||||
else:
|
||||
ensure_dir(cfg_dir / cfg_name)
|
||||
copy_path(item, cfg_dir / cfg_name / item.name)
|
||||
# Copy .env.example to output root
|
||||
env_example = room_cfg / ".env.example"
|
||||
if env_example.exists():
|
||||
copy_path(env_example, output_dir / ".env.example")
|
||||
|
||||
# Copy room-specific databrowse depot if exists
|
||||
room_databrowse = room_cfg / "databrowse" / "depot"
|
||||
if room_databrowse.exists():
|
||||
log.info(f" Copying {cfg_name} databrowse depot...")
|
||||
target = output_dir / "station" / "monitors" / "databrowse" / "depot"
|
||||
copy_path(room_databrowse, target)
|
||||
# Copy room-specific databrowse depot if exists
|
||||
room_databrowse = room_cfg / "databrowse" / "depot"
|
||||
if room_databrowse.exists():
|
||||
log.info(f" Copying {room} databrowse depot...")
|
||||
target = output_dir / "station" / "monitors" / "databrowse" / "depot"
|
||||
copy_path(room_databrowse, target)
|
||||
|
||||
# Copy room-specific tester tests if exists
|
||||
room_tests = room_cfg / "tester" / "tests"
|
||||
if room_tests.exists():
|
||||
log.info(f" Copying {cfg_name} tester tests...")
|
||||
target = output_dir / "station" / "tools" / "tester" / "tests"
|
||||
copy_path(room_tests, target)
|
||||
# Copy room-specific tester tests if exists
|
||||
room_tests = room_cfg / "tester" / "tests"
|
||||
if room_tests.exists():
|
||||
log.info(f" Copying {room} tester tests...")
|
||||
target = output_dir / "station" / "tools" / "tester" / "tests"
|
||||
copy_path(room_tests, target)
|
||||
|
||||
# Copy room-specific monitors if exists
|
||||
room_monitors = room_cfg / "monitors"
|
||||
if room_monitors.exists():
|
||||
log.info(f" Copying {cfg_name} monitors...")
|
||||
for monitor in room_monitors.iterdir():
|
||||
if monitor.is_dir():
|
||||
target = output_dir / "station" / "monitors" / monitor.name
|
||||
copy_path(monitor, target)
|
||||
# Copy room-specific monitors if exists
|
||||
room_monitors = room_cfg / "monitors"
|
||||
if room_monitors.exists():
|
||||
log.info(f" Copying {room} monitors...")
|
||||
for monitor in room_monitors.iterdir():
|
||||
if monitor.is_dir():
|
||||
target = output_dir / "station" / "monitors" / monitor.name
|
||||
copy_path(monitor, target)
|
||||
|
||||
# Copy room-specific models if exists
|
||||
room_models = room_cfg / "models"
|
||||
if room_models.exists():
|
||||
log.info(f" Copying {cfg_name} models...")
|
||||
target = output_dir / "models" / cfg_name
|
||||
copy_path(room_models, target)
|
||||
else:
|
||||
log.warning(f"Room config '{cfg_name}' not found at {room_cfg}")
|
||||
# Copy room-specific models if exists
|
||||
room_models = room_cfg / "models"
|
||||
if room_models.exists():
|
||||
log.info(f" Copying {room} models...")
|
||||
target = output_dir / "models" / room
|
||||
copy_path(room_models, target)
|
||||
|
||||
|
||||
def build_dev(output_dir: Path, cfg_name: str | None = None):
|
||||
@@ -174,7 +183,7 @@ def build_dev(output_dir: Path, cfg_name: str | None = None):
|
||||
Build for development using copies (Docker-compatible).
|
||||
|
||||
Structure:
|
||||
gen/
|
||||
gen/standalone/ or gen/<room>/
|
||||
├── main.py
|
||||
├── run.py
|
||||
├── index.html
|
||||
@@ -189,7 +198,7 @@ def build_dev(output_dir: Path, cfg_name: str | None = None):
|
||||
├── .env.example # From cfg/<room>/.env.example
|
||||
└── models/ # Generated
|
||||
|
||||
After editing source files, re-run `python build.py dev` to update gen/.
|
||||
After editing source files, re-run `python build.py dev` to update.
|
||||
"""
|
||||
log.info("\n=== Building DEV environment ===")
|
||||
log.info(f"SPR root: {SPR_ROOT}")
|
||||
@@ -217,17 +226,13 @@ def build_dev(output_dir: Path, cfg_name: str | None = None):
|
||||
if source.exists():
|
||||
copy_path(source, output_dir / system)
|
||||
|
||||
# Data directory
|
||||
log.info("\nCopying data...")
|
||||
copy_path(SPR_ROOT / "data", output_dir / "data")
|
||||
|
||||
# Config
|
||||
# Config (includes data/ from room)
|
||||
log.info("\nCopying config...")
|
||||
copy_cfg(output_dir, cfg_name)
|
||||
|
||||
# Models (generated)
|
||||
log.info("\nGenerating models...")
|
||||
if not generate_models(output_dir):
|
||||
if not generate_models(output_dir, cfg_name):
|
||||
log.warning("Model generation failed, you may need to run it manually")
|
||||
|
||||
log.info("\n✓ Dev build complete!")
|
||||
@@ -236,7 +241,12 @@ def build_dev(output_dir: Path, cfg_name: str | None = None):
|
||||
log.info(f" python3 -m venv .venv")
|
||||
log.info(f" .venv/bin/pip install -r requirements.txt")
|
||||
log.info(f" .venv/bin/python run.py # Single-port bare-metal dev")
|
||||
log.info(f"\nAfter editing source, rebuild with: python build.py dev")
|
||||
if cfg_name:
|
||||
log.info(
|
||||
f"\nAfter editing source, rebuild with: python build.py dev --cfg {cfg_name}"
|
||||
)
|
||||
else:
|
||||
log.info(f"\nAfter editing source, rebuild with: python build.py dev")
|
||||
|
||||
|
||||
def build_deploy(output_dir: Path, cfg_name: str | None = None):
|
||||
@@ -276,19 +286,16 @@ def build_deploy(output_dir: Path, cfg_name: str | None = None):
|
||||
if source.exists():
|
||||
copy_path(source, output_dir / system)
|
||||
|
||||
# Data directory (copy)
|
||||
log.info("\nCopying data...")
|
||||
copy_path(SPR_ROOT / "data", output_dir / "data")
|
||||
|
||||
# Config (copy)
|
||||
# Config (includes data/ from room)
|
||||
log.info("\nCopying config...")
|
||||
copy_cfg(output_dir, cfg_name)
|
||||
|
||||
# Models (generate fresh) - pass output_dir, modelgen adds models/pydantic
|
||||
log.info("\nGenerating models...")
|
||||
if not generate_models(output_dir):
|
||||
if not generate_models(output_dir, cfg_name):
|
||||
# Fallback: copy from gen if exists
|
||||
existing = SPR_ROOT / "gen" / "models"
|
||||
room = cfg_name or "standalone"
|
||||
existing = SPR_ROOT / "gen" / room / "models"
|
||||
if existing.exists():
|
||||
log.info(" Using existing models from gen/")
|
||||
copy_path(existing, output_dir / "models")
|
||||
@@ -354,8 +361,8 @@ def main():
|
||||
"--output",
|
||||
"-o",
|
||||
type=Path,
|
||||
default=SPR_ROOT / "gen",
|
||||
help="Output directory (default: gen/)",
|
||||
default=None,
|
||||
help="Output directory (default: gen/standalone/ or gen/<cfg>/)",
|
||||
)
|
||||
dev_parser.add_argument(
|
||||
"--cfg",
|
||||
@@ -364,6 +371,11 @@ def main():
|
||||
default=None,
|
||||
help="Room config to include (e.g., 'amar')",
|
||||
)
|
||||
dev_parser.add_argument(
|
||||
"--all",
|
||||
action="store_true",
|
||||
help="Build all configs (standalone + all rooms in cfg/)",
|
||||
)
|
||||
|
||||
# deploy command
|
||||
deploy_parser = subparsers.add_parser(
|
||||
@@ -390,7 +402,23 @@ def main():
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.command == "dev":
|
||||
build_dev(args.output.resolve(), args.cfg)
|
||||
if getattr(args, "all", False):
|
||||
# Build standalone
|
||||
build_dev(SPR_ROOT / "gen" / "standalone", None)
|
||||
# Build all room configs
|
||||
cfg_dir = SPR_ROOT / "cfg"
|
||||
for room in cfg_dir.iterdir():
|
||||
if room.is_dir() and room.name not in ("__pycache__",):
|
||||
build_dev(SPR_ROOT / "gen" / room.name, room.name)
|
||||
else:
|
||||
# Determine output directory
|
||||
if args.output:
|
||||
output_dir = args.output.resolve()
|
||||
elif args.cfg:
|
||||
output_dir = SPR_ROOT / "gen" / args.cfg
|
||||
else:
|
||||
output_dir = SPR_ROOT / "gen" / "standalone"
|
||||
build_dev(output_dir, args.cfg)
|
||||
elif args.command == "deploy":
|
||||
build_deploy(args.output.resolve(), args.cfg)
|
||||
elif args.command == "models":
|
||||
|
||||
Reference in New Issue
Block a user