devs-common 5.0.1__tar.gz → 5.0.3__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-5.0.1 → devs_common-5.0.3}/PKG-INFO +1 -1
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/core/container.py +26 -1
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/Dockerfile +2 -3
- devs_common-5.0.3/devs_common/templates/extensions/devs-bridge-drop.vsix +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/scripts/post-create-wrapper.sh +11 -0
- devs_common-5.0.3/devs_common/templates/scripts/run-autoexec.sh +30 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/utils/devcontainer.py +24 -2
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/utils/docker_client.py +36 -6
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common.egg-info/PKG-INFO +1 -1
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common.egg-info/SOURCES.txt +1 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/pyproject.toml +1 -1
- devs_common-5.0.1/devs_common/templates/extensions/devs-bridge-drop.vsix +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/LICENSE +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/README.md +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/__init__.py +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/config.py +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/core/__init__.py +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/core/project.py +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/core/workspace.py +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/devs_config.py +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/exceptions.py +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/README-vscode-settings.md +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/devcontainer.json +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/extensions/README.md +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/extensions/install.sh +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/machine-settings.json +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/machine-settings.tmux.json +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/register-vscode-extensions.js +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/scripts/copy-ssh.sh +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/scripts/install-bridge-drop.sh +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/scripts/post-start.sh +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/scripts/python-venv-integration.sh +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/scripts/screenshot-webapp.sh +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/scripts/setup-vscode-settings.sh +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/scripts/setup-workspace.sh +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/scripts/start-tailscale.sh +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/scripts/start-tunnel.sh +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/scripts/ts.sh +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/scripts/tunnel-status.sh +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/scripts/webapp-screenshot.py +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/sudo-scripts/init-firewall.sh +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/sudo-scripts/setup-devs-env.sh +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/sudo-scripts/setup-magicdns.sh +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/sudo-scripts/setup-vscode-cache.sh +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/sudo-scripts/start-services.sh +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/sudo-scripts/start-tailscaled.sh +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/sudo-scripts/ts-cli.sh +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/vscode-settings-reference.md +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/utils/__init__.py +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/utils/config_hash.py +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/utils/console.py +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/utils/devcontainer_template.py +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/utils/file_utils.py +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/utils/git_utils.py +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common/utils/repo_cache.py +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common.egg-info/dependency_links.txt +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common.egg-info/requires.txt +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/devs_common.egg-info/top_level.txt +0 -0
- {devs_common-5.0.1 → devs_common-5.0.3}/setup.cfg +0 -0
|
@@ -433,9 +433,34 @@ class ContainerManager:
|
|
|
433
433
|
tailscaled and the tailnet node stay down, and VS Code settings aren't
|
|
434
434
|
re-deployed. The script is idempotent, so running it again is harmless. Never
|
|
435
435
|
raises: a container without the devs template simply has no such script.
|
|
436
|
+
|
|
437
|
+
The hook's identity env (``DEVS_PROJECT_NAME``/``DEVCONTAINER_NAME``) comes from
|
|
438
|
+
devcontainer.json ``remoteEnv``, which only the devcontainer CLI injects — a raw
|
|
439
|
+
exec sees neither. Without them start-tailscale.sh falls through to its
|
|
440
|
+
``devcontainer`` default and the node rejoins the tailnet as ``devs-devcontainer``
|
|
441
|
+
(then clash-suffixed ``-1``, ``-2``…) instead of ``devs-<project>-<dev>`` — so
|
|
442
|
+
every name anyone SSHes to breaks on each host reboot. Re-derive them from the
|
|
443
|
+
labels set at creation, which are the container's own record of that identity.
|
|
436
444
|
"""
|
|
445
|
+
environment = {}
|
|
446
|
+
try:
|
|
447
|
+
labels = self.docker.get_container_labels(container_name)
|
|
448
|
+
project = labels.get("devs.project", "")
|
|
449
|
+
dev = labels.get("devs.dev", "")
|
|
450
|
+
if project and dev:
|
|
451
|
+
environment = {
|
|
452
|
+
"DEVS_PROJECT_NAME": project,
|
|
453
|
+
"DEVCONTAINER_NAME": dev,
|
|
454
|
+
}
|
|
455
|
+
except Exception:
|
|
456
|
+
pass # fall back to the hook's own defaults
|
|
457
|
+
|
|
437
458
|
try:
|
|
438
|
-
self.docker.exec_command(
|
|
459
|
+
self.docker.exec_command(
|
|
460
|
+
container_name,
|
|
461
|
+
"/usr/local/bin/post-start.sh",
|
|
462
|
+
environment=environment or None,
|
|
463
|
+
)
|
|
439
464
|
except Exception:
|
|
440
465
|
pass # not a devs-template container / exec unavailable
|
|
441
466
|
|
|
@@ -186,8 +186,8 @@ RUN for shell_rc in /home/node/.zshrc /home/node/.bashrc; do \
|
|
|
186
186
|
echo "export CODEX_CONFIG_HOME=\"/home/node/codexconfig\"" >> "$shell_rc" && \
|
|
187
187
|
echo "export PATH=\"/home/node/.local/bin:\$PATH\"" >> "$shell_rc" && \
|
|
188
188
|
echo "alias claude=\"claude --dangerously-skip-permissions\"" >> "$shell_rc" && \
|
|
189
|
-
echo "alias codex=\"/usr/local/share/npm-global/bin/codex --dangerously-bypass-approvals-and-sandbox\"" >> "$shell_rc" && \
|
|
190
|
-
echo "alias codex-normal=\"/usr/local/share/npm-global/bin/codex\"" >> "$shell_rc" && \
|
|
189
|
+
echo "alias codex=\"/usr/local/share/npm-global/bin/codex -c check_for_update_on_startup=false --dangerously-bypass-approvals-and-sandbox\"" >> "$shell_rc" && \
|
|
190
|
+
echo "alias codex-normal=\"/usr/local/share/npm-global/bin/codex -c check_for_update_on_startup=false\"" >> "$shell_rc" && \
|
|
191
191
|
echo "" >> "$shell_rc" && \
|
|
192
192
|
echo "# Auto-activate Python venv if it exists" >> "$shell_rc" && \
|
|
193
193
|
echo "if [ -f /home/node/.devs-venv/workspace-venv/bin/activate ]; then" >> "$shell_rc" && \
|
|
@@ -234,4 +234,3 @@ RUN echo "DEBUG: Files that need sudo:" && ls -la /tmp/sudo-scripts-list/ && \
|
|
|
234
234
|
rm -rf /tmp/sudo-scripts-list
|
|
235
235
|
|
|
236
236
|
USER node
|
|
237
|
-
|
|
Binary file
|
{devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/scripts/post-create-wrapper.sh
RENAMED
|
@@ -34,12 +34,23 @@ run_step() {
|
|
|
34
34
|
# Run each step with error handling
|
|
35
35
|
run_step "setup-vscode-cache" "sudo /usr/local/bin/setup-vscode-cache.sh"
|
|
36
36
|
run_step "setup-devs-env.sh" "/usr/local/bin/setup-devs-env.sh"
|
|
37
|
+
run_step "run-autoexec.sh" "/usr/local/bin/run-autoexec.sh"
|
|
37
38
|
#run_step "init-firewall.sh" "sudo /usr/local/bin/init-firewall.sh"
|
|
38
39
|
run_step "setup-workspace.sh" "/usr/local/bin/setup-workspace.sh"
|
|
39
40
|
run_step "start-services.sh" "sudo /usr/local/bin/start-services.sh"
|
|
40
41
|
# Optional: join the tailnet + serve a port. Non-fatal — no auth key => no-op.
|
|
41
42
|
run_step "start-tailscale.sh" "/usr/local/bin/start-tailscale.sh" || true
|
|
42
43
|
|
|
44
|
+
# setup-devs-env.sh runs through run_step in a subshell, so variables it exports
|
|
45
|
+
# do not reach this wrapper. Load the mounted environment here as well so GH_TOKEN
|
|
46
|
+
# is available while gh configures git's credential helper.
|
|
47
|
+
if [ -f /home/node/.devs-env/.env ]; then
|
|
48
|
+
set -a
|
|
49
|
+
# shellcheck disable=SC1091 -- this file is supplied by the devs bind mount
|
|
50
|
+
source /home/node/.devs-env/.env
|
|
51
|
+
set +a
|
|
52
|
+
fi
|
|
53
|
+
|
|
43
54
|
# GitHub auth setup is optional, so handle it separately
|
|
44
55
|
echo "📋 Running gh auth setup-git..."
|
|
45
56
|
if output=$(gh auth setup-git 2>&1); then
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Run optional, user-supplied startup hooks from the mounted devs environment.
|
|
3
|
+
# The directory's presence is the opt-in; hooks run in lexical filename order.
|
|
4
|
+
set -uo pipefail
|
|
5
|
+
|
|
6
|
+
hooks_dir="${DEVS_AUTOEXEC_DIR:-/home/node/.devs-env/autoexec}"
|
|
7
|
+
[ -d "$hooks_dir" ] || exit 0
|
|
8
|
+
|
|
9
|
+
status=0
|
|
10
|
+
found=0
|
|
11
|
+
for hook in "$hooks_dir"/*; do
|
|
12
|
+
[ -f "$hook" ] || continue
|
|
13
|
+
[ -x "$hook" ] || {
|
|
14
|
+
echo "ℹ️ Skipping non-executable autoexec hook: $(basename "$hook")"
|
|
15
|
+
continue
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
found=1
|
|
19
|
+
echo "📋 Running autoexec hook: $(basename "$hook")"
|
|
20
|
+
if "$hook"; then
|
|
21
|
+
echo "✅ Autoexec hook completed: $(basename "$hook")"
|
|
22
|
+
else
|
|
23
|
+
hook_status=$?
|
|
24
|
+
echo "⚠️ Autoexec hook failed ($hook_status): $(basename "$hook")"
|
|
25
|
+
status=1
|
|
26
|
+
fi
|
|
27
|
+
done
|
|
28
|
+
|
|
29
|
+
[ "$found" -eq 0 ] || echo "🏁 Autoexec hooks finished"
|
|
30
|
+
exit "$status"
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"""DevContainer CLI wrapper utilities."""
|
|
2
2
|
|
|
3
|
+
import json
|
|
3
4
|
import os
|
|
4
5
|
import re
|
|
6
|
+
import socket
|
|
5
7
|
import sys
|
|
6
8
|
import subprocess
|
|
7
9
|
from pathlib import Path
|
|
@@ -44,8 +46,8 @@ def prepare_devcontainer_environment(
|
|
|
44
46
|
env = os.environ.copy()
|
|
45
47
|
|
|
46
48
|
# Core devcontainer environment variables
|
|
47
|
-
# IMPORTANT: In live mode, we must use the actual host folder name (e.g. "
|
|
48
|
-
# instead of our constructed name (e.g. "
|
|
49
|
+
# IMPORTANT: In live mode, we must use the actual host folder name (e.g. "devs")
|
|
50
|
+
# instead of our constructed name (e.g. "ideonate-devs-sally") because
|
|
49
51
|
# the devcontainer CLI directly mounts the host folder and preserves its name.
|
|
50
52
|
# The container will have /workspaces/<host-folder-name>, not /workspaces/<constructed-name>
|
|
51
53
|
workspace_folder_name = workspace_folder.name if live else container_workspace_name
|
|
@@ -80,6 +82,7 @@ def prepare_devcontainer_environment(
|
|
|
80
82
|
bridge_mount_path = Path.home() / '.devs' / 'bridge' / f"{project_name}-{dev_name}"
|
|
81
83
|
bridge_mount_path.mkdir(parents=True, exist_ok=True)
|
|
82
84
|
env['DEVS_BRIDGE_MOUNT_PATH'] = str(bridge_mount_path)
|
|
85
|
+
write_bridge_info(bridge_mount_path)
|
|
83
86
|
|
|
84
87
|
# Pass debug mode to container scripts
|
|
85
88
|
if debug:
|
|
@@ -104,6 +107,25 @@ def prepare_devcontainer_environment(
|
|
|
104
107
|
return env
|
|
105
108
|
|
|
106
109
|
|
|
110
|
+
BRIDGE_INFO_FILENAME = '.devs-bridge.json'
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def write_bridge_info(bridge_mount_path: Path) -> None:
|
|
114
|
+
"""Record the bridge's host-side location inside the bridge itself.
|
|
115
|
+
|
|
116
|
+
The bridge-drop extension shows the host path for each dropped file. It
|
|
117
|
+
reads DEVS_BRIDGE_MOUNT_PATH when set, but that arrives via remoteEnv, which
|
|
118
|
+
only the Dev Containers extension applies — a Remote-SSH session straight
|
|
119
|
+
into the container never sees it. The bridge dir is mounted in the
|
|
120
|
+
container regardless of how VS Code connects, so the info lives there too.
|
|
121
|
+
"""
|
|
122
|
+
info = {'host_path': str(bridge_mount_path), 'hostname': socket.gethostname()}
|
|
123
|
+
try:
|
|
124
|
+
(bridge_mount_path / BRIDGE_INFO_FILENAME).write_text(json.dumps(info, indent=2) + '\n')
|
|
125
|
+
except OSError as e:
|
|
126
|
+
console.print(f"[yellow]Warning: could not write bridge info: {e}[/yellow]")
|
|
127
|
+
|
|
128
|
+
|
|
107
129
|
def parse_docker_error(error_output: str) -> Tuple[Optional[str], Optional[str]]:
|
|
108
130
|
"""Parse Docker error output for specific error patterns.
|
|
109
131
|
|
|
@@ -170,6 +170,25 @@ class DockerClient:
|
|
|
170
170
|
except DockerException as e:
|
|
171
171
|
raise DockerError(f"Error finding containers by labels: {e}")
|
|
172
172
|
|
|
173
|
+
def get_container_labels(self, name: str) -> Dict[str, str]:
|
|
174
|
+
"""Get a single container's labels.
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
name: Container name or id
|
|
178
|
+
|
|
179
|
+
Returns:
|
|
180
|
+
The container's label dictionary
|
|
181
|
+
|
|
182
|
+
Raises:
|
|
183
|
+
DockerError: If the container is missing or inspection fails
|
|
184
|
+
"""
|
|
185
|
+
try:
|
|
186
|
+
return self.client.containers.get(name).labels or {}
|
|
187
|
+
except NotFound:
|
|
188
|
+
raise DockerError(f"Container {name} not found")
|
|
189
|
+
except DockerException as e:
|
|
190
|
+
raise DockerError(f"Error inspecting container {name}: {e}")
|
|
191
|
+
|
|
173
192
|
def rename_container(self, old_name: str, new_name: str) -> None:
|
|
174
193
|
"""Rename a container.
|
|
175
194
|
|
|
@@ -188,26 +207,37 @@ class DockerClient:
|
|
|
188
207
|
except DockerException as e:
|
|
189
208
|
raise DockerError(f"Error renaming container {old_name} to {new_name}: {e}")
|
|
190
209
|
|
|
191
|
-
def exec_command(
|
|
210
|
+
def exec_command(
|
|
211
|
+
self,
|
|
212
|
+
container_name: str,
|
|
213
|
+
command: str,
|
|
214
|
+
workdir: Optional[str] = None,
|
|
215
|
+
environment: Optional[Dict[str, str]] = None,
|
|
216
|
+
) -> bool:
|
|
192
217
|
"""Execute a command in a container.
|
|
193
|
-
|
|
218
|
+
|
|
194
219
|
Args:
|
|
195
220
|
container_name: Container name
|
|
196
221
|
command: Command to execute
|
|
197
222
|
workdir: Working directory for command
|
|
198
|
-
|
|
223
|
+
environment: Extra env vars for this exec only. A raw exec inherits the
|
|
224
|
+
image's baked-in env but NOT devcontainer.json ``remoteEnv``, which the
|
|
225
|
+
devcontainer CLI injects per-exec — pass anything the command needs from
|
|
226
|
+
there explicitly.
|
|
227
|
+
|
|
199
228
|
Returns:
|
|
200
229
|
True if command succeeded
|
|
201
|
-
|
|
230
|
+
|
|
202
231
|
Raises:
|
|
203
232
|
DockerError: If execution fails
|
|
204
233
|
"""
|
|
205
234
|
try:
|
|
206
235
|
container = self.client.containers.get(container_name)
|
|
207
|
-
|
|
236
|
+
|
|
208
237
|
exec_result = container.exec_run(
|
|
209
|
-
command,
|
|
238
|
+
command,
|
|
210
239
|
workdir=workdir,
|
|
240
|
+
environment=environment,
|
|
211
241
|
tty=False,
|
|
212
242
|
stream=False
|
|
213
243
|
)
|
|
@@ -29,6 +29,7 @@ devs_common/templates/scripts/install-bridge-drop.sh
|
|
|
29
29
|
devs_common/templates/scripts/post-create-wrapper.sh
|
|
30
30
|
devs_common/templates/scripts/post-start.sh
|
|
31
31
|
devs_common/templates/scripts/python-venv-integration.sh
|
|
32
|
+
devs_common/templates/scripts/run-autoexec.sh
|
|
32
33
|
devs_common/templates/scripts/screenshot-webapp.sh
|
|
33
34
|
devs_common/templates/scripts/setup-vscode-settings.sh
|
|
34
35
|
devs_common/templates/scripts/setup-workspace.sh
|
|
Binary file
|
|
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
|
{devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/scripts/install-bridge-drop.sh
RENAMED
|
File without changes
|
|
File without changes
|
{devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/scripts/python-venv-integration.sh
RENAMED
|
File without changes
|
|
File without changes
|
{devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/scripts/setup-vscode-settings.sh
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
|
{devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/sudo-scripts/setup-devs-env.sh
RENAMED
|
File without changes
|
{devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/sudo-scripts/setup-magicdns.sh
RENAMED
|
File without changes
|
{devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/sudo-scripts/setup-vscode-cache.sh
RENAMED
|
File without changes
|
{devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/sudo-scripts/start-services.sh
RENAMED
|
File without changes
|
{devs_common-5.0.1 → devs_common-5.0.3}/devs_common/templates/sudo-scripts/start-tailscaled.sh
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
|