Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## Unreleased

***Changed:***

- Only support the latest version of the developer environment image for the `linux-container` developer environment type

***Fixed:***

- Fix the allowed range of exposed developer environment ports
Expand Down
47 changes: 20 additions & 27 deletions src/dda/env/dev/types/linux_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ class LinuxContainerConfig(DeveloperEnvironmentConfig):
Additional host directories to be mounted into the dev env. This option may be supplied multiple
times, and has the same syntax as the `-v/--volume` flag of `docker run`. Examples:

- `./some-repo:/root/repos/some-repo`
- `./some-repo:/repos/some-repo`
- `/tmp/some-location:/location:ro`
- `~/projects:/root/projects:ro`
- `~/projects:/projects:ro`
"""
),
}
Expand Down Expand Up @@ -181,7 +181,10 @@ def start(self) -> None:

for shared_shell_file in self.shell.collect_shared_files():
unix_path = shared_shell_file.relative_to(self.global_shared_dir).as_posix()
command.extend(("-v", f"{shared_shell_file}:{self.home_dir}/.shared/{unix_path}"))
command.extend(("-v", f"{shared_shell_file}:/.shared/{unix_path}"))

for mount in self.data_volumes:
command.extend(("--mount", mount.as_csv()))

for mount in self.cache_volumes:
command.extend(("--mount", mount.as_csv()))
Expand Down Expand Up @@ -370,7 +373,7 @@ def mcp_port(self) -> int:

@cached_property
def home_dir(self) -> str:
return "/root"
return "/home/dd"

@cached_property
def container_name(self) -> str:
Expand All @@ -382,32 +385,22 @@ def shell(self) -> Shell:

return get_shell(self.config.shell)(self.global_shared_dir)

@cached_property
def data_volumes(self) -> list[Mount]:
from dda.utils.container.model import Mount

return [
# Root data directory
Mount(type="volume", path="/var/lib/dd", source=self.get_volume_name("data")),
]

@cached_property
def cache_volumes(self) -> list[Mount]:
from dda.utils.container.model import Mount

return [
# `go env GOCACHE`
Mount(type="volume", path="/root/.cache/go-build", source=self.get_volume_name("go_build_cache")),
# `go env GOMODCACHE`
Mount(type="volume", path="/go/pkg/mod", source=self.get_volume_name("go_mod_cache")),
# `pip cache dir`
Mount(type="volume", path="/root/.cache/pip", source=self.get_volume_name("pip_cache")),
# `uv cache dir`
Mount(type="volume", path="/root/.cache/uv", source=self.get_volume_name("uv_cache")),
# Rust
Mount(type="volume", path="/root/.cargo/registry", source=self.get_volume_name("cargo_registry")),
Mount(type="volume", path="/root/.cargo/git", source=self.get_volume_name("cargo_git")),
# Omnibus
Mount(type="volume", path="/omnibus/vendor/bundle", source=self.get_volume_name("omnibus_gems")),
Mount(type="volume", path="/omnibus/cache", source=self.get_volume_name("omnibus_cache")),
Mount(
type="volume",
path="/tmp/omnibus-git-cache", # noqa: S108
source=self.get_volume_name("omnibus_git_cache"),
),
# VS Code/Cursor
Mount(type="volume", path="/root/.vscode-extensions", source=self.get_volume_name("vscode_extensions")),
# Root cache directory
Mount(type="volume", path="/var/cache/dd", source=self.get_volume_name("cache")),
Comment on lines +402 to +403
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC, we're now using a single volume for all caches rather than one volume per cache type - can you explain why this is ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for better discoverability and cache management. Rather than separate volumes, there is one hierarchical tree with permissions that are applied recursively. It makes everything easier!

]
Comment thread
ofek marked this conversation as resolved.

def cache_volume_names(self) -> list[str]:
Expand Down Expand Up @@ -437,7 +430,7 @@ def check_readiness(self) -> None:
def ssh_base_command(self) -> list[str]:
from dda.utils.ssh import ssh_base_command

return ssh_base_command("root@localhost", self.ssh_port)
return ssh_base_command("dd@localhost", self.ssh_port)

def ensure_ssh_config(self) -> None:
from dda.env.ssh import ensure_ssh_config
Expand All @@ -448,7 +441,7 @@ def repo_path(self, repo: str | None) -> str:
if repo is None:
repo = self.default_repo

return f"{self.home_dir}/repos/{repo}"
return f"/repos/{repo}"

def _container_cp(self, source: str, destination: str, *args: Any) -> None:
"""Runs a `cp -r` command inside the context of the container"""
Expand Down
6 changes: 3 additions & 3 deletions src/dda/utils/editors/types/cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

class CursorEditorInterface(EditorInterface):
def open_via_ssh(self, *, server: str, port: int, path: str) -> None:
self.app.subprocess.run(["cursor", "--remote", f"ssh-remote+root@{server}:{port}", path])
self.app.subprocess.run(["cursor", "--remote", f"ssh-remote+dd@{server}:{port}", path])

def add_mcp_server(self, *, name: str, url: str) -> None:
config = self.__load_mcp_config()
Expand All @@ -28,7 +28,7 @@ def remove_mcp_server(self, *, name: str) -> None:

@staticmethod
def __get_mcp_server_config(config: dict[str, Any]) -> dict[str, Any]:
# https://docs.cursor.com/context/mcp#using-mcp-json
# https://cursor.com/docs/mcp#using-mcpjson
return config.setdefault("mcpServers", {})

def __load_mcp_config(self) -> dict[str, Any]:
Expand All @@ -47,5 +47,5 @@ def __save_mcp_config(self, config: dict[str, Any]) -> None:

@cached_property
def __mcp_config_file(self) -> Path:
# https://docs.cursor.com/context/mcp#configuration-locations
# https://cursor.com/docs/mcp#configuration-locations
return Path.home() / ".cursor" / "mcp.json"
4 changes: 2 additions & 2 deletions src/dda/utils/editors/types/vscode.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

class VSCodeEditorInterface(EditorInterface):
def open_via_ssh(self, *, server: str, port: int, path: str) -> None:
self.app.subprocess.run(["code", "--remote", f"ssh-remote+root@{server}:{port}", path])
self.app.subprocess.run(["code", "--remote", f"ssh-remote+dd@{server}:{port}", path])

def add_mcp_server(self, *, name: str, url: str) -> None:
config = self.__load_config()
Expand All @@ -28,7 +28,7 @@ def remove_mcp_server(self, *, name: str) -> None:

@staticmethod
def __get_mcp_server_config(config: dict[str, Any]) -> dict[str, Any]:
# https://code.visualstudio.com/docs/copilot/chat/mcp-servers#_add-an-mcp-server-to-your-user-settings
# https://code.visualstudio.com/docs/copilot/customization/mcp-servers#_add-an-mcp-server
return config.setdefault("mcp", {}).setdefault("servers", {})

def __load_config(self) -> dict[str, Any]:
Expand Down
Loading
Loading