devs-cli 1.2.0__tar.gz → 2.0.0__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_cli-1.2.0/devs_cli.egg-info → devs_cli-2.0.0}/PKG-INFO +1 -1
- {devs_cli-1.2.0 → devs_cli-2.0.0}/devs/cli.py +86 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/devs/config.py +9 -2
- {devs_cli-1.2.0 → devs_cli-2.0.0/devs_cli.egg-info}/PKG-INFO +1 -1
- {devs_cli-1.2.0 → devs_cli-2.0.0}/pyproject.toml +1 -1
- {devs_cli-1.2.0 → devs_cli-2.0.0}/LICENSE +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/README.md +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/devs/__init__.py +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/devs/core/__init__.py +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/devs/core/integration.py +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/devs/exceptions.py +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/devs/utils/__init__.py +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/devs_cli.egg-info/SOURCES.txt +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/devs_cli.egg-info/dependency_links.txt +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/devs_cli.egg-info/entry_points.txt +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/devs_cli.egg-info/requires.txt +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/devs_cli.egg-info/top_level.txt +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/setup.cfg +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/tests/test_cli.py +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/tests/test_cli_clean.py +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/tests/test_cli_misc.py +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/tests/test_cli_start.py +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/tests/test_cli_stop.py +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/tests/test_cli_vscode.py +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/tests/test_container_manager.py +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/tests/test_e2e.py +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/tests/test_error_parsing.py +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/tests/test_integration.py +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/tests/test_live_mode.py +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/tests/test_project.py +0 -0
- {devs_cli-1.2.0 → devs_cli-2.0.0}/tests/test_workspace_manager.py +0 -0
|
@@ -778,6 +778,92 @@ def runtests(dev_name: str, reset_workspace: bool, live: bool, env: tuple, debug
|
|
|
778
778
|
sys.exit(1)
|
|
779
779
|
|
|
780
780
|
|
|
781
|
+
@cli.command()
|
|
782
|
+
@click.argument('dev_name')
|
|
783
|
+
@click.option('--status', is_flag=True, help='Check tunnel status instead of starting')
|
|
784
|
+
@click.option('--kill', 'kill_tunnel', is_flag=True, help='Kill running tunnel')
|
|
785
|
+
@click.option('--live', is_flag=True, help='Start container with current directory mounted as workspace')
|
|
786
|
+
@click.option('--env', multiple=True, help='Environment variables to pass to container (format: VAR=value)')
|
|
787
|
+
@debug_option
|
|
788
|
+
def tunnel(dev_name: str, status: bool, kill_tunnel: bool, live: bool, env: tuple, debug: bool) -> None:
|
|
789
|
+
"""Start a VS Code tunnel in devcontainer.
|
|
790
|
+
|
|
791
|
+
VS Code tunnels allow you to connect VS Code directly to the container
|
|
792
|
+
without SSH - the container initiates an outbound connection to Microsoft's
|
|
793
|
+
tunnel service, and your local VS Code connects through that.
|
|
794
|
+
|
|
795
|
+
This is useful for:
|
|
796
|
+
- Connecting to containers on remote servers without port forwarding
|
|
797
|
+
- Working through firewalls (only outbound connections needed)
|
|
798
|
+
- Avoiding the "double-hop" of SSH + container attach
|
|
799
|
+
|
|
800
|
+
DEV_NAME: Development environment name
|
|
801
|
+
|
|
802
|
+
Example: devs tunnel sally # Start tunnel (interactive)
|
|
803
|
+
Example: devs tunnel sally --status # Check tunnel status
|
|
804
|
+
Example: devs tunnel sally --kill # Stop running tunnel
|
|
805
|
+
Example: devs tunnel sally --live # Start with current directory mounted
|
|
806
|
+
"""
|
|
807
|
+
check_dependencies()
|
|
808
|
+
project = get_project()
|
|
809
|
+
|
|
810
|
+
# Load environment variables from DEVS.yml and merge with CLI --env flags
|
|
811
|
+
devs_env = DevsConfigLoader.load_env_vars(dev_name, project.info.name)
|
|
812
|
+
cli_env = parse_env_vars(env) if env else {}
|
|
813
|
+
extra_env = merge_env_vars(devs_env, cli_env) if devs_env or cli_env else None
|
|
814
|
+
|
|
815
|
+
if extra_env:
|
|
816
|
+
console.print(f"Environment variables: {', '.join(f'{k}={v}' for k, v in extra_env.items())}")
|
|
817
|
+
|
|
818
|
+
container_manager = ContainerManager(project, config)
|
|
819
|
+
workspace_manager = WorkspaceManager(project, config)
|
|
820
|
+
|
|
821
|
+
try:
|
|
822
|
+
# Ensure workspace exists (handles live mode internally)
|
|
823
|
+
workspace_dir = workspace_manager.create_workspace(dev_name, live=live)
|
|
824
|
+
|
|
825
|
+
if status:
|
|
826
|
+
# Check tunnel status
|
|
827
|
+
is_running, status_msg = container_manager.get_tunnel_status(
|
|
828
|
+
dev_name=dev_name,
|
|
829
|
+
workspace_dir=workspace_dir,
|
|
830
|
+
debug=debug,
|
|
831
|
+
live=live,
|
|
832
|
+
extra_env=extra_env
|
|
833
|
+
)
|
|
834
|
+
if is_running:
|
|
835
|
+
console.print(f"Tunnel status for {dev_name}:")
|
|
836
|
+
console.print(status_msg)
|
|
837
|
+
else:
|
|
838
|
+
console.print(f"No tunnel running in {dev_name}")
|
|
839
|
+
console.print(f" {status_msg}")
|
|
840
|
+
|
|
841
|
+
elif kill_tunnel:
|
|
842
|
+
# Kill the tunnel
|
|
843
|
+
console.print(f"Stopping tunnel in {dev_name}...")
|
|
844
|
+
container_manager.kill_tunnel(
|
|
845
|
+
dev_name=dev_name,
|
|
846
|
+
workspace_dir=workspace_dir,
|
|
847
|
+
debug=debug,
|
|
848
|
+
live=live,
|
|
849
|
+
extra_env=extra_env
|
|
850
|
+
)
|
|
851
|
+
|
|
852
|
+
else:
|
|
853
|
+
# Start the tunnel (interactive)
|
|
854
|
+
container_manager.start_tunnel(
|
|
855
|
+
dev_name=dev_name,
|
|
856
|
+
workspace_dir=workspace_dir,
|
|
857
|
+
debug=debug,
|
|
858
|
+
live=live,
|
|
859
|
+
extra_env=extra_env
|
|
860
|
+
)
|
|
861
|
+
|
|
862
|
+
except (ContainerError, WorkspaceError) as e:
|
|
863
|
+
console.print(f"Error with tunnel for {dev_name}: {e}")
|
|
864
|
+
sys.exit(1)
|
|
865
|
+
|
|
866
|
+
|
|
781
867
|
@cli.command()
|
|
782
868
|
@click.option('--all-projects', is_flag=True, help='List containers for all projects')
|
|
783
869
|
def list(all_projects: bool) -> None:
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import Optional
|
|
5
|
+
from typing import Dict, Optional
|
|
6
6
|
|
|
7
7
|
from devs_common.config import BaseConfig
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class Config(BaseConfig):
|
|
11
11
|
"""Configuration settings for devs CLI."""
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
# Default settings
|
|
14
14
|
PROJECT_PREFIX = "dev"
|
|
15
15
|
WORKSPACES_DIR = Path.home() / ".devs" / "workspaces"
|
|
@@ -17,6 +17,13 @@ class Config(BaseConfig):
|
|
|
17
17
|
CLAUDE_CONFIG_DIR = Path.home() / ".devs" / "claudeconfig"
|
|
18
18
|
CODEX_CONFIG_DIR = Path.home() / ".devs" / "codexconfig"
|
|
19
19
|
|
|
20
|
+
@property
|
|
21
|
+
def container_labels(self) -> Dict[str, str]:
|
|
22
|
+
"""Standard labels applied to containers created by CLI."""
|
|
23
|
+
labels = super().container_labels
|
|
24
|
+
labels["devs.source"] = "cli"
|
|
25
|
+
return labels
|
|
26
|
+
|
|
20
27
|
def __init__(self) -> None:
|
|
21
28
|
"""Initialize configuration with environment variable overrides."""
|
|
22
29
|
super().__init__()
|
|
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
|
|
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
|