Skip to content

Commit 82de5f8

Browse files
committed
CH-216 dev container tweaks
1 parent 2b6b3e6 commit 82de5f8

File tree

6 files changed

+326
-87
lines changed

6 files changed

+326
-87
lines changed

.devcontainer/dev-scripts/post-create.sh

Lines changed: 157 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ else
3030
echo '{}' > /root/.docker-container/config.json
3131
fi
3232

33+
# Download bash-preexec if it doesn't exist (required for atuin/starship)
34+
if [ ! -f ~/.bash-preexec.sh ]; then
35+
echo "Downloading bash-preexec..."
36+
curl -sL https://raw.githubusercontent.com/rcaloras/bash-preexec/master/bash-preexec.sh -o ~/.bash-preexec.sh
37+
fi
38+
3339
# Initialize bashrc if needed
3440
if [ ! -f ~/.bashrc ] || [ ! -s ~/.bashrc ] || ! grep -q 'common-bashrc' ~/.bashrc; then
3541
echo "Initializing ~/.bashrc..."
@@ -59,11 +65,13 @@ if [ -n "$DOCKER_SOCKET_PROXY" ]; then
5965
fi
6066
6167
# Source common bash configuration (aliases and functions)
62-
source /workspace/dev-scripts/common-bashrc.sh
68+
if [ -f /usr/local/share/dev-scripts/common-bashrc.sh ]; then
69+
source /usr/local/share/dev-scripts/common-bashrc.sh
70+
fi
6371
6472
# Source the virtual environment (must use source, not bash)
65-
if [ -f /workspace/dev-scripts/use-venv ]; then
66-
source /workspace/dev-scripts/use-venv
73+
if [ -f /usr/local/share/dev-scripts/use-venv ]; then
74+
source /usr/local/share/dev-scripts/use-venv
6775
fi
6876
6977
# Load bash-preexec (required for atuin and starship to work with VS Code)
@@ -84,19 +92,26 @@ if command -v starship &> /dev/null; then
8492
eval "$(starship init bash)"
8593
fi
8694
87-
# Fix for VS Code shell integration overriding PROMPT_COMMAND
88-
# Ensure bash-preexec hooks are called so atuin and starship work
89-
if declare -F __bp_precmd_invoke_cmd &>/dev/null; then
90-
# Prepend bash-preexec to PROMPT_COMMAND if not already there
91-
if [[ "$PROMPT_COMMAND" != *"__bp_precmd_invoke_cmd"* ]]; then
92-
PROMPT_COMMAND="__bp_precmd_invoke_cmd; $PROMPT_COMMAND"
95+
# Fix for VS Code shell integration overriding bash-preexec's DEBUG trap
96+
# VS Code loads its shell integration after bashrc, so we restore the trap on each prompt
97+
__restore_bash_preexec_trap() {
98+
if declare -F __bp_preexec_invoke_exec &>/dev/null; then
99+
local current_trap=\$(trap -p DEBUG)
100+
if [[ "\$current_trap" != *"__bp_preexec_invoke_exec"* ]]; then
101+
trap '__bp_preexec_invoke_exec "\$_"' DEBUG
102+
fi
93103
fi
104+
}
105+
106+
# Add the trap restoration to PROMPT_COMMAND
107+
if [[ "\$PROMPT_COMMAND" != *"__restore_bash_preexec_trap"* ]]; then
108+
PROMPT_COMMAND="__restore_bash_preexec_trap\${PROMPT_COMMAND:+; \$PROMPT_COMMAND}"
94109
fi
95110
96111
# asdf version manager
97-
if [ -f "$HOME/.asdf/asdf.sh" ]; then
98-
. "$HOME/.asdf/asdf.sh"
99-
. "$HOME/.asdf/completions/asdf.bash"
112+
if [ -f "\$HOME/.asdf/asdf.sh" ]; then
113+
. "\$HOME/.asdf/asdf.sh"
114+
. "\$HOME/.asdf/completions/asdf.bash"
100115
fi
101116
EOF
102117
fi
@@ -108,8 +123,9 @@ if command -v atuin &> /dev/null; then
108123
# Create atuin data directory if it doesn't exist
109124
mkdir -p ~/.local/share/atuin ~/.config/atuin
110125

