Skip to content

Commit 802cfbf

Browse files
committed
fix(resolver): dedupe override.yml; apply gpu_backends filter to user-extensions
Two resolver-layer defects fixed together because they cluster in the same call chain. 1. installers/lib/compose-select.sh double-appended docker-compose.override.yml to COMPOSE_FLAGS. scripts/resolve- compose-stack.sh already appends it once when its env output is consumed by compose-select.sh's load_env_from_output. Removing the redundant bash-level append leaves the resolver as the single source of truth. 2. scripts/resolve-compose-stack.sh included every data/user-extensions/<id>/compose.yaml unconditionally, bypassing the gpu_backends compatibility check that the built-in extension loop already performs. An NVIDIA-only user extension installed on AMD/Apple would be merged into the stack and fail at container start. This adds the same manifest read + schema_version + gpu_backends filter the built-in loop uses, verbatim, including "all"/"none" sentinels and the narrow-dispatch error handling gated by skip_broken.
1 parent d5154c3 commit 802cfbf

2 files changed

Lines changed: 46 additions & 7 deletions

File tree

dream-server/installers/lib/compose-select.sh

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,5 @@ resolve_compose_config() {
102102
log "Including docker-compose.tier0.yml (Tier 0 memory limits)"
103103
fi
104104

105-
# Auto-include docker-compose.override.yml if present (standard Docker convention).
106-
# This lets modders add services without editing core compose files.
107-
if [[ -f "$SCRIPT_DIR/docker-compose.override.yml" ]]; then
108-
COMPOSE_FLAGS="$COMPOSE_FLAGS -f docker-compose.override.yml"
109-
log "Including docker-compose.override.yml (user overrides)"
110-
fi
111-
112105
log "Compose selection: $COMPOSE_FLAGS"
113106
}

dream-server/scripts/resolve-compose-stack.sh

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,56 @@ if ext_dir.exists():
223223
# Discover enabled user-installed extensions (from dashboard portal)
224224
user_ext_dir = script_dir / "data" / "user-extensions"
225225
if user_ext_dir.exists():
226+
try:
227+
import yaml
228+
yaml_available = True
229+
except ImportError:
230+
yaml_available = False
231+
226232
try:
227233
for service_dir in sorted(user_ext_dir.iterdir()):
228234
if not service_dir.is_dir():
229235
continue
236+
# Find manifest
237+
manifest_path = None
238+
for name in ("manifest.yaml", "manifest.yml", "manifest.json"):
239+
candidate = service_dir / name
240+
if candidate.exists():
241+
manifest_path = candidate
242+
break
243+
if not manifest_path:
244+
continue
245+
try:
246+
with open(manifest_path) as f:
247+
if manifest_path.suffix == ".json":
248+
manifest = json.load(f)
249+
elif yaml_available:
250+
manifest = yaml.safe_load(f)
251+
else:
252+
continue # skip YAML manifests when PyYAML unavailable
253+
if manifest.get("schema_version") != "dream.services.v1":
254+
continue
255+
service = manifest.get("service", {})
256+
# same gpu_backends filter as built-in loop
257+
backends = service.get("gpu_backends", ["amd", "nvidia"])
258+
if gpu_backend not in backends and "all" not in backends and "none" not in backends:
259+
continue
260+
except Exception as e:
261+
yaml_error = yaml_available and hasattr(yaml, 'YAMLError') and isinstance(e, yaml.YAMLError)
262+
json_error = isinstance(e, json.JSONDecodeError)
263+
structure_error = isinstance(e, (KeyError, TypeError))
264+
265+
if yaml_error or json_error or structure_error:
266+
print(f"ERROR: Failed to parse manifest for {service_dir.name}: {e}", file=sys.stderr)
267+
print(f" Manifest path: {manifest_path}", file=sys.stderr)
268+
print(f" This service will be skipped. Fix the manifest or disable the service.", file=sys.stderr)
269+
if skip_broken:
270+
continue
271+
else:
272+
sys.exit(1)
273+
else:
274+
raise
275+
230276
compose_path = service_dir / "compose.yaml"
231277
if compose_path.exists():
232278
resolved.append(str(compose_path.relative_to(script_dir)))

0 commit comments

Comments
 (0)