Skip to content

Commit 7c20287

Browse files
committed
Move ensure_browser_proxy_started to parent class
1 parent bccd8e8 commit 7c20287

2 files changed

Lines changed: 43 additions & 36 deletions

File tree

src/dda/env/dev/interface.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,44 @@ def launch_gui(self) -> NoReturn:
199199
"""
200200
raise NotImplementedError
201201

202+
def ensure_browser_proxy_started(self) -> None:
203+
"""
204+
Start the shared browser proxy daemon on the host if it is not already running.
205+
206+
The daemon forwards browser open requests from inside the environment to the host's
207+
default browser, including setting up SSH port forwards for OAuth callbacks.
208+
Subclasses that do not support browser forwarding may leave this as a no-op.
209+
"""
210+
import sys
211+
212+
try:
213+
import psutil
214+
except ImportError:
215+
return
216+
217+
storage = self.app.config.storage.join("browser-proxy")
218+
storage.data.ensure_dir()
219+
pid_file = storage.data / "server.pid"
220+
log_file = storage.data / "browser-proxy.log"
221+
if pid_file.is_file():
222+
try:
223+
pid = int(pid_file.read_text().strip())
224+
proc = psutil.Process(pid)
225+
if proc.is_running() and "dda.env.dev.browser_proxy" in " ".join(proc.cmdline()):
226+
return
227+
except (ValueError, psutil.NoSuchProcess, psutil.AccessDenied):
228+
pass
229+
pid_file.unlink()
230+
pid = self.app.subprocess.spawn_daemon([
231+
sys.executable,
232+
"-m",
233+
"dda.env.dev.browser_proxy",
234+
str(self.browser_proxy_port),
235+
"--log-file",
236+
str(log_file),
237+
])
238+
pid_file.write_text(str(pid), encoding="utf-8")
239+
202240
def remove_cache(self) -> None:
203241
"""
204242
This method removes the developer environment's cache that is persisted between lifecycles.

src/dda/env/dev/types/linux_container.py

Lines changed: 5 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ def start(self) -> None:
147147
status = self.__latest_status if self.__latest_status is not None else self.status()
148148
if status.state == EnvironmentState.STOPPED:
149149
self.docker.wait(["start", self.container_name], message=f"Starting container: {self.container_name}")
150-
self._ensure_browser_proxy_started()
150+
self.ensure_browser_proxy_started()
151151
else:
152152
from dda.config.constants import AppEnvVars
153153
from dda.utils.process import EnvVars
@@ -256,7 +256,7 @@ def start(self) -> None:
256256
with self.app.status(f"Waiting for container: {self.container_name}"):
257257
wait_for(self.check_readiness, timeout=30, interval=0.3)
258258

259-
self._ensure_browser_proxy_started()
259+
self.ensure_browser_proxy_started()
260260
self.ensure_ssh_config()
261261

262262
if self.config.clone:
@@ -315,7 +315,7 @@ def status(self) -> EnvironmentStatus:
315315

316316
def launch_shell(self, *, repo: str | None = None) -> NoReturn:
317317
self.ensure_ssh_config()
318-
self._ensure_browser_proxy_started()
318+
self.ensure_browser_proxy_started()
319319
ssh_command = self.ssh_base_command()
320320
ssh_command.append(self.shell.get_login_command(cwd=self.repo_path(repo)))
321321
process = self.app.subprocess.attach(ssh_command, check=False)
@@ -326,7 +326,7 @@ def code(self, *, editor: EditorInterface, repo: str | None = None) -> None:
326326
self.app.abort(f"Unsupported editor: {editor.name}")
327327

328328
self.ensure_ssh_config()
329-
self._ensure_browser_proxy_started()
329+
self.ensure_browser_proxy_started()
330330
repo_path = self.repo_path(repo)
331331

332332
# TODO: Currently, we do not support aggregating local commands from multiple repositories as a single tool
@@ -346,7 +346,7 @@ def code(self, *, editor: EditorInterface, repo: str | None = None) -> None:
346346

347347
def run_command(self, command: list[str], *, repo: str | None = None) -> None:
348348
self.ensure_ssh_config()
349-
self._ensure_browser_proxy_started()
349+
self.ensure_browser_proxy_started()
350350
self.app.subprocess.run(self.construct_command(command, cwd=self.repo_path(repo)))
351351

352352
def remove_cache(self) -> None:
@@ -455,37 +455,6 @@ def _write_xdg_open_script(self) -> None:
455455
)
456456
os.chmod(self._xdg_open_script_path, 0o755) # noqa: S103
457457

458-
def _ensure_browser_proxy_started(self) -> None:
459-
"""
460-
Start the shared browser proxy daemon if it is not already running.
461-
Useful to open browser on the host machine from the container, to handle authentication
462-
callbacks.
463-
"""
464-
import psutil
465-
466-
storage = self.app.config.storage.join("browser-proxy")
467-
storage.data.ensure_dir()
468-
pid_file = storage.data / "server.pid"
469-
log_file = storage.data / "browser-proxy.log"
470-
if pid_file.is_file():
471-
try:
472-
pid = int(pid_file.read_text().strip())
473-
proc = psutil.Process(pid)
474-
if proc.is_running() and "dda.env.dev.browser_proxy" in " ".join(proc.cmdline()):
475-
return
476-
except (ValueError, psutil.NoSuchProcess, psutil.AccessDenied):
477-
pass
478-
pid_file.unlink()
479-
pid = self.app.subprocess.spawn_daemon([
480-
sys.executable,
481-
"-m",
482-
"dda.env.dev.browser_proxy",
483-
str(self.browser_proxy_port),
484-
"--log-file",
485-
str(log_file),
486-
])
487-
pid_file.write_text(str(pid), encoding="utf-8")
488-
489458
def construct_command(self, command: list[str], *, cwd: str | None = None) -> list[str]:
490459
if cwd is None:
491460
cwd = self.home_dir

0 commit comments

Comments
 (0)