Skip to content

Commit e8ab07e

Browse files
committed
1.0.9
1 parent 107e9c3 commit e8ab07e

60 files changed

Lines changed: 2806 additions & 894 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ RUN APKO_ARCH=$([ "$TARGETARCH" = "arm64" ] && echo "aarch64" || echo "x86_64")
4949
" - tzdata" \
5050
" - docker-cli" \
5151
" - docker-compose" \
52+
" - docker-cli-buildx" \
5253
" - sqlite" \
5354
" - git" \
5455
" - openssh-client" \
@@ -142,6 +143,7 @@ ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
142143
PGID=1001
143144

144145
# Create docker compose plugin symlink (we use `docker compose` syntax, Wolfi has standalone binary)
146+
# Note: docker-cli-buildx package already creates the buildx symlink
145147
RUN mkdir -p /usr/libexec/docker/cli-plugins \
146148
&& ln -s /usr/bin/docker-compose /usr/libexec/docker/cli-plugins/docker-compose
147149

package.json

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "dockhand",
33
"private": true,
4-
"version": "1.0.8",
4+
"version": "1.0.3",
55
"type": "module",
66
"scripts": {
77
"dev": "bunx --bun vite dev",
@@ -50,10 +50,10 @@
5050
"@codemirror/lang-xml": "6.1.0",
5151
"@codemirror/lang-yaml": "6.1.2",
5252
"@codemirror/language": "6.12.1",
53-
"@codemirror/search": "6.5.11",
54-
"@codemirror/state": "6.5.3",
53+
"@codemirror/search": "6.6.0",
54+
"@codemirror/state": "6.5.4",
5555
"@codemirror/theme-one-dark": "6.1.3",
56-
"@codemirror/view": "6.39.9",
56+
"@codemirror/view": "6.39.11",
5757
"@lezer/highlight": "1.2.3",
5858
"@lucide/lab": "^0.1.2",
5959
"codemirror": "6.0.2",
@@ -75,12 +75,12 @@
7575
"@layerstack/tailwind": "^1.0.1",
7676
"@lucide/svelte": "^0.562.0",
7777
"@playwright/test": "1.57.0",
78-
"@sveltejs/kit": "^2.49.3",
79-
"@sveltejs/vite-plugin-svelte": "^6.2.3",
78+
"@sveltejs/kit": "2.49.5",
79+
"@sveltejs/vite-plugin-svelte": "6.2.4",
8080
"@tailwindcss/vite": "^4.1.18",
81-
"@types/bun": "^1.3.5",
81+
"@types/bun": "1.3.6",
8282
"@types/js-yaml": "^4.0.9",
83-
"@types/nodemailer": "^7.0.4",
83+
"@types/nodemailer": "7.0.5",
8484
"@types/qrcode": "^1.5.6",
8585
"@xterm/addon-fit": "^0.11.0",
8686
"@xterm/addon-web-links": "^0.12.0",
@@ -96,7 +96,7 @@
9696
"lucide-svelte": "^0.562.0",
9797
"mode-watcher": "^1.1.0",
9898
"postcss": "^8.5.6",
99-
"svelte": "^5.46.1",
99+
"svelte": "5.46.4",
100100
"svelte-adapter-bun": "1.0.1",
101101
"svelte-check": "^4.3.5",
102102
"svelte-easy-crop": "^5.0.0",
@@ -109,9 +109,11 @@
109109
"vite": "^7.3.1"
110110
},
111111
"overrides": {
112-
"@codemirror/state": "6.5.3",
113-
"@codemirror/view": "6.39.9",
112+
"@codemirror/state": "6.5.4",
113+
"@codemirror/view": "6.39.11",
114114
"@codemirror/language": "6.12.1",
115+
"@codemirror/commands": "6.10.1",
116+
"@codemirror/search": "6.6.0",
115117
"@lezer/common": "1.5.0",
116118
"@lezer/highlight": "1.2.3"
117119
}

src/hooks.server.ts

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,34 @@ import { isAuthEnabled, validateSession } from '$lib/server/auth';
55
import { setServerStartTime } from '$lib/server/uptime';
66
import { checkLicenseExpiry, getHostname } from '$lib/server/license';
77
import { initCryptoFallback } from '$lib/server/crypto-fallback';
8+
import { detectHostDataDir } from '$lib/server/host-path';
9+
import { listContainers, removeContainer } from '$lib/server/docker';
10+
import { rmSync, readdirSync, existsSync } from 'fs';
11+
import { join } from 'path';
812
import type { HandleServerError, Handle } from '@sveltejs/kit';
913
import { redirect } from '@sveltejs/kit';
1014

