29a12bb102
- Add expand_container_path() helper that resolves ~/ and $HOME/ prefixes
- Add get_manifest_home_dir() to compute /home/{user.name} or /root from manifest
- Set ENV HOME=... and ENV USER=... in generated Dockerfile for runtime compatibility
- Pass home_dir through instance creation and startup pipeline
- Expand mount targets in apply_resolved_profile() for regular profile mounts
- Expand mapping targets in _resolve_git_mount_mappings() for git mounts
- Expand working_directory and volume targets in _modify_compose_file()
- Update _prepare_manifest_instance to return home_dir alongside image tag
- Fetch tool_type early in start_instance to determine home_dir before profile application
Quality gates: pytest 188 passed, frontend typecheck clean
Addresses: home-path-expansion
103 lines
2.9 KiB
Markdown
103 lines
2.9 KiB
Markdown
# Design: ~ / $HOME Expansion in Mount Paths
|
|
|
|
## Architecture
|
|
|
|
### New Helpers
|
|
|
|
#### `expand_container_path(path: str, home_dir: str) -> str`
|
|
Located in `config_profile_resolver.py` (or new shared module).
|
|
|
|
```python
|
|
def expand_container_path(path: str, home_dir: str) -> str:
|
|
if path.startswith("~/"):
|
|
return os.path.join(home_dir, path[2:])
|
|
if path == "~":
|
|
return home_dir
|
|
path = path.replace("$HOME/", home_dir + "/")
|
|
path = path.replace("$HOME", home_dir)
|
|
return path
|
|
```
|
|
|
|
#### `get_manifest_home_dir(manifest: dict) -> str`
|
|
Located in `manifest_compiler.py`.
|
|
|
|
```python
|
|
def get_manifest_home_dir(manifest: dict) -> str:
|
|
user = manifest.get("user")
|
|
if user and user.get("name"):
|
|
return f"/home/{user['name']}"
|
|
return "/root"
|
|
```
|
|
|
|
#### `get_tool_home_dir(tool_type: ToolType, manifest: dict | None) -> str`
|
|
Located in `tool_instances.py` or `manifest_compiler.py`.
|
|
|
|
```python
|
|
def get_tool_home_dir(tool_type: ToolType, manifest: dict | None = None) -> str:
|
|
if tool_type.definition_type == "manifest" and manifest:
|
|
return get_manifest_home_dir(manifest)
|
|
return "/root"
|
|
```
|
|
|
|
### Pipeline Changes
|
|
|
|
#### `create_instance` flow
|
|
|
|
1. Determine `home_dir` from tool type + manifest (if manifest-based)
|
|
2. Pass `home_dir` to `_modify_compose_file()` — expand mount targets in compose
|
|
|
|
#### `start_instance` flow
|
|
|
|
1. Determine `home_dir` from tool type + resolved manifest
|
|
2. Pass `home_dir` to `apply_resolved_profile()` — expand profile mount targets
|
|
3. Pass `home_dir` to `_resolve_git_mounts()` — expand git mount mapping targets
|
|
|
|
#### `apply_resolved_profile()`
|
|
|
|
```python
|
|
def apply_resolved_profile(
|
|
instance_dir: str,
|
|
resolved: ResolvedProfile,
|
|
home_dir: str = "/root",
|
|
) -> tuple[...]:
|
|
...
|
|
for mount in resolved.mounts.values():
|
|
target = expand_container_path(mount.target, home_dir)
|
|
...
|
|
```
|
|
|
|
#### `_resolve_git_mount_mappings()`
|
|
|
|
```python
|
|
def _resolve_git_mount_mappings(
|
|
repo_path: str,
|
|
mappings: list[dict],
|
|
working_directory: str | None,
|
|
home_dir: str = "/root",
|
|
) -> list[dict]:
|
|
...
|
|
final_target = expand_container_path(target_path, home_dir)
|
|
...
|
|
```
|
|
|
|
### Dockerfile Change
|
|
|
|
In `compile_dockerfile()`, after user creation, set `HOME`:
|
|
|
|
```python
|
|
if user:
|
|
home = f"/home/{user['name']}"
|
|
lines.append(f"ENV HOME={home}")
|
|
lines.append(f"ENV USER={user['name']}")
|
|
```
|
|
|
|
### File Changes
|
|
|
|
| File | Change |
|
|
|------|--------|
|
|
| `apps/api/src/services/config_profile_resolver.py` | Add `expand_container_path()`, apply in `apply_resolved_profile()` |
|
|
| `apps/api/src/services/manifest_compiler.py` | Add `get_manifest_home_dir()`, set `HOME`/`USER` env in Dockerfile |
|
|
| `apps/api/src/api/tool_instances.py` | Determine `home_dir`, pass through all mount resolution functions |
|
|
| `apps/api/tests/unit/test_home_path_expansion.py` | New unit tests |
|
|
| `apps/api/tests/unit/test_manifest_compiler.py` | Add tests for `get_manifest_home_dir` and Dockerfile `HOME` env |
|