Skip to content
Merged
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
16 changes: 13 additions & 3 deletions src/dstack/_internal/server/services/jobs/configurators/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,17 @@ def _dstack_image_commands(self) -> List[str]:
):
return []
return [
f"eval $(echo 'export DSTACK_VENV_DIR={DSTACK_DIR}/venv' | sudo tee -a {DSTACK_PROFILE_PATH})",
# Make sure /dstack/venv is owned by the current user.
# XXX: Generally, /dstack and all its descendants should be owned by root, as it is
# intended to be a place for files shared by all users, but since a non-root user
# should be able to install packages via pip and we want to avoid cluttering the user's
# home dir if possible, we make the venv dir owned by the current user rather than
# creating it inside the user's home or (even worse) making /dstack/venv
# world-writable.
"sudo rm -rf $DSTACK_VENV_DIR",
"sudo mkdir $DSTACK_VENV_DIR",
"sudo chown $(id -u):$(id -g) $DSTACK_VENV_DIR",
# `uv` may emit:
# > warning: `VIRTUAL_ENV=/dstack/venv` does not match the project environment path
# > `.venv` and will be ignored; use `--active` to target the active environment
Expand All @@ -228,9 +239,8 @@ def _dstack_image_commands(self) -> List[str]:
# used for legacy `pip`-based configurations). `--no-active` suppresses the warning.
# Alternatively, the user can call `deactivate` once before using `uv`.
# If the user really wants to reuse dstack's venv, they must spefify `--active`.
f"uv venv -q --prompt dstack -p {self._python()} --seed {DSTACK_DIR}/venv",
f"echo '. {DSTACK_DIR}/venv/bin/activate' >> {DSTACK_PROFILE_PATH}",
f". {DSTACK_DIR}/venv/bin/activate",
f"uv venv -q --prompt dstack -p {self._python()} --seed $DSTACK_VENV_DIR",
f"eval $(echo '. $DSTACK_VENV_DIR/bin/activate' | sudo tee -a {DSTACK_PROFILE_PATH})",
]

def _app_specs(self) -> List[AppSpec]:
Expand Down
18 changes: 12 additions & 6 deletions src/tests/_internal/server/routers/test_runs.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,12 @@ def get_dev_env_run_plan_dict(
"-i",
"-c",
(
"uv venv -q --prompt dstack -p 3.13 --seed /dstack/venv"
" && echo '. /dstack/venv/bin/activate' >> /dstack/profile"
" && . /dstack/venv/bin/activate"
"eval $(echo 'export DSTACK_VENV_DIR=/dstack/venv' | sudo tee -a /dstack/profile)"
" && sudo rm -rf $DSTACK_VENV_DIR"
" && sudo mkdir $DSTACK_VENV_DIR"
" && sudo chown $(id -u):$(id -g) $DSTACK_VENV_DIR"
" && uv venv -q --prompt dstack -p 3.13 --seed $DSTACK_VENV_DIR"
" && eval $(echo '. $DSTACK_VENV_DIR/bin/activate' | sudo tee -a /dstack/profile)"
" && (echo 'pip install ipykernel...'"
" && pip install -q --no-cache-dir ipykernel 2> /dev/null)"
" || echo 'no pip, ipykernel was not installed'"
Expand Down Expand Up @@ -344,9 +347,12 @@ def get_dev_env_run_dict(
"-i",
"-c",
(
"uv venv -q --prompt dstack -p 3.13 --seed /dstack/venv"
" && echo '. /dstack/venv/bin/activate' >> /dstack/profile"
" && . /dstack/venv/bin/activate"
"eval $(echo 'export DSTACK_VENV_DIR=/dstack/venv' | sudo tee -a /dstack/profile)"
" && sudo rm -rf $DSTACK_VENV_DIR"
" && sudo mkdir $DSTACK_VENV_DIR"
" && sudo chown $(id -u):$(id -g) $DSTACK_VENV_DIR"
" && uv venv -q --prompt dstack -p 3.13 --seed $DSTACK_VENV_DIR"
" && eval $(echo '. $DSTACK_VENV_DIR/bin/activate' | sudo tee -a /dstack/profile)"
" && (echo 'pip install ipykernel...'"
" && pip install -q --no-cache-dir ipykernel 2> /dev/null)"
" || echo 'no pip, ipykernel was not installed'"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,15 @@ async def test_with_commands_no_image(self, shell: Optional[str], expected_shell
expected_shell,
"-i",
"-c",
"uv venv -q --prompt dstack -p 3.12 --seed /dstack/venv"
" && echo '. /dstack/venv/bin/activate' >> /dstack/profile"
" && . /dstack/venv/bin/activate"
" && sleep inf",
(
"eval $(echo 'export DSTACK_VENV_DIR=/dstack/venv' | sudo tee -a /dstack/profile)"
" && sudo rm -rf $DSTACK_VENV_DIR"
" && sudo mkdir $DSTACK_VENV_DIR"
" && sudo chown $(id -u):$(id -g) $DSTACK_VENV_DIR"
" && uv venv -q --prompt dstack -p 3.12 --seed $DSTACK_VENV_DIR"
" && eval $(echo '. $DSTACK_VENV_DIR/bin/activate' | sudo tee -a /dstack/profile)"
" && sleep inf"
),
]

async def test_no_commands(self, image_config_mock: ImageConfig):
Expand Down