devs-common 2.0.10__tar.gz → 2.0.12__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {devs_common-2.0.10 → devs_common-2.0.12}/PKG-INFO +1 -1
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/core/container.py +126 -104
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/Dockerfile +5 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common.egg-info/PKG-INFO +1 -1
- {devs_common-2.0.10 → devs_common-2.0.12}/pyproject.toml +1 -1
- {devs_common-2.0.10 → devs_common-2.0.12}/LICENSE +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/README.md +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/__init__.py +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/config.py +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/core/__init__.py +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/core/project.py +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/core/workspace.py +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/devs_config.py +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/exceptions.py +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/devcontainer.json +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/scripts/copy-ssh.sh +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/scripts/post-create-wrapper.sh +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/scripts/python-venv-integration.sh +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/scripts/screenshot-webapp.sh +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/scripts/setup-workspace.sh +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/scripts/start-tunnel.sh +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/scripts/tunnel-status.sh +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/scripts/webapp-screenshot.py +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/sudo-scripts/init-firewall.sh +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/sudo-scripts/setup-devs-env.sh +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/sudo-scripts/setup-vscode-cache.sh +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/sudo-scripts/start-services.sh +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/vscode-settings-reference.md +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/utils/__init__.py +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/utils/config_hash.py +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/utils/console.py +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/utils/devcontainer.py +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/utils/devcontainer_template.py +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/utils/docker_client.py +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/utils/file_utils.py +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/utils/git_utils.py +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common/utils/repo_cache.py +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common.egg-info/SOURCES.txt +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common.egg-info/dependency_links.txt +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common.egg-info/requires.txt +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/devs_common.egg-info/top_level.txt +0 -0
- {devs_common-2.0.10 → devs_common-2.0.12}/setup.cfg +0 -0
|
@@ -399,27 +399,20 @@ class ContainerManager:
|
|
|
399
399
|
project_labels = self._get_project_labels(dev_name)
|
|
400
400
|
|
|
401
401
|
try:
|
|
402
|
-
console.print(f" 🔍 Looking for containers with labels: {project_labels}")
|
|
403
402
|
existing_containers = self.docker.find_containers_by_labels(project_labels)
|
|
404
|
-
console.print(f" 📋 Found {len(existing_containers)} containers")
|
|
405
403
|
|
|
406
404
|
if existing_containers:
|
|
407
405
|
for container_info in existing_containers:
|
|
408
406
|
container_name = container_info['name']
|
|
409
|
-
container_status = container_info['status']
|
|
410
407
|
|
|
411
|
-
console.print(f" 🛑 Stopping container: {container_name} (status: {container_status})")
|
|
412
408
|
try:
|
|
413
|
-
|
|
414
|
-
console.print(f" 📋 Stop result: {stop_result}")
|
|
409
|
+
self.docker.stop_container(container_name)
|
|
415
410
|
except DockerError as stop_e:
|
|
416
411
|
console.print(f" ⚠️ Stop failed for {container_name}: {stop_e}")
|
|
417
412
|
|
|
418
413
|
if remove:
|
|
419
|
-
console.print(f" 🗑️ Removing container: {container_name}")
|
|
420
414
|
try:
|
|
421
|
-
|
|
422
|
-
console.print(f" 📋 Remove result: {remove_result}")
|
|
415
|
+
self.docker.remove_container(container_name)
|
|
423
416
|
except DockerError as remove_e:
|
|
424
417
|
console.print(f" ⚠️ Remove failed for {container_name}: {remove_e}")
|
|
425
418
|
|
|
@@ -586,7 +579,7 @@ class ContainerManager:
|
|
|
586
579
|
|
|
587
580
|
return removed_count
|
|
588
581
|
|
|
589
|
-
def _prepare_container_exec(self, dev_name: str, workspace_dir: Path, debug: bool = False, live: bool = False, extra_env: Optional[Dict[str, str]] = None) -> Tuple[str, str]:
|
|
582
|
+
def _prepare_container_exec(self, dev_name: str, workspace_dir: Path, debug: bool = False, live: bool = False, extra_env: Optional[Dict[str, str]] = None, reuse_existing: bool = False) -> Tuple[str, str]:
|
|
590
583
|
"""Prepare container for exec operations (shared by exec_shell and exec_command).
|
|
591
584
|
|
|
592
585
|
Args:
|
|
@@ -595,6 +588,10 @@ class ContainerManager:
|
|
|
595
588
|
debug: Show debug output for devcontainer operations
|
|
596
589
|
live: Whether the container is in live mode
|
|
597
590
|
extra_env: Additional environment variables to pass to container
|
|
591
|
+
reuse_existing: If True, use existing container as-is (starting
|
|
592
|
+
it if stopped) without rebuilding. Only creates a new
|
|
593
|
+
container if none exists. Used by tunnel commands to
|
|
594
|
+
avoid accidentally destroying work in the container.
|
|
598
595
|
|
|
599
596
|
Returns:
|
|
600
597
|
Tuple of (container_name, container_workspace_dir)
|
|
@@ -623,9 +620,17 @@ class ContainerManager:
|
|
|
623
620
|
workspace_name = workspace_info["workspace_name"]
|
|
624
621
|
container_workspace_dir = f"/workspaces/{workspace_name}"
|
|
625
622
|
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
623
|
+
if reuse_existing and existing_containers:
|
|
624
|
+
# Use existing container as-is (start if stopped, but never rebuild)
|
|
625
|
+
status = existing_containers[0].get('status', '')
|
|
626
|
+
if status != 'running':
|
|
627
|
+
container_id = existing_containers[0].get('name', container_name)
|
|
628
|
+
console.print(f" ▶️ Starting stopped container: {container_id}")
|
|
629
|
+
self.docker.start_container(container_id)
|
|
630
|
+
else:
|
|
631
|
+
# Ensure container is running (may create/restart as needed)
|
|
632
|
+
if not self.ensure_container_running(dev_name, workspace_dir, debug=debug, live=live, extra_env=extra_env):
|
|
633
|
+
raise ContainerError(f"Failed to start container for {dev_name}")
|
|
629
634
|
|
|
630
635
|
return container_name, container_workspace_dir
|
|
631
636
|
|
|
@@ -877,13 +882,99 @@ class ContainerManager:
|
|
|
877
882
|
|
|
878
883
|
return tunnel_name
|
|
879
884
|
|
|
885
|
+
def _run_tunnel_auth(self, container_name: str, debug: bool = False) -> bool:
|
|
886
|
+
"""Run interactive VS Code tunnel authentication in a container.
|
|
887
|
+
|
|
888
|
+
Returns:
|
|
889
|
+
True if authentication succeeded
|
|
890
|
+
"""
|
|
891
|
+
console.print("[yellow]Follow the prompts to authenticate:[/yellow]")
|
|
892
|
+
console.print(" 1. A URL and code will be displayed")
|
|
893
|
+
console.print(" 2. Open the URL in your browser")
|
|
894
|
+
console.print(" 3. Enter the code to authenticate with GitHub/Microsoft")
|
|
895
|
+
console.print("")
|
|
896
|
+
|
|
897
|
+
cmd = [
|
|
898
|
+
'docker', 'exec', '-it',
|
|
899
|
+
container_name,
|
|
900
|
+
'/usr/local/bin/code', 'tunnel', 'user', 'login',
|
|
901
|
+
'--provider', 'github'
|
|
902
|
+
]
|
|
903
|
+
|
|
904
|
+
if debug:
|
|
905
|
+
console.print(f"[dim]Running: {' '.join(cmd)}[/dim]")
|
|
906
|
+
|
|
907
|
+
result = subprocess.run(cmd, check=False)
|
|
908
|
+
|
|
909
|
+
if result.returncode == 0:
|
|
910
|
+
console.print("")
|
|
911
|
+
console.print("[bold green]Authentication successful![/bold green]")
|
|
912
|
+
console.print(" Auth persists across container stop/restart cycles.")
|
|
913
|
+
return True
|
|
914
|
+
else:
|
|
915
|
+
console.print("")
|
|
916
|
+
console.print("[yellow]Authentication was cancelled or failed.[/yellow]")
|
|
917
|
+
return False
|
|
918
|
+
|
|
919
|
+
def _start_and_poll_tunnel(self, container_name: str, dev_name: str, tunnel_cmd: str,
|
|
920
|
+
log_file: str, vscode_cmd: str, web_url: str, debug: bool = False) -> bool:
|
|
921
|
+
"""Start a detached tunnel and poll the log for startup confirmation.
|
|
922
|
+
|
|
923
|
+
Returns:
|
|
924
|
+
True if tunnel started (or timed out), False if auth is needed.
|
|
925
|
+
"""
|
|
926
|
+
subprocess.run(
|
|
927
|
+
['docker', 'exec', '-d', container_name,
|
|
928
|
+
'/bin/sh', '-c', f'{tunnel_cmd} > {log_file} 2>&1'],
|
|
929
|
+
check=True
|
|
930
|
+
)
|
|
931
|
+
|
|
932
|
+
console.print("[dim]Waiting for tunnel to start...[/dim]")
|
|
933
|
+
for i in range(15):
|
|
934
|
+
time.sleep(1)
|
|
935
|
+
result = subprocess.run(
|
|
936
|
+
['docker', 'exec', container_name, 'cat', log_file],
|
|
937
|
+
capture_output=True, text=True
|
|
938
|
+
)
|
|
939
|
+
output = result.stdout
|
|
940
|
+
|
|
941
|
+
if 'Open this link' in output or 'vscode.dev/tunnel' in output:
|
|
942
|
+
console.print(f"[bold green]Tunnel running![/bold green]")
|
|
943
|
+
console.print("")
|
|
944
|
+
console.print("[bold]Connect:[/bold]")
|
|
945
|
+
console.print(f" Desktop: {vscode_cmd}")
|
|
946
|
+
console.print(f" Browser: {web_url}")
|
|
947
|
+
console.print("")
|
|
948
|
+
console.print(f"[dim]Use 'devs tunnel {dev_name} --status' to check status[/dim]")
|
|
949
|
+
console.print(f"[dim]Use 'devs tunnel {dev_name} --kill' to stop[/dim]")
|
|
950
|
+
return True
|
|
951
|
+
|
|
952
|
+
if 'log in' in output.lower() or 'device' in output.lower() or 'invalid' in output.lower():
|
|
953
|
+
subprocess.run(
|
|
954
|
+
['docker', 'exec', container_name, '/usr/local/bin/code', 'tunnel', 'kill'],
|
|
955
|
+
capture_output=True
|
|
956
|
+
)
|
|
957
|
+
return False
|
|
958
|
+
|
|
959
|
+
if debug and output.strip():
|
|
960
|
+
console.print(f"[dim]Log ({i+1}s): {output.strip()[-100:]}[/dim]")
|
|
961
|
+
|
|
962
|
+
# Timeout
|
|
963
|
+
result = subprocess.run(
|
|
964
|
+
['docker', 'exec', container_name, 'cat', log_file],
|
|
965
|
+
capture_output=True, text=True
|
|
966
|
+
)
|
|
967
|
+
if result.stdout.strip():
|
|
968
|
+
console.print("[yellow]Tunnel may still be starting. Log output:[/yellow]")
|
|
969
|
+
console.print(result.stdout.strip())
|
|
970
|
+
else:
|
|
971
|
+
console.print("[yellow]Tunnel started but no output yet. Check status with:[/yellow]")
|
|
972
|
+
console.print(f" devs tunnel {dev_name} --status")
|
|
973
|
+
return True
|
|
974
|
+
|
|
880
975
|
def tunnel_auth(self, dev_name: str, workspace_dir: Path, debug: bool = False, live: bool = False, extra_env: Optional[Dict[str, str]] = None) -> None:
|
|
881
976
|
"""Authenticate VS Code tunnel (interactive, per-container setup).
|
|
882
977
|
|
|
883
|
-
Runs the device code flow interactively inside the container. Auth is
|
|
884
|
-
stored in the container's filesystem and persists across stop/restart
|
|
885
|
-
cycles (but not container removal/recreation).
|
|
886
|
-
|
|
887
978
|
Args:
|
|
888
979
|
dev_name: Development environment name
|
|
889
980
|
workspace_dir: Workspace directory path
|
|
@@ -896,7 +987,7 @@ class ContainerManager:
|
|
|
896
987
|
"""
|
|
897
988
|
try:
|
|
898
989
|
container_name, container_workspace_dir = self._prepare_container_exec(
|
|
899
|
-
dev_name, workspace_dir, debug=debug, live=live, extra_env=extra_env
|
|
990
|
+
dev_name, workspace_dir, debug=debug, live=live, extra_env=extra_env, reuse_existing=True
|
|
900
991
|
)
|
|
901
992
|
|
|
902
993
|
tunnel_name = self._get_tunnel_name(dev_name)
|
|
@@ -904,34 +995,11 @@ class ContainerManager:
|
|
|
904
995
|
console.print("🔐 Setting up VS Code tunnel authentication...")
|
|
905
996
|
console.print(f" Container: {container_name}")
|
|
906
997
|
console.print("")
|
|
907
|
-
console.print("[yellow]Follow the prompts to authenticate:[/yellow]")
|
|
908
|
-
console.print(" 1. A URL and code will be displayed")
|
|
909
|
-
console.print(" 2. Open the URL in your browser")
|
|
910
|
-
console.print(" 3. Enter the code to authenticate with GitHub/Microsoft")
|
|
911
|
-
console.print("")
|
|
912
998
|
|
|
913
|
-
|
|
914
|
-
'docker', 'exec', '-it',
|
|
915
|
-
container_name,
|
|
916
|
-
'/usr/local/bin/code', 'tunnel', 'user', 'login',
|
|
917
|
-
'--provider', 'github'
|
|
918
|
-
]
|
|
919
|
-
|
|
920
|
-
if debug:
|
|
921
|
-
console.print(f"[dim]Running: {' '.join(cmd)}[/dim]")
|
|
922
|
-
|
|
923
|
-
result = subprocess.run(cmd, check=False)
|
|
924
|
-
|
|
925
|
-
if result.returncode == 0:
|
|
926
|
-
console.print("")
|
|
927
|
-
console.print("[bold green]Authentication successful![/bold green]")
|
|
928
|
-
console.print(" Auth persists across container stop/restart cycles.")
|
|
999
|
+
if self._run_tunnel_auth(container_name, debug=debug):
|
|
929
1000
|
console.print("")
|
|
930
1001
|
console.print(f" Start a tunnel: devs tunnel {dev_name}")
|
|
931
1002
|
console.print(f" Then connect: code --remote tunnel+{tunnel_name} {container_workspace_dir}")
|
|
932
|
-
else:
|
|
933
|
-
console.print("")
|
|
934
|
-
console.print("[yellow]Authentication was cancelled or failed.[/yellow]")
|
|
935
1003
|
|
|
936
1004
|
except (DockerError, subprocess.SubprocessError) as e:
|
|
937
1005
|
raise ContainerError(f"Failed to authenticate tunnel in {dev_name}: {e}")
|
|
@@ -939,8 +1007,7 @@ class ContainerManager:
|
|
|
939
1007
|
def start_tunnel(self, dev_name: str, workspace_dir: Path, debug: bool = False, live: bool = False, extra_env: Optional[Dict[str, str]] = None) -> None:
|
|
940
1008
|
"""Start a VS Code tunnel in the background.
|
|
941
1009
|
|
|
942
|
-
|
|
943
|
-
detached inside the container.
|
|
1010
|
+
If authentication is needed, prompts interactively then retries.
|
|
944
1011
|
|
|
945
1012
|
Args:
|
|
946
1013
|
dev_name: Development environment name
|
|
@@ -954,78 +1021,33 @@ class ContainerManager:
|
|
|
954
1021
|
"""
|
|
955
1022
|
try:
|
|
956
1023
|
container_name, container_workspace_dir = self._prepare_container_exec(
|
|
957
|
-
dev_name, workspace_dir, debug=debug, live=live, extra_env=extra_env
|
|
1024
|
+
dev_name, workspace_dir, debug=debug, live=live, extra_env=extra_env, reuse_existing=True
|
|
958
1025
|
)
|
|
959
1026
|
|
|
960
1027
|
tunnel_name = self._get_tunnel_name(dev_name)
|
|
961
1028
|
log_file = '/tmp/vscode-tunnel.log'
|
|
962
1029
|
tunnel_cmd = f'/usr/local/bin/code tunnel --accept-server-license-terms --name {tunnel_name}'
|
|
963
1030
|
vscode_cmd = f"code --remote tunnel+{tunnel_name} {container_workspace_dir}"
|
|
1031
|
+
web_url = f"https://vscode.dev/tunnel/{tunnel_name}{container_workspace_dir}"
|
|
964
1032
|
|
|
965
1033
|
console.print(f"[bold cyan]Starting VS Code tunnel for: {dev_name}[/bold cyan]")
|
|
966
1034
|
console.print(f" Container: {container_name}")
|
|
967
1035
|
console.print(f" Tunnel name: {tunnel_name}")
|
|
968
1036
|
console.print("")
|
|
969
1037
|
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
]
|
|
977
|
-
|
|
978
|
-
if debug:
|
|
979
|
-
console.print(f"[dim]Running: {' '.join(cmd)}[/dim]")
|
|
980
|
-
|
|
981
|
-
subprocess.run(cmd, check=True)
|
|
982
|
-
|
|
983
|
-
# Poll the log to confirm startup and show the URL
|
|
984
|
-
console.print("[dim]Waiting for tunnel to start...[/dim]")
|
|
985
|
-
for i in range(15):
|
|
986
|
-
time.sleep(1)
|
|
987
|
-
result = subprocess.run(
|
|
988
|
-
['docker', 'exec', container_name, 'cat', log_file],
|
|
989
|
-
capture_output=True, text=True
|
|
990
|
-
)
|
|
991
|
-
output = result.stdout
|
|
992
|
-
|
|
993
|
-
if 'Open this link' in output or 'vscode.dev/tunnel' in output:
|
|
994
|
-
console.print(f"[bold green]Tunnel running![/bold green]")
|
|
995
|
-
console.print("")
|
|
996
|
-
console.print("[bold]Connect from your local machine:[/bold]")
|
|
997
|
-
console.print(f" {vscode_cmd}")
|
|
998
|
-
console.print("")
|
|
999
|
-
for line in output.split('\n'):
|
|
1000
|
-
if 'vscode.dev/tunnel' in line:
|
|
1001
|
-
console.print(f"[dim]Or open in browser: {line.strip()}[/dim]")
|
|
1002
|
-
console.print(f"[dim]Use 'devs tunnel {dev_name} --status' to check status[/dim]")
|
|
1003
|
-
console.print(f"[dim]Use 'devs tunnel {dev_name} --kill' to stop[/dim]")
|
|
1004
|
-
return
|
|
1005
|
-
|
|
1006
|
-
if 'log in' in output.lower() or 'device' in output.lower() or 'invalid' in output.lower():
|
|
1007
|
-
console.print("[yellow]Authentication required.[/yellow]")
|
|
1008
|
-
console.print(f" Run: devs tunnel {dev_name} --auth")
|
|
1009
|
-
subprocess.run(
|
|
1010
|
-
['docker', 'exec', container_name, '/usr/local/bin/code', 'tunnel', 'kill'],
|
|
1011
|
-
capture_output=True
|
|
1012
|
-
)
|
|
1038
|
+
if not self._start_and_poll_tunnel(container_name, dev_name, tunnel_cmd,
|
|
1039
|
+
log_file, vscode_cmd, web_url, debug=debug):
|
|
1040
|
+
# Auth needed
|
|
1041
|
+
console.print("[yellow]Authentication required. Starting login...[/yellow]")
|
|
1042
|
+
console.print("")
|
|
1043
|
+
if not self._run_tunnel_auth(container_name, debug=debug):
|
|
1013
1044
|
return
|
|
1014
1045
|
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
['docker', 'exec', container_name, 'cat', log_file],
|
|
1021
|
-
capture_output=True, text=True
|
|
1022
|
-
)
|
|
1023
|
-
if result.stdout.strip():
|
|
1024
|
-
console.print("[yellow]Tunnel may still be starting. Log output:[/yellow]")
|
|
1025
|
-
console.print(result.stdout.strip())
|
|
1026
|
-
else:
|
|
1027
|
-
console.print("[yellow]Tunnel started but no output yet. Check status with:[/yellow]")
|
|
1028
|
-
console.print(f" devs tunnel {dev_name} --status")
|
|
1046
|
+
console.print("")
|
|
1047
|
+
console.print("[dim]Restarting tunnel...[/dim]")
|
|
1048
|
+
console.print("")
|
|
1049
|
+
self._start_and_poll_tunnel(container_name, dev_name, tunnel_cmd,
|
|
1050
|
+
log_file, vscode_cmd, web_url, debug=debug)
|
|
1029
1051
|
|
|
1030
1052
|
except (DockerError, subprocess.SubprocessError) as e:
|
|
1031
1053
|
raise ContainerError(f"Failed to start tunnel in {dev_name}: {e}")
|
|
@@ -1049,7 +1071,7 @@ class ContainerManager:
|
|
|
1049
1071
|
try:
|
|
1050
1072
|
# Prepare container for execution
|
|
1051
1073
|
container_name, container_workspace_dir = self._prepare_container_exec(
|
|
1052
|
-
dev_name, workspace_dir, debug=debug, live=live, extra_env=extra_env
|
|
1074
|
+
dev_name, workspace_dir, debug=debug, live=live, extra_env=extra_env, reuse_existing=True
|
|
1053
1075
|
)
|
|
1054
1076
|
|
|
1055
1077
|
# Check tunnel status
|
|
@@ -1091,7 +1113,7 @@ class ContainerManager:
|
|
|
1091
1113
|
try:
|
|
1092
1114
|
# Prepare container for execution
|
|
1093
1115
|
container_name, container_workspace_dir = self._prepare_container_exec(
|
|
1094
|
-
dev_name, workspace_dir, debug=debug, live=live, extra_env=extra_env
|
|
1116
|
+
dev_name, workspace_dir, debug=debug, live=live, extra_env=extra_env, reuse_existing=True
|
|
1095
1117
|
)
|
|
1096
1118
|
|
|
1097
1119
|
# Kill the tunnel
|
|
@@ -125,9 +125,14 @@ RUN curl -fsSL https://claude.ai/install.sh | bash
|
|
|
125
125
|
# Install OpenAI Codex CLI
|
|
126
126
|
RUN npm install -g @openai/codex
|
|
127
127
|
|
|
128
|
+
# Install cloudflared for tunnel support (proxies all HTTP methods correctly)
|
|
128
129
|
# Install VS Code CLI for tunnel support (needs root for /usr/local/bin)
|
|
129
130
|
# Using the standalone CLI which supports the 'tunnel' command
|
|
130
131
|
USER root
|
|
132
|
+
RUN ARCH=$(dpkg --print-architecture) && \
|
|
133
|
+
curl -fSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${ARCH}" -o /usr/local/bin/cloudflared && \
|
|
134
|
+
chmod +x /usr/local/bin/cloudflared
|
|
135
|
+
|
|
131
136
|
RUN ARCH=$(dpkg --print-architecture) && \
|
|
132
137
|
if [ "$ARCH" = "amd64" ]; then \
|
|
133
138
|
curl -fSL 'https://update.code.visualstudio.com/latest/cli-linux-x64/stable' -o /tmp/vscode-cli.tar.gz; \
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/scripts/post-create-wrapper.sh
RENAMED
|
File without changes
|
{devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/scripts/python-venv-integration.sh
RENAMED
|
File without changes
|
{devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/scripts/screenshot-webapp.sh
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/scripts/webapp-screenshot.py
RENAMED
|
File without changes
|
{devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/sudo-scripts/init-firewall.sh
RENAMED
|
File without changes
|
{devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/sudo-scripts/setup-devs-env.sh
RENAMED
|
File without changes
|
{devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/sudo-scripts/setup-vscode-cache.sh
RENAMED
|
File without changes
|
{devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/sudo-scripts/start-services.sh
RENAMED
|
File without changes
|
{devs_common-2.0.10 → devs_common-2.0.12}/devs_common/templates/vscode-settings-reference.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|