15+
// Cleanup orphaned scanner version containers from previous runs
16+
async function cleanupOrphanedScannerContainers() {
17+
try {
18+
const containers = await listContainers(true);
19+
const orphaned = containers.filter(c =>
20+
c.name?.startsWith('dockhand-grype-version-') ||
21+
c.name?.startsWith('dockhand-trivy-version-')
22+
);
23+
for (const c of orphaned) {
24+
try {
25+
await removeContainer(c.id, true);
26+
} catch { /* ignore */ }
27+
}
28+
if (orphaned.length > 0) {
29+
console.log(`[Startup] Cleaned up ${orphaned.length} orphaned scanner containers`);
30+
}
31+
} catch (error) {
32+
// Silently ignore - Docker may not be available yet or no containers to clean
33+
}
34+
}
35+
1136
// License expiry check interval (24 hours)
1237
const LICENSE_CHECK_INTERVAL = 86400000;
1338

@@ -24,10 +49,46 @@ if (!initialized) {
2449
// Initialize crypto fallback first (detects old kernels and logs status)
2550
initCryptoFallback();
2651

52+
// Cleanup orphaned TLS temp directories from previous crashes
53+
const dataDir = process.env.DATA_DIR || './data';
54+
const tmpDir = join(dataDir, 'tmp');
55+
if (existsSync(tmpDir)) {
56+
try {
57+
const entries = readdirSync(tmpDir);
58+
for (const entry of entries) {
59+
if (entry.startsWith('tls-')) {
60+
const path = join(tmpDir, entry);
61+
try {
62+
rmSync(path, { recursive: true, force: true });
63+
console.log(`[Startup] Cleaned orphaned TLS temp dir: ${entry}`);
64+
} catch { /* ignore */ }
65+
}
66+
}
67+
} catch { /* ignore */ }
68+
}
69+
2770
setServerStartTime(); // Track when server started
2871
initDatabase();
2972
// Log hostname for license validation (set by entrypoint in Docker, or os.hostname() outside)
3073
console.log('Hostname for license validation:', getHostname());
74+
75+
// Detect host data directory for path translation
76+
// This allows Dockhand to translate container paths to host paths for compose volume mounts
77+
detectHostDataDir().then(hostPath => {
78+
if (hostPath) {
79+
console.log(`[Startup] Host data directory detected: ${hostPath}`);
80+
} else {
81+
console.warn('[Startup] Could not detect host data path.');
82+
console.warn('[Startup] Git stacks with relative volume paths may not work correctly.');
83+
console.warn('[Startup] Consider setting HOST_DATA_DIR or using matching volume paths (-v /app/data:/app/data)');
84+
}
85+
}).catch(err => {
86+
console.error('[Startup] Failed to detect host data directory:', err);
87+
});
88+
// Cleanup orphaned scanner containers from previous runs (non-blocking)
89+
cleanupOrphanedScannerContainers().catch(err => {
90+
console.error('Failed to cleanup orphaned scanner containers:', err);
91+
});
3192
// Start background subprocesses for metrics and event collection (isolated processes)
3293
startSubprocesses().catch(err => {
3394
console.error('Failed to start background subprocesses:', err);
@@ -174,4 +235,3 @@ export const handleError: HandleServerError = ({ error, event }) => {
174235
code: 'INTERNAL_ERROR'
175236
};
176237
};
177-
// CI trigger 1766327149

src/lib/components/host-info.svelte

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -316,13 +316,10 @@
316316
envAbortController = new AbortController();
317317
fetchHostInfo();
318318
fetchDiskUsage();
319-
const hostInterval = setInterval(fetchHostInfo, 30000);
320-
const diskInterval = setInterval(fetchDiskUsage, 30000);
319+
// No polling - only fetch on mount and environment switch
321320
document.addEventListener('click', handleClickOutside);
322321
return () => {
323322
abortPendingRequests(); // Abort on destroy
324-
clearInterval(hostInterval);
325-
clearInterval(diskInterval);
326323
document.removeEventListener('click', handleClickOutside);
327324
};
328325
});

src/lib/data/changelog.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,22 @@
11
[
2+
{
3+
"version": "1.0.9",
4+
"date": "2026-01-17",
5+
"changes": [
6+
{ "type": "feature", "text": "Shell: detect available shells in container before connecting" },
7+
{ "type": "fix", "text": "Fix GHCR registry authentication with OAuth2 token flow" },
8+
{ "type": "fix", "text": "Add page titles for browser tab updates on navigation" },
9+
{ "type": "fix", "text": "Add stack name conflict warning" },
10+
{ "type": "feature", "text": "Add docker-buildx plugin to container image" },
11+
{ "type": "fix", "text": "Fix relative paths not working for adopted/imported stacks" },
12+
{ "type": "fix", "text": "Fix TLS certificates not passed to docker-compose for direct connections" },
13+
{ "type": "fix", "text": "Fix registry queries for images with docker.io prefix" },
14+
{ "type": "fix", "text": "Fix compose editor issues when editing near env var references" },
15+
{ "type": "fix", "text": "Fix branch switching causing unknown revision error in git stacks" },
16+
{ "type": "fix", "text": "Fix SSE connection leak" }
17+
],
18+
"imageTag": "fnsys/dockhand:v1.0.9"
19+
},
220
{
321
"version": "1.0.8",
422
"date": "2026-01-13",

0 commit comments

Comments
 (0)