Disable updater until we can debug more in release (#2908)
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import { Switch } from '../../ui/switch';
|
||||
import UpdateSection from './UpdateSection';
|
||||
import { UPDATES_ENABLED } from '../../../updates';
|
||||
|
||||
interface AppSettingsSectionProps {
|
||||
scrollToSection?: string;
|
||||
@@ -12,6 +11,7 @@ export default function AppSettingsSection({ scrollToSection }: AppSettingsSecti
|
||||
const [dockIconEnabled, setDockIconEnabled] = useState(true);
|
||||
const [isMacOS, setIsMacOS] = useState(false);
|
||||
const [isDockSwitchDisabled, setIsDockSwitchDisabled] = useState(false);
|
||||
const [updatesEnabled, setUpdatesEnabled] = useState(false);
|
||||
const updateSectionRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// Check if running on macOS
|
||||
@@ -19,6 +19,25 @@ export default function AppSettingsSection({ scrollToSection }: AppSettingsSecti
|
||||
setIsMacOS(window.electron.platform === 'darwin');
|
||||
}, []);
|
||||
|
||||
// Load updater state
|
||||
useEffect(() => {
|
||||
window.electron.getUpdaterEnabled().then((enabled) => {
|
||||
setUpdatesEnabled(enabled);
|
||||
});
|
||||
|
||||
// Listen for updater state changes
|
||||
const handleUpdaterStateChange = (enabled: boolean) => {
|
||||
setUpdatesEnabled(enabled);
|
||||
};
|
||||
|
||||
window.electron.onUpdaterStateChanged(handleUpdaterStateChange);
|
||||
|
||||
// Cleanup listener on unmount
|
||||
return () => {
|
||||
window.electron.removeUpdaterStateListener(handleUpdaterStateChange);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Handle scrolling to update section
|
||||
useEffect(() => {
|
||||
if (scrollToSection === 'update' && updateSectionRef.current) {
|
||||
@@ -125,7 +144,7 @@ export default function AppSettingsSection({ scrollToSection }: AppSettingsSecti
|
||||
</div>
|
||||
|
||||
{/* Update Section */}
|
||||
{UPDATES_ENABLED && (
|
||||
{updatesEnabled && (
|
||||
<div ref={updateSectionRef} className="mt-8 pt-8 border-t border-gray-200">
|
||||
<UpdateSection />
|
||||
</div>
|
||||
|
||||
+61
-2
@@ -37,12 +37,31 @@ import * as yaml from 'yaml';
|
||||
import windowStateKeeper from 'electron-window-state';
|
||||
import {
|
||||
setupAutoUpdater,
|
||||
registerUpdateIpcHandlers,
|
||||
setTrayRef,
|
||||
updateTrayMenu,
|
||||
getUpdateAvailable,
|
||||
} from './utils/autoUpdater';
|
||||
import { UPDATES_ENABLED } from './updates';
|
||||
|
||||
// Updater toggle functions (moved here to keep updates.ts minimal for release replacement)
|
||||
let updatesEnabled = UPDATES_ENABLED;
|
||||
|
||||
function toggleUpdates(): boolean {
|
||||
updatesEnabled = !updatesEnabled;
|
||||
return updatesEnabled;
|
||||
}
|
||||
|
||||
function getUpdatesEnabled(): boolean {
|
||||
// Only return the toggle state, ignore ENABLE_DEV_UPDATES for UI visibility
|
||||
return updatesEnabled;
|
||||
}
|
||||
|
||||
function shouldSetupUpdater(): boolean {
|
||||
// Setup updater if either the toggle is enabled OR dev updates are enabled
|
||||
return updatesEnabled || process.env.ENABLE_DEV_UPDATES === 'true';
|
||||
}
|
||||
|
||||
// Define temp directory for pasted images
|
||||
const gooseTempDir = path.join(app.getPath('temp'), 'goose-pasted-images');
|
||||
|
||||
@@ -1157,8 +1176,11 @@ const registerGlobalHotkey = (accelerator: string) => {
|
||||
};
|
||||
|
||||
app.whenReady().then(async () => {
|
||||
// Setup auto-updater
|
||||
UPDATES_ENABLED && setupAutoUpdater();
|
||||
// Register update IPC handlers once
|
||||
registerUpdateIpcHandlers();
|
||||
|
||||
// Setup auto-updater if enabled
|
||||
shouldSetupUpdater() && setupAutoUpdater();
|
||||
|
||||
// Add CSP headers to all sessions
|
||||
session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
|
||||
@@ -1200,6 +1222,38 @@ app.whenReady().then(async () => {
|
||||
// Register the default global hotkey
|
||||
registerGlobalHotkey('CommandOrControl+Alt+Shift+G');
|
||||
|
||||
// Register hidden key combination to toggle updater (Cmd+Shift+U+P+D+A+T+E)
|
||||
globalShortcut.register('CommandOrControl+Shift+U', () => {
|
||||
// This is a multi-key sequence, we'll use a simpler approach
|
||||
// Register a hidden key combination: Cmd/Ctrl + Alt + Shift + U for "Update toggle"
|
||||
const newState = toggleUpdates();
|
||||
log.info(
|
||||
`Updater toggled via keyboard shortcut. New state: ${newState ? 'ENABLED' : 'DISABLED'}`
|
||||
);
|
||||
|
||||
// Show a notification to the user
|
||||
new Notification({
|
||||
title: 'Goose Updater',
|
||||
body: `Updates ${newState ? 'enabled' : 'disabled'}`,
|
||||
}).show();
|
||||
|
||||
// If we're enabling updates and haven't set up the auto-updater yet, set it up now
|
||||
if (newState) {
|
||||
try {
|
||||
setupAutoUpdater(tray || undefined);
|
||||
log.info('Auto-updater setup completed after keyboard toggle');
|
||||
} catch (error) {
|
||||
log.error('Error setting up auto-updater after keyboard toggle:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Notify all windows about the updater state change
|
||||
const windows = BrowserWindow.getAllWindows();
|
||||
windows.forEach((win) => {
|
||||
win.webContents.send('updater-state-changed', newState);
|
||||
});
|
||||
});
|
||||
|
||||
session.defaultSession.webRequest.onBeforeSendHeaders((details, callback) => {
|
||||
details.requestHeaders['Origin'] = 'http://localhost:5173';
|
||||
callback({ cancel: false, requestHeaders: details.requestHeaders });
|
||||
@@ -1610,6 +1664,11 @@ app.whenReady().then(async () => {
|
||||
ipcMain.on('get-app-version', (event) => {
|
||||
event.returnValue = app.getVersion();
|
||||
});
|
||||
|
||||
// Handler for getting updater state
|
||||
ipcMain.handle('get-updater-enabled', () => {
|
||||
return getUpdatesEnabled();
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
@@ -89,6 +89,10 @@ type ElectronAPI = {
|
||||
restartApp: () => void;
|
||||
onUpdaterEvent: (callback: (event: UpdaterEvent) => void) => void;
|
||||
getUpdateState: () => Promise<{ updateAvailable: boolean; latestVersion?: string } | null>;
|
||||
// Updater state functions
|
||||
getUpdaterEnabled: () => Promise<boolean>;
|
||||
onUpdaterStateChanged: (callback: (enabled: boolean) => void) => void;
|
||||
removeUpdaterStateListener: (callback: (enabled: boolean) => void) => void;
|
||||
};
|
||||
|
||||
type AppConfigAPI = {
|
||||
@@ -96,6 +100,12 @@ type AppConfigAPI = {
|
||||
getAll: () => Record<string, unknown>;
|
||||
};
|
||||
|
||||
// Store callback wrappers for proper cleanup
|
||||
const updaterStateCallbacks = new Map<
|
||||
(enabled: boolean) => void,
|
||||
(event: Electron.IpcRendererEvent, enabled: boolean) => void
|
||||
>();
|
||||
|
||||
const electronAPI: ElectronAPI = {
|
||||
platform: process.platform,
|
||||
reactReady: () => ipcRenderer.send('react-ready'),
|
||||
@@ -183,6 +193,22 @@ const electronAPI: ElectronAPI = {
|
||||
getUpdateState: (): Promise<{ updateAvailable: boolean; latestVersion?: string } | null> => {
|
||||
return ipcRenderer.invoke('get-update-state');
|
||||
},
|
||||
// Updater state functions
|
||||
getUpdaterEnabled: (): Promise<boolean> => {
|
||||
return ipcRenderer.invoke('get-updater-enabled');
|
||||
},
|
||||
onUpdaterStateChanged: (callback: (enabled: boolean) => void): void => {
|
||||
const wrapper = (_event: Electron.IpcRendererEvent, enabled: boolean) => callback(enabled);
|
||||
updaterStateCallbacks.set(callback, wrapper);
|
||||
ipcRenderer.on('updater-state-changed', wrapper);
|
||||
},
|
||||
removeUpdaterStateListener: (callback: (enabled: boolean) => void): void => {
|
||||
const wrapper = updaterStateCallbacks.get(callback);
|
||||
if (wrapper) {
|
||||
ipcRenderer.off('updater-state-changed', wrapper);
|
||||
updaterStateCallbacks.delete(callback);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const appConfigAPI: AppConfigAPI = {
|
||||
|
||||
@@ -1 +1 @@
|
||||
export const UPDATES_ENABLED = true;
|
||||
export const UPDATES_ENABLED = false;
|
||||
|
||||
+248
-153
@@ -30,189 +30,68 @@ let githubUpdateInfo: {
|
||||
// Store update state
|
||||
let lastUpdateState: { updateAvailable: boolean; latestVersion?: string } | null = null;
|
||||
|
||||
// Configure auto-updater
|
||||
export function setupAutoUpdater(tray?: Tray) {
|
||||
if (tray) {
|
||||
trayRef = tray;
|
||||
// Track if IPC handlers have been registered
|
||||
let ipcUpdateHandlersRegistered = false;
|
||||
|
||||
// Register IPC handlers (only once)
|
||||
export function registerUpdateIpcHandlers() {
|
||||
if (ipcUpdateHandlersRegistered) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the feed URL for GitHub releases
|
||||
autoUpdater.setFeedURL({
|
||||
provider: 'github',
|
||||
owner: 'block',
|
||||
repo: 'goose',
|
||||
releaseType: 'release',
|
||||
});
|
||||
|
||||
// Configure auto-updater settings
|
||||
autoUpdater.autoDownload = false; // We'll trigger downloads manually
|
||||
autoUpdater.autoInstallOnAppQuit = true;
|
||||
|
||||
// Enable updates in development mode for testing
|
||||
if (process.env.ENABLE_DEV_UPDATES === 'true') {
|
||||
autoUpdater.forceDevUpdateConfig = true;
|
||||
}
|
||||
|
||||
// Set logger
|
||||
autoUpdater.logger = log;
|
||||
|
||||
// Check for updates on startup
|
||||
setTimeout(() => {
|
||||
log.info('Checking for updates on startup...');
|
||||
autoUpdater.checkForUpdates().catch((err) => {
|
||||
log.error('Error checking for updates on startup:', err);
|
||||
// If electron-updater fails, try GitHub API as fallback
|
||||
if (
|
||||
err.message.includes('HttpError: 404') ||
|
||||
err.message.includes('ERR_CONNECTION_REFUSED') ||
|
||||
err.message.includes('ENOTFOUND')
|
||||
) {
|
||||
log.info('Using GitHub API fallback for startup update check...');
|
||||
isUsingGitHubFallback = true;
|
||||
|
||||
githubUpdater
|
||||
.checkForUpdates()
|
||||
.then((result) => {
|
||||
if (result.error) {
|
||||
sendStatusToWindow('error', result.error);
|
||||
} else if (result.updateAvailable) {
|
||||
// Store GitHub update info
|
||||
githubUpdateInfo = {
|
||||
latestVersion: result.latestVersion,
|
||||
downloadUrl: result.downloadUrl,
|
||||
releaseUrl: result.releaseUrl,
|
||||
};
|
||||
|
||||
updateAvailable = true;
|
||||
lastUpdateState = { updateAvailable: true, latestVersion: result.latestVersion };
|
||||
updateTrayIcon(true);
|
||||
sendStatusToWindow('update-available', { version: result.latestVersion });
|
||||
} else {
|
||||
updateAvailable = false;
|
||||
lastUpdateState = { updateAvailable: false };
|
||||
updateTrayIcon(false);
|
||||
sendStatusToWindow('update-not-available', {
|
||||
version: autoUpdater.currentVersion.version,
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((fallbackError) => {
|
||||
log.error('GitHub fallback also failed on startup:', fallbackError);
|
||||
});
|
||||
}
|
||||
});
|
||||
}, 5000); // Wait 5 seconds after app starts
|
||||
|
||||
// Handle update events
|
||||
autoUpdater.on('checking-for-update', () => {
|
||||
log.info('Checking for update...');
|
||||
sendStatusToWindow('checking-for-update');
|
||||
});
|
||||
|
||||
autoUpdater.on('update-available', (info: UpdateInfo) => {
|
||||
log.info('Update available:', info);
|
||||
updateAvailable = true;
|
||||
lastUpdateState = { updateAvailable: true, latestVersion: info.version };
|
||||
updateTrayIcon(true);
|
||||
sendStatusToWindow('update-available', info);
|
||||
});
|
||||
|
||||
autoUpdater.on('update-not-available', (info: UpdateInfo) => {
|
||||
log.info('Update not available:', info);
|
||||
updateAvailable = false;
|
||||
lastUpdateState = { updateAvailable: false };
|
||||
updateTrayIcon(false);
|
||||
sendStatusToWindow('update-not-available', info);
|
||||
});
|
||||
|
||||
autoUpdater.on('error', async (err) => {
|
||||
log.error('Error in auto-updater:', err);
|
||||
|
||||
// Check if this is a 404 error (missing update files) or connection error
|
||||
if (
|
||||
err.message.includes('HttpError: 404') ||
|
||||
err.message.includes('ERR_CONNECTION_REFUSED') ||
|
||||
err.message.includes('ENOTFOUND')
|
||||
) {
|
||||
log.info('Falling back to GitHub API for update check...');
|
||||
isUsingGitHubFallback = true;
|
||||
|
||||
try {
|
||||
const result = await githubUpdater.checkForUpdates();
|
||||
|
||||
if (result.error) {
|
||||
sendStatusToWindow('error', result.error);
|
||||
} else if (result.updateAvailable) {
|
||||
// Store GitHub update info
|
||||
githubUpdateInfo = {
|
||||
latestVersion: result.latestVersion,
|
||||
downloadUrl: result.downloadUrl,
|
||||
releaseUrl: result.releaseUrl,
|
||||
};
|
||||
|
||||
updateAvailable = true;
|
||||
updateTrayIcon(true);
|
||||
sendStatusToWindow('update-available', { version: result.latestVersion });
|
||||
} else {
|
||||
updateAvailable = false;
|
||||
updateTrayIcon(false);
|
||||
sendStatusToWindow('update-not-available', {
|
||||
version: autoUpdater.currentVersion.version,
|
||||
});
|
||||
}
|
||||
} catch (fallbackError) {
|
||||
log.error('GitHub fallback also failed:', fallbackError);
|
||||
sendStatusToWindow(
|
||||
'error',
|
||||
'Unable to check for updates. Please check your internet connection.'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
sendStatusToWindow('error', err.message);
|
||||
}
|
||||
});
|
||||
|
||||
autoUpdater.on('download-progress', (progressObj) => {
|
||||
let log_message = 'Download speed: ' + progressObj.bytesPerSecond;
|
||||
log_message = log_message + ' - Downloaded ' + progressObj.percent + '%';
|
||||
log_message = log_message + ' (' + progressObj.transferred + '/' + progressObj.total + ')';
|
||||
log.info(log_message);
|
||||
sendStatusToWindow('download-progress', progressObj);
|
||||
});
|
||||
|
||||
autoUpdater.on('update-downloaded', (info: UpdateInfo) => {
|
||||
log.info('Update downloaded:', info);
|
||||
sendStatusToWindow('update-downloaded', info);
|
||||
});
|
||||
log.info('Registering update IPC handlers...');
|
||||
ipcUpdateHandlersRegistered = true;
|
||||
|
||||
// IPC handlers for renderer process
|
||||
ipcMain.handle('check-for-updates', async () => {
|
||||
try {
|
||||
log.info('Manual check for updates requested');
|
||||
|
||||
// Reset fallback flag
|
||||
isUsingGitHubFallback = false;
|
||||
githubUpdateInfo = {};
|
||||
|
||||
// Ensure auto-updater is properly initialized
|
||||
if (!autoUpdater.currentVersion) {
|
||||
log.error('Auto-updater currentVersion is null/undefined');
|
||||
throw new Error('Auto-updater not initialized. Please restart the application.');
|
||||
}
|
||||
|
||||
log.info(
|
||||
`About to check for updates with currentVersion: ${JSON.stringify(autoUpdater.currentVersion)}`
|
||||
);
|
||||
log.info(`Feed URL: ${autoUpdater.getFeedURL()}`);
|
||||
|
||||
const result = await autoUpdater.checkForUpdates();
|
||||
log.info('Auto-updater checkForUpdates result:', result);
|
||||
|
||||
return {
|
||||
updateInfo: result?.updateInfo,
|
||||
error: null,
|
||||
};
|
||||
} catch (error) {
|
||||
log.error('Error checking for updates:', error);
|
||||
log.error('Manual check error details:', {
|
||||
message: error instanceof Error ? error.message : 'Unknown error',
|
||||
stack: error instanceof Error ? error.stack : 'No stack',
|
||||
name: error instanceof Error ? error.name : 'Unknown',
|
||||
code:
|
||||
error instanceof Error && 'code' in error
|
||||
? (error as Error & { code: unknown }).code
|
||||
: undefined,
|
||||
toString: error?.toString(),
|
||||
});
|
||||
|
||||
// If electron-updater fails, try GitHub API fallback
|
||||
if (
|
||||
error instanceof Error &&
|
||||
(error.message.includes('HttpError: 404') ||
|
||||
error.message.includes('ERR_CONNECTION_REFUSED') ||
|
||||
error.message.includes('ENOTFOUND'))
|
||||
error.message.includes('ENOTFOUND') ||
|
||||
error.message.includes('No published versions'))
|
||||
) {
|
||||
log.info('Using GitHub API fallback in check-for-updates...');
|
||||
log.info('Manual fallback triggered by error:', error.message);
|
||||
isUsingGitHubFallback = true;
|
||||
|
||||
try {
|
||||
@@ -365,6 +244,222 @@ export function setupAutoUpdater(tray?: Tray) {
|
||||
});
|
||||
}
|
||||
|
||||
// Configure auto-updater
|
||||
export function setupAutoUpdater(tray?: Tray) {
|
||||
if (tray) {
|
||||
trayRef = tray;
|
||||
}
|
||||
|
||||
log.info('Setting up auto-updater...');
|
||||
log.info(`Current app version: ${app.getVersion()}`);
|
||||
log.info(`Platform: ${process.platform}, Arch: ${process.arch}`);
|
||||
log.info(`NODE_ENV: ${process.env.NODE_ENV}`);
|
||||
log.info(`ENABLE_DEV_UPDATES: ${process.env.ENABLE_DEV_UPDATES}`);
|
||||
log.info(`App is packaged: ${app.isPackaged}`);
|
||||
log.info(`App path: ${app.getAppPath()}`);
|
||||
log.info(`Resources path: ${process.resourcesPath}`);
|
||||
|
||||
// Set the feed URL for GitHub releases
|
||||
const feedConfig = {
|
||||
provider: 'github' as const,
|
||||
owner: 'block',
|
||||
repo: 'goose',
|
||||
releaseType: 'release' as const,
|
||||
};
|
||||
|
||||
log.info('Setting feed URL with config:', feedConfig);
|
||||
autoUpdater.setFeedURL(feedConfig);
|
||||
|
||||
// Log the feed URL after setting it
|
||||
try {
|
||||
const feedUrl = autoUpdater.getFeedURL();
|
||||
log.info(`Feed URL set to: ${feedUrl}`);
|
||||
} catch (e) {
|
||||
log.error('Error getting feed URL:', e);
|
||||
}
|
||||
|
||||
// Configure auto-updater settings
|
||||
autoUpdater.autoDownload = false; // We'll trigger downloads manually
|
||||
autoUpdater.autoInstallOnAppQuit = true;
|
||||
|
||||
// Enable updates in development mode for testing
|
||||
if (process.env.ENABLE_DEV_UPDATES === 'true') {
|
||||
log.info('Enabling dev updates config');
|
||||
autoUpdater.forceDevUpdateConfig = true;
|
||||
}
|
||||
|
||||
// Additional debugging for release builds
|
||||
if (app.isPackaged) {
|
||||
log.info('App is packaged - this is a release build');
|
||||
// Try to get more info about the updater configuration
|
||||
try {
|
||||
log.info(`Auto-updater channel: ${autoUpdater.channel}`);
|
||||
log.info(`Auto-updater allowPrerelease: ${autoUpdater.allowPrerelease}`);
|
||||
log.info(`Auto-updater allowDowngrade: ${autoUpdater.allowDowngrade}`);
|
||||
} catch (e) {
|
||||
log.error('Error getting auto-updater properties:', e);
|
||||
}
|
||||
} else {
|
||||
log.info('App is not packaged - this is a development build');
|
||||
}
|
||||
|
||||
// Set logger
|
||||
autoUpdater.logger = log;
|
||||
|
||||
log.info('Auto-updater setup completed');
|
||||
|
||||
// Check for updates on startup
|
||||
setTimeout(() => {
|
||||
log.info('Checking for updates on startup...');
|
||||
log.info(`autoUpdater.currentVersion: ${JSON.stringify(autoUpdater.currentVersion)}`);
|
||||
log.info(`autoUpdater.getFeedURL(): ${autoUpdater.getFeedURL()}`);
|
||||
|
||||
autoUpdater.checkForUpdates().catch((err) => {
|
||||
log.error('Error checking for updates on startup:', err);
|
||||
log.error('Error details:', {
|
||||
message: err.message,
|
||||
stack: err.stack,
|
||||
name: err.name,
|
||||
code: 'code' in err ? err.code : undefined,
|
||||
});
|
||||
|
||||
// If electron-updater fails, try GitHub API as fallback
|
||||
if (
|
||||
err.message.includes('HttpError: 404') ||
|
||||
err.message.includes('ERR_CONNECTION_REFUSED') ||
|
||||
err.message.includes('ENOTFOUND') ||
|
||||
err.message.includes('No published versions')
|
||||
) {
|
||||
log.info('Using GitHub API fallback for startup update check...');
|
||||
log.info('Fallback triggered by error containing:', err.message);
|
||||
isUsingGitHubFallback = true;
|
||||
|
||||
githubUpdater
|
||||
.checkForUpdates()
|
||||
.then((result) => {
|
||||
if (result.error) {
|
||||
sendStatusToWindow('error', result.error);
|
||||
} else if (result.updateAvailable) {
|
||||
// Store GitHub update info
|
||||
githubUpdateInfo = {
|
||||
latestVersion: result.latestVersion,
|
||||
downloadUrl: result.downloadUrl,
|
||||
releaseUrl: result.releaseUrl,
|
||||
};
|
||||
|
||||
updateAvailable = true;
|
||||
lastUpdateState = { updateAvailable: true, latestVersion: result.latestVersion };
|
||||
updateTrayIcon(true);
|
||||
sendStatusToWindow('update-available', { version: result.latestVersion });
|
||||
} else {
|
||||
updateAvailable = false;
|
||||
lastUpdateState = { updateAvailable: false };
|
||||
updateTrayIcon(false);
|
||||
sendStatusToWindow('update-not-available', {
|
||||
version: autoUpdater.currentVersion.version,
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((fallbackError) => {
|
||||
log.error('GitHub fallback also failed on startup:', fallbackError);
|
||||
});
|
||||
}
|
||||
});
|
||||
}, 5000); // Wait 5 seconds after app starts
|
||||
|
||||
// Handle update events
|
||||
autoUpdater.on('checking-for-update', () => {
|
||||
log.info('Auto-updater: Checking for update...');
|
||||
log.info(`Auto-updater: Feed URL during check: ${autoUpdater.getFeedURL()}`);
|
||||
sendStatusToWindow('checking-for-update');
|
||||
});
|
||||
|
||||
autoUpdater.on('update-available', (info: UpdateInfo) => {
|
||||
log.info('Update available:', info);
|
||||
updateAvailable = true;
|
||||
lastUpdateState = { updateAvailable: true, latestVersion: info.version };
|
||||
updateTrayIcon(true);
|
||||
sendStatusToWindow('update-available', info);
|
||||
});
|
||||
|
||||
autoUpdater.on('update-not-available', (info: UpdateInfo) => {
|
||||
log.info('Update not available:', info);
|
||||
updateAvailable = false;
|
||||
lastUpdateState = { updateAvailable: false };
|
||||
updateTrayIcon(false);
|
||||
sendStatusToWindow('update-not-available', info);
|
||||
});
|
||||
|
||||
autoUpdater.on('error', async (err) => {
|
||||
log.error('Error in auto-updater:', err);
|
||||
log.error('Auto-updater error details:', {
|
||||
message: err.message,
|
||||
stack: err.stack,
|
||||
name: err.name,
|
||||
code: 'code' in err ? err.code : undefined,
|
||||
toString: err.toString(),
|
||||
});
|
||||
|
||||
// Check if this is a 404 error (missing update files) or connection error
|
||||
if (
|
||||
err.message.includes('HttpError: 404') ||
|
||||
err.message.includes('ERR_CONNECTION_REFUSED') ||
|
||||
err.message.includes('ENOTFOUND') ||
|
||||
err.message.includes('No published versions')
|
||||
) {
|
||||
log.info('Falling back to GitHub API for update check...');
|
||||
log.info('Fallback triggered by error:', err.message);
|
||||
isUsingGitHubFallback = true;
|
||||
|
||||
try {
|
||||
const result = await githubUpdater.checkForUpdates();
|
||||
|
||||
if (result.error) {
|
||||
sendStatusToWindow('error', result.error);
|
||||
} else if (result.updateAvailable) {
|
||||
// Store GitHub update info
|
||||
githubUpdateInfo = {
|
||||
latestVersion: result.latestVersion,
|
||||
downloadUrl: result.downloadUrl,
|
||||
releaseUrl: result.releaseUrl,
|
||||
};
|
||||
|
||||
updateAvailable = true;
|
||||
updateTrayIcon(true);
|
||||
sendStatusToWindow('update-available', { version: result.latestVersion });
|
||||
} else {
|
||||
updateAvailable = false;
|
||||
updateTrayIcon(false);
|
||||
sendStatusToWindow('update-not-available', {
|
||||
version: autoUpdater.currentVersion.version,
|
||||
});
|
||||
}
|
||||
} catch (fallbackError) {
|
||||
log.error('GitHub fallback also failed:', fallbackError);
|
||||
sendStatusToWindow(
|
||||
'error',
|
||||
'Unable to check for updates. Please check your internet connection.'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
sendStatusToWindow('error', err.message);
|
||||
}
|
||||
});
|
||||
|
||||
autoUpdater.on('download-progress', (progressObj) => {
|
||||
let log_message = 'Download speed: ' + progressObj.bytesPerSecond;
|
||||
log_message = log_message + ' - Downloaded ' + progressObj.percent + '%';
|
||||
log_message = log_message + ' (' + progressObj.transferred + '/' + progressObj.total + ')';
|
||||
log.info(log_message);
|
||||
sendStatusToWindow('download-progress', progressObj);
|
||||
});
|
||||
|
||||
autoUpdater.on('update-downloaded', (info: UpdateInfo) => {
|
||||
log.info('Update downloaded:', info);
|
||||
sendStatusToWindow('update-downloaded', info);
|
||||
});
|
||||
}
|
||||
|
||||
interface UpdaterEvent {
|
||||
event: string;
|
||||
data?: unknown;
|
||||
|
||||
@@ -34,6 +34,8 @@ export class GitHubUpdater {
|
||||
async checkForUpdates(): Promise<UpdateCheckResult> {
|
||||
try {
|
||||
log.info('GitHubUpdater: Checking for updates via GitHub API...');
|
||||
log.info(`GitHubUpdater: API URL: ${this.apiUrl}`);
|
||||
log.info(`GitHubUpdater: Current app version: ${app.getVersion()}`);
|
||||
|
||||
const response = await fetch(this.apiUrl, {
|
||||
headers: {
|
||||
@@ -42,11 +44,21 @@ export class GitHubUpdater {
|
||||
},
|
||||
});
|
||||
|
||||
log.info(
|
||||
`GitHubUpdater: GitHub API response status: ${response.status} ${response.statusText}`
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
log.error(`GitHubUpdater: GitHub API error response: ${errorText}`);
|
||||
throw new Error(`GitHub API returned ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
|
||||
const release: GitHubRelease = await response.json();
|
||||
log.info(`GitHubUpdater: Found release: ${release.tag_name} (${release.name})`);
|
||||
log.info(`GitHubUpdater: Release published at: ${release.published_at}`);
|
||||
log.info(`GitHubUpdater: Release assets count: ${release.assets.length}`);
|
||||
|
||||
const latestVersion = release.tag_name.replace(/^v/, ''); // Remove 'v' prefix if present
|
||||
const currentVersion = app.getVersion();
|
||||
|
||||
@@ -56,6 +68,7 @@ export class GitHubUpdater {
|
||||
|
||||
// Compare versions
|
||||
const updateAvailable = compareVersions(latestVersion, currentVersion) > 0;
|
||||
log.info(`GitHubUpdater: Update available: ${updateAvailable}`);
|
||||
|
||||
if (!updateAvailable) {
|
||||
return {
|
||||
@@ -70,6 +83,8 @@ export class GitHubUpdater {
|
||||
let downloadUrl: string | undefined;
|
||||
let assetName: string;
|
||||
|
||||
log.info(`GitHubUpdater: Looking for asset for platform: ${platform}, arch: ${arch}`);
|
||||
|
||||
if (platform === 'darwin') {
|
||||
// macOS
|
||||
if (arch === 'arm64') {
|
||||
@@ -85,9 +100,16 @@ export class GitHubUpdater {
|
||||
assetName = `Goose-linux-${arch}.zip`;
|
||||
}
|
||||
|
||||
log.info(`GitHubUpdater: Looking for asset named: ${assetName}`);
|
||||
log.info(`GitHubUpdater: Available assets: ${release.assets.map((a) => a.name).join(', ')}`);
|
||||
|
||||
const asset = release.assets.find((a) => a.name === assetName);
|
||||
if (asset) {
|
||||
downloadUrl = asset.browser_download_url;
|
||||
log.info(`GitHubUpdater: Found matching asset: ${asset.name} (${asset.size} bytes)`);
|
||||
log.info(`GitHubUpdater: Download URL: ${downloadUrl}`);
|
||||
} else {
|
||||
log.warn(`GitHubUpdater: No matching asset found for ${assetName}`);
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -98,6 +120,15 @@ export class GitHubUpdater {
|
||||
};
|
||||
} catch (error) {
|
||||
log.error('GitHubUpdater: Error checking for updates:', error);
|
||||
log.error('GitHubUpdater: Error details:', {
|
||||
message: error instanceof Error ? error.message : 'Unknown error',
|
||||
stack: error instanceof Error ? error.stack : 'No stack',
|
||||
name: error instanceof Error ? error.name : 'Unknown',
|
||||
code:
|
||||
error instanceof Error && 'code' in error
|
||||
? (error as Error & { code: unknown }).code
|
||||
: undefined,
|
||||
});
|
||||
return {
|
||||
updateAvailable: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error',
|
||||
|
||||
Reference in New Issue
Block a user