111-
# Generate default config with explicit paths
112-
cat > ~/.config/atuin/config.toml << 'ATUINCONF'
126+
# Generate default config with explicit paths (only if it doesn't exist)
127+
if [ ! -f ~/.config/atuin/config.toml ]; then
128+
cat > ~/.config/atuin/config.toml << 'ATUINCONF'
113129
## Atuin configuration for CloudHarness dev container
114130
115131
## Explicitly set paths to avoid VS Code XDG_DATA_HOME issues
@@ -132,6 +148,7 @@ secrets_filter = true
132148
enter_accept = true
133149
history_filter = ["^secret", "^password", "AWS_SECRET", "KUBECONFIG"]
134150
ATUINCONF
151+
fi
135152

136153
# Import existing bash history
137154
if [ -f ~/.bash_history ]; then
@@ -140,6 +157,132 @@ ATUINCONF
140157
fi
141158
fi
142159

160+
# Create Starship config if it doesn't exist
161+
if [ ! -f ~/.config/starship.toml ]; then
162+
echo "Creating Starship prompt configuration..."
163+
mkdir -p ~/.config
164+
cat > ~/.config/starship.toml << 'STARSHIPCONF'
165+
# Starship prompt configuration for CloudHarness dev container
166+
# Documentation: https://starship.rs/config/
167+
168+
# Timeout for starship to run (in milliseconds)
169+
command_timeout = 1000
170+
171+
# Add a new line before the prompt
172+
add_newline = true
173+
174+
# Format of the prompt
175+
format = """
176+
[╭─](bold green)$username\
177+
$hostname\
178+
$directory\
179+
$git_branch\
180+
$git_status\
181+
$python\
182+
$nodejs\
183+
$docker_context\
184+
$kubernetes
185+
[╰─](bold green)$character"""
186+
187+
[character]
188+
success_symbol = "[➜](bold green)"
189+
error_symbol = "[✗](bold red)"
190+
191+
[username]
192+
style_user = "bold yellow"
193+
style_root = "bold red"
194+
format = "[$user]($style) "
195+
disabled = false
196+
show_always = true
197+
198+
[hostname]
199+
ssh_only = false
200+
format = "[@$hostname](bold blue) "
201+
disabled = false
202+
203+
[directory]
204+
truncation_length = 3
205+
truncate_to_repo = true
206+
format = "[$path]($style)[$read_only]($read_only_style) "
207+
style = "bold cyan"
208+
read_only = " 🔒"
209+
210+
[git_branch]
211+
symbol = " "
212+
format = "on [$symbol$branch]($style) "
213+
style = "bold purple"
214+
215+
[git_status]
216+
format = '([\[$all_status$ahead_behind\]]($style) )'
217+
style = "bold red"
218+
conflicted = "🏳"
219+
ahead = "⇡${count}"
220+
behind = "⇣${count}"
221+
diverged = "⇕⇡${ahead_count}⇣${behind_count}"
222+
untracked = "?${count}"
223+
stashed = "$${count}"
224+
modified = "!${count}"
225+
staged = "+${count}"
226+
renamed = "»${count}"
227+
deleted = "✘${count}"
228+
229+
[python]
230+
symbol = " "
231+
format = 'via [${symbol}${pyenv_prefix}(${version} )(\($virtualenv\) )]($style)'
232+
style = "yellow"
233+
pyenv_version_name = false
234+
detect_extensions = ["py"]
235+
detect_files = [".python-version", "Pipfile", "__pycache__", "pyproject.toml", "requirements.txt", "setup.py", "tox.ini"]
236+
detect_folders = []
237+
238+
[nodejs]
239+
symbol = " "
240+
format = "via [$symbol($version )]($style)"
241+
style = "bold green"
242+
243+
[docker_context]
244+
symbol = " "
245+
format = "via [$symbol$context]($style) "
246+
style = "blue bold"
247+
only_with_files = true
248+
detect_files = ["docker-compose.yml", "docker-compose.yaml", "Dockerfile"]
249+
detect_folders = []
250+
251+
[kubernetes]
252+
symbol = "☸ "
253+
format = 'on [$symbol$context( \($namespace\))]($style) '
254+
style = "cyan bold"
255+
disabled = false
256+
detect_files = ["k8s"]
257+
detect_folders = ["k8s"]
258+
259+
[kubernetes.context_aliases]
260+
"docker-desktop" = "🐳 desktop"
261+
"kind-.*" = "kind"
262+
"minikube" = "mini"
263+
264+
[cmd_duration]
265+
min_time = 500
266+
format = "took [$duration](bold yellow) "
267+
268+
[time]
269+
disabled = false
270+
format = '🕙[\[ $time \]]($style) '
271+
time_format = "%T"
272+
style = "bold white"
273+
274+
[memory_usage]
275+
disabled = true
276+
threshold = -1
277+
symbol = " "
278+
format = "via $symbol[${ram_pct}]($style) "
279+
style = "bold dimmed white"
280+
281+
[package]
282+
disabled = true
283+
STARSHIPCONF
284+
fi
285+
143286
# Create tmux config if it doesn't exist
144287
if [ ! -f ~/.tmux.conf ]; then
145288
cat > ~/.tmux.conf << 'EOF'

