fix: handle existing git mount dirs and invalid compose ports

- Fix git mount clone to check correct path (repo-clone subdir)
- Pull updates instead of re-cloning when git mount dir exists
- Add compose file sanitization to remove invalid port 0 mappings
- Fixes startup failures for existing instances with old compose files
This commit is contained in:
Alex Blank
2026-05-27 22:34:24 +02:00
parent d9d2b91384
commit c63cf7db50
+50 -4
View File
@@ -130,17 +130,19 @@ async def _resolve_single_git_mount(
import hashlib
url_hash = hashlib.md5(remote_url.encode()).hexdigest()[:12]
repo_name = remote_url.split("/")[-1].replace(".git", "") or "repo"
clone_dir = os.path.join(instance_dir, "git-mounts", f"{repo_name}-{url_hash}")
clone_parent = os.path.join(instance_dir, "git-mounts", f"{repo_name}-{url_hash}")
# clone_repository always creates 'repo-clone' inside the given directory
repo_path = os.path.join(clone_parent, "repo-clone")
# Clone or pull the repository
repo_path = clone_dir
if not os.path.exists(clone_dir):
if not os.path.exists(repo_path):
try:
os.makedirs(clone_parent, exist_ok=True)
repo_path = await asyncio.to_thread(
clone_repository,
remote_url,
None, # No SSH key for now - can be added later
os.path.dirname(clone_dir),
clone_parent,
branch or "main",
)
logger.debug("Cloned git mount repository %s to %s", remote_url, repo_path)
@@ -384,6 +386,47 @@ async def _validate_config_profile(
return profile_uuid
def _sanitize_compose_file(compose_path: str) -> None:
"""Remove invalid port mappings (target port 0) from compose file."""
import yaml
from pathlib import Path
compose_file = Path(compose_path)
if not compose_file.exists():
return
content = compose_file.read_text()
compose_data = yaml.safe_load(content)
if not compose_data or "services" not in compose_data:
return
modified = False
for service_name, service_config in compose_data["services"].items():
if "ports" in service_config:
valid_ports = []
for port_mapping in service_config["ports"]:
if isinstance(port_mapping, str) and ":" in port_mapping:
parts = port_mapping.split(":")
if len(parts) == 2:
host_port, container_port = parts
# Skip invalid mappings (target port 0 or empty)
if container_port == "0" or not container_port:
modified = True
continue
valid_ports.append(port_mapping)
if valid_ports:
service_config["ports"] = valid_ports
else:
del service_config["ports"]
modified = True
break # Only check first service
if modified:
compose_file.write_text(yaml.dump(compose_data, default_flow_style=False))
def _modify_compose_file(
compose_path: str,
port_override: int | None = None,
@@ -996,6 +1039,9 @@ async def start_instance(
_modify_compose_file(instance.compose_path, port_override, start_command, working_directory, extra_volumes)
logger.debug("Modified compose file for instance %s", instance.id)
# Sanitize compose file to remove invalid port mappings from old instances
_sanitize_compose_file(instance.compose_path)
# Execute docker compose up with env file
logger.debug("Running docker compose up for instance %s (compose_path=%s)", instance.id, instance.compose_path)
returncode, stdout, stderr = execute_compose_command(