Skip to content

Commit 9c8e4a9

Browse files
anubissbeclaude
andcommitted
fix: Simplify update checker to avoid CORS issues
- Replace complex Docker Hub API check with simple UI - Add direct link to Docker Hub tags page - Keep copy-to-clipboard functionality - Show current version clearly - Add backend proxy endpoint for future use The simpler approach avoids CORS issues when checking for updates from the browser context. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 4a10198 commit 9c8e4a9

File tree

4 files changed

+156
-6
lines changed

4 files changed

+156
-6
lines changed

backend/main.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@ func main() {
177177
router.POST("/dashboard/systeminfo", getDashboardSystemInfo)
178178
router.POST("/dashboard/events", getDashboardEvents)
179179

180+
// Update checker endpoint
181+
router.GET("/updates/check", checkForUpdates)
182+
180183
// MCP endpoints
181184
router.GET("/mcp/predefined", getPredefinedMCPServers)
182185
router.GET("/mcp/catalog", getMCPCatalog)
@@ -748,6 +751,31 @@ func getDashboardEvents(ctx echo.Context) error {
748751
return ctx.JSON(http.StatusOK, EventsResponse{Events: events})
749752
}
750753

754+
// Check for updates by proxying to Docker Hub API
755+
func checkForUpdates(ctx echo.Context) error {
756+
// Proxy request to Docker Hub to avoid CORS issues
757+
resp, err := http.Get("https://hub.docker.com/v2/repositories/telkombe/remote-docker/tags/?page_size=50&ordering=-last_updated")
758+
if err != nil {
759+
logger.Errorf("Failed to check Docker Hub for updates: %v", err)
760+
return ctx.JSON(http.StatusInternalServerError, map[string]string{
761+
"error": "Failed to check for updates",
762+
})
763+
}
764+
defer resp.Body.Close()
765+
766+
// Read response body
767+
body, err := ioutil.ReadAll(resp.Body)
768+
if err != nil {
769+
logger.Errorf("Failed to read Docker Hub response: %v", err)
770+
return ctx.JSON(http.StatusInternalServerError, map[string]string{
771+
"error": "Failed to read update information",
772+
})
773+
}
774+
775+
// Return the raw response from Docker Hub
776+
return ctx.String(http.StatusOK, string(body))
777+
}
778+
751779
// Request for container logs
752780
type ContainerLogsRequest struct {
753781
Hostname string `json:"hostname"`

ui/src/components/UpdateChecker.tsx

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,35 @@ const UpdateChecker: React.FC = () => {
4949

5050
try {
5151
// Check Docker Hub for latest version
52-
const response = await fetch('https://hub.docker.com/v2/repositories/telkombe/remote-docker/tags/?page_size=10&ordering=-last_updated');
53-
const data = await response.json();
52+
// Use backend proxy to avoid CORS issues
53+
const response = await ddClient.extension?.vm?.service?.get('/updates/check');
5454

55-
if (!data.results || data.results.length === 0) {
55+
console.log('Update check response:', response);
56+
57+
// Handle wrapped response
58+
let data = response;
59+
if (response && typeof response === 'object' && 'data' in response) {
60+
data = response.data;
61+
}
62+
63+
// Parse if string
64+
if (typeof data === 'string') {
65+
try {
66+
data = JSON.parse(data);
67+
} catch (e) {
68+
throw new Error('Invalid response format');
69+
}
70+
}
71+
72+
// Type assertion after validation
73+
const dockerHubResponse = data as { results?: any[] };
74+
75+
if (!dockerHubResponse.results || dockerHubResponse.results.length === 0) {
5676
throw new Error('No versions found');
5777
}
5878

5979
// Find the latest version tag (exclude 'latest' and commit hashes)
60-
const versionTags = data.results
80+
const versionTags = dockerHubResponse.results
6181
.filter((tag: any) => tag.name.match(/^\d+\.\d+(\.\d+)?$/))
6282
.sort((a: any, b: any) => {
6383
// Sort by version number
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import React, { useState } from 'react';
2+
import {
3+
Box,
4+
Button,
5+
Alert,
6+
Stack,
7+
Typography,
8+
Chip,
9+
Link,
10+
} from '@mui/material';
11+
import {
12+
Update as UpdateIcon,
13+
CheckCircle as CheckCircleIcon,
14+
OpenInNew as OpenInNewIcon,
15+
} from '@mui/icons-material';
16+
17+
const UpdateCheckerSimple: React.FC = () => {
18+
const [showInstructions, setShowInstructions] = useState(false);
19+
20+
// Get current version from package.json
21+
const CURRENT_VERSION = '1.0.22';
22+
23+
const copyUpdateCommand = async () => {
24+
const command = `docker extension update telkombe/remote-docker:latest`;
25+
26+
try {
27+
if (navigator.clipboard) {
28+
await navigator.clipboard.writeText(command);
29+
// Show success message
30+
setShowInstructions(false);
31+
}
32+
} catch (err) {
33+
console.error('Failed to copy:', err);
34+
}
35+
};
36+
37+
return (
38+
<Box>
39+
<Stack direction="row" spacing={2} alignItems="center">
40+
<Chip
41+
label={`Current: v${CURRENT_VERSION}`}
42+
color="primary"
43+
size="small"
44+
variant="outlined"
45+
icon={<CheckCircleIcon />}
46+
/>
47+
48+
<Button
49+
variant="outlined"
50+
startIcon={<UpdateIcon />}
51+
onClick={() => setShowInstructions(!showInstructions)}
52+
>
53+
Check for Updates
54+
</Button>
55+
56+
<Link
57+
href="https://hub.docker.com/r/telkombe/remote-docker/tags"
58+
target="_blank"
59+
rel="noopener noreferrer"
60+
sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}
61+
>
62+
View on Docker Hub
63+
<OpenInNewIcon fontSize="small" />
64+
</Link>
65+
</Stack>
66+
67+
{showInstructions && (
68+
<Alert
69+
severity="info"
70+
sx={{ mt: 2 }}
71+
action={
72+
<Button color="inherit" size="small" onClick={copyUpdateCommand}>
73+
Copy Command
74+
</Button>
75+
}
76+
>
77+
<Typography variant="subtitle2" gutterBottom>
78+
To update to the latest version:
79+
</Typography>
80+
<Box
81+
component="pre"
82+
sx={{
83+
mt: 1,
84+
p: 1,
85+
bgcolor: 'rgba(0, 0, 0, 0.05)',
86+
borderRadius: 1,
87+
fontSize: '0.875rem',
88+
fontFamily: 'monospace',
89+
}}
90+
>
91+
docker extension update telkombe/remote-docker:latest
92+
</Box>
93+
<Typography variant="caption" sx={{ display: 'block', mt: 1 }}>
94+
Current version: v{CURRENT_VERSION}
95+
</Typography>
96+
</Alert>
97+
)}
98+
</Box>
99+
);
100+
};
101+
102+
export default UpdateCheckerSimple;

ui/src/pages/settings/Environments.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import { Environment, ExtensionSettings } from '../../App';
2727
import EditIcon from '@mui/icons-material/Edit';
2828
import DeleteIcon from '@mui/icons-material/Delete';
2929
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
30-
import UpdateChecker from '../../components/UpdateChecker';
30+
import UpdateCheckerSimple from '../../components/UpdateCheckerSimple';
3131

3232
interface EnvironmentsProps {
3333
settings: ExtensionSettings;
@@ -279,7 +279,7 @@ const Environments: React.FC<EnvironmentsProps> = ({
279279
<Typography variant="h6" gutterBottom>
280280
Extension Updates
281281
</Typography>
282-
<UpdateChecker />
282+
<UpdateCheckerSimple />
283283
</Paper>
284284

285285
{/* Environment List */}

0 commit comments

Comments
 (0)