.devcontainer/docker-compose.yml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ services:
66
docker-socket-proxy:
77
image: tecnativa/docker-socket-proxy:latest
88
container_name: cloudharness-docker-proxy
9-
restart: unless-stopped
9+
restart: "no"
1010
privileged: false
1111
environment:
1212
# Disable all by default
@@ -64,6 +64,7 @@ services:
6464
- devcontainer
6565
ports:
6666
# Expose on localhost only for security
67+
# If port is already in use, container will exit silently (restart: no)
6768
- "127.0.0.1:2375:2375"
6869

6970
# Dev container - connects through the proxy
@@ -75,6 +76,11 @@ services:
7576
container_name: cloudharness-dev
7677
user: root
7778
network_mode: host
79+
# Don't fail if proxy isn't running (may already be running from another devcontainer)
80+
depends_on:
81+
docker-socket-proxy:
82+
condition: service_started
83+
required: false
7884
environment:
7985
PYTHONPATH: "/cloudharness:/workspace/libraries/models:/workspace/libraries/cloudharness-utils:/workspace/libraries/cloudharness-common:/workspace/libraries/client/cloudharness_cli:/workspace/tools/deployment-cli-tools"
8086
# Point docker client to the proxy on localhost
@@ -93,8 +99,6 @@ services:
9399
- vscode-server:/root/.vscode-server
94100
- vscode-server-insiders:/root/.vscode-server-insiders
95101
command: sleep infinity
96-
depends_on:
97-
- docker-socket-proxy
98102

99103
networks:
100104
devcontainer:

.devcontainer/vscode/launch.json

Lines changed: 1 addition & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -137,50 +137,7 @@
137137
},
138138
{
139139
"cleanUp": false,
140-
"debug": [
141-
{
142-
"image": "cloud-harness/workflows:1",
143-
"sourceFileMap": {
144-
"${workspaceFolder}/applications/workflows/server": "/usr/src/app",
145-
"justMyCode": false
146-
}
147-
},
148-
{
149-
"image": "cloud-harness/jupyterhub:1",
150-
"sourceFileMap": {
151-
"${workspaceFolder}/applications/jupyterhub/src/harness_jupyter": "/usr/src/app",
152-
"justMyCode": false
153-
}
154-
},
155-
{
156-
"image": "cloud-harness/jupyterhub:1",
157-
"sourceFileMap": {
158-
"${workspaceFolder}/applications/jupyterhub/src/chauthenticator": "/usr/src/app",
159-
"justMyCode": false
160-
}
161-
},
162-
{
163-
"image": "cloud-harness/common:1",
164-
"sourceFileMap": {
165-
"${workspaceFolder}/applications/common/server": "/usr/src/app",
166-
"justMyCode": false
167-
}
168-
},
169-
{
170-
"image": "cloud-harness/volumemanager:1",
171-
"sourceFileMap": {
172-
"${workspaceFolder}/applications/volumemanager/server": "/usr/src/app",
173-
"justMyCode": false
174-
}
175-
},
176-
{
177-
"image": "cloud-harness/samples:1",
178-
"sourceFileMap": {
179-
"${workspaceFolder}/applications/samples/backend": "/usr/src/app",
180-
"justMyCode": false
181-
}
182-
}
183-
],
140+
"debug": [],
184141
"imageRegistry": "localhost:5000",
185142
"name": "CloudHarness: Run/Debug",
186143
"portForward": true,

blueprint/.devcontainer/devcontainer.json

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,28 @@
11
{
22
"name": "My Project Development",
3-
"build": {
4-
"context": "..",
5-
"dockerfile": "./Dockerfile"
6-
},
3+
4+
5+
"dockerComposeFile": "docker-compose.yml",
6+
"service": "app",
77
"workspaceFolder": "/workspace",
88
"shutdownAction": "none",
9-
"runArgs": [
10-
"--name=myproject-dev",
11-
"--user=root",
12-
"--network=host"
13-
],
14-
"containerEnv": {
15-
"PYTHONPATH": "/cloudharness:/workspace/cloud-harness/libraries/models:/workspace/cloud-harness/libraries/cloudharness-utils:/workspace/cloud-harness/libraries/cloudharness-common:/workspace/cloud-harness/libraries/client/cloudharness_cli:/workspace/tools/deployment-cli-tools",
16-
"DOCKER_HOST": "unix:///var/run/docker.sock",
17-
"KUBECONFIG": "/root/.kube-container/config"
18-
},
19-
"mounts": [
20-
"source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached",
21-
"source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind",
22-
"source=${localEnv:HOME}${localEnv:USERPROFILE}/.docker,target=/root/.docker,type=bind,readonly",
23-
"source=${localEnv:HOME}${localEnv:USERPROFILE}/.kube,target=/root/.kube,type=bind,readonly",
24-
"source=${localWorkspaceFolder}/.devcontainer/home,target=/root,type=bind",
25-
"source=${localWorkspaceFolder}/.devcontainer/vscode,target=/workspace/.vscode,type=bind"
26-
],
279
"forwardPorts": [3000, 5000, 8000, 8100, 9000, 9100, 9200],
28-
"postCreateCommand": "bash /workspace/.devcontainer/post-create.sh",
10+
"postCreateCommand": "bash /usr/local/share/dev-scripts/post-create.sh",
11+
"features": {
12+
"ghcr.io/devcontainers/features/github-cli:1": {}
13+
},
2914
"customizations": {
3015
"vscode": {
3116
"settings": {
3217
"terminal.integrated.defaultProfile.linux": "bash",
3318
"python.defaultInterpreterPath": "/root/.local/venv/bin/python",
3419
"python.terminal.activateEnvironment": true,
3520
"python.terminal.activateEnvInCurrentTerminal": true,
36-
"terminal.integrated.shellIntegration.enabled": true,
21+
// Disable VS Code shell integration - conflicts with bash-preexec (required for atuin/starship)
22+
"terminal.integrated.shellIntegration.enabled": false,
23+
"terminal.integrated.env.linux": {
24+
"XDG_DATA_HOME": "${env:HOME}/.local/share"
25+
},
3726
"extensions.autoUpdate": false,
3827
"extensions.autoCheckUpdates": false,
3928
"python.analysis.extraPaths": [
@@ -43,7 +32,22 @@
4332
"/workspace/cloud-harness/libraries/cloudharness-common",
4433
"/workspace/cloud-harness/libraries/client/cloudharness_cli",
4534
"/workspace/tools/deployment-cli-tools"
46-
]
35+
],
36+
"github.copilot.enable": {
37+
"*": true,
38+
"yaml": true,
39+
"plaintext": true,
40+
"markdown": true,
41+
"python": true,
42+
"javascript": true,
43+
"typescript": true,
44+
"json": true,
45+
"jsonc": true
46+
},
47+
"remote.extensionKind": {
48+
"GitHub.copilot": ["ui"],
49+
"GitHub.copilot-chat": ["ui"]
50+
}
4751
},
4852
"extensions": [
4953
"ms-python.python",
@@ -52,7 +56,6 @@
5256
"ms-python.python-extension-pack",
5357
"KevinRose.vsc-python-indent",
5458
"dbaeumer.vscode-eslint",
55-
"github.copilot",
5659
"redhat.vscode-yaml",
5760
"ms-vscode.vscode-json",
5861
"ms-kubernetes-tools.vscode-kubernetes-tools"

0 commit comments

Comments
 (0)