mirror of
https://github.com/lobehub/lobehub.git
synced 2026-03-27 13:29:15 +07:00
🐛 fix: simplify updater config logic (#11636)
* 🐛 fix: simplify updater config logic - Remove isDev check from UpdaterManager initialization - Remove unused enableRenderHotUpdate field - Simplify updater behavior to respect enableAppUpdate config * chore: cleanup Signed-off-by: Innei <tukon479@gmail.com> --------- Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
@@ -14,10 +14,8 @@ import { createLogger } from '@/utils/logger';
|
||||
|
||||
import type { App as AppCore } from '../App';
|
||||
|
||||
// Allow forcing dev update config via env (for testing updates in packaged app)
|
||||
const FORCE_DEV_UPDATE_CONFIG = getDesktopEnv().FORCE_DEV_UPDATE_CONFIG;
|
||||
|
||||
// Create logger
|
||||
const logger = createLogger('core:UpdaterManager');
|
||||
|
||||
export class UpdaterManager {
|
||||
@@ -31,11 +29,10 @@ export class UpdaterManager {
|
||||
constructor(app: AppCore) {
|
||||
this.app = app;
|
||||
|
||||
// 设置日志
|
||||
log.transports.file.level = 'info';
|
||||
autoUpdater.logger = log;
|
||||
|
||||
logger.debug(`[Updater] Log file should be at: ${log.transports.file.getFile().path}`); // 打印路径
|
||||
logger.debug(`[Updater] Log file should be at: ${log.transports.file.getFile().path}`);
|
||||
}
|
||||
|
||||
get mainWindow() {
|
||||
@@ -44,50 +41,36 @@ export class UpdaterManager {
|
||||
|
||||
public initialize = async () => {
|
||||
logger.debug('Initializing UpdaterManager');
|
||||
// If updates are disabled and in production environment, don't initialize updates
|
||||
if (!updaterConfig.enableAppUpdate && !isDev) {
|
||||
|
||||
if (!updaterConfig.enableAppUpdate) {
|
||||
logger.info('App updates are disabled, skipping updater initialization');
|
||||
return;
|
||||
}
|
||||
|
||||
// Configure autoUpdater
|
||||
autoUpdater.autoDownload = false; // Set to false, we'll control downloads manually
|
||||
autoUpdater.autoDownload = false;
|
||||
autoUpdater.autoInstallOnAppQuit = false;
|
||||
autoUpdater.allowDowngrade = false;
|
||||
|
||||
// Enable test mode in development environment or when forced via env
|
||||
// IMPORTANT: This must be set BEFORE channel configuration so that
|
||||
// dev-app-update.yml takes precedence over programmatic configuration
|
||||
const useDevConfig = isDev || FORCE_DEV_UPDATE_CONFIG;
|
||||
if (useDevConfig) {
|
||||
// In dev mode, use dev-app-update.yml for all configuration including channel
|
||||
// Don't set channel here - let dev-app-update.yml control it (defaults to "latest")
|
||||
autoUpdater.forceDevUpdateConfig = true;
|
||||
logger.info(
|
||||
`Using dev update config (isDev=${isDev}, FORCE_DEV_UPDATE_CONFIG=${FORCE_DEV_UPDATE_CONFIG})`,
|
||||
);
|
||||
logger.info('Dev mode: Using dev-app-update.yml for update configuration');
|
||||
} else {
|
||||
// Only configure channel and update provider programmatically in production
|
||||
// Note: channel is configured in configureUpdateProvider based on provider type
|
||||
autoUpdater.allowPrerelease = channel !== 'stable';
|
||||
logger.info(`Production mode: channel=${channel}, allowPrerelease=${channel !== 'stable'}`);
|
||||
this.configureUpdateProvider();
|
||||
}
|
||||
|
||||
// Register events
|
||||
this.registerEvents();
|
||||
|
||||
// If auto-check for updates is configured, set up periodic checks
|
||||
if (updaterConfig.app.autoCheckUpdate) {
|
||||
// Delay update check by 1 minute after startup to avoid network instability
|
||||
setTimeout(() => this.checkForUpdates(), 60 * 1000);
|
||||
|
||||
// Set up periodic checks
|
||||
setInterval(() => this.checkForUpdates(), updaterConfig.app.checkUpdateInterval);
|
||||
}
|
||||
|
||||
// Log the channel and allowPrerelease values
|
||||
logger.debug(
|
||||
`Initialized with channel: ${autoUpdater.channel}, allowPrerelease: ${autoUpdater.allowPrerelease}`,
|
||||
);
|
||||
@@ -105,15 +88,12 @@ export class UpdaterManager {
|
||||
this.checking = true;
|
||||
this.isManualCheck = manual;
|
||||
|
||||
// Ensure allowPrerelease is correctly set before each check
|
||||
// This guards against any internal state reset by electron-updater
|
||||
if (!isStableChannel) {
|
||||
autoUpdater.allowPrerelease = true;
|
||||
}
|
||||
|
||||
logger.info(`${manual ? 'Manually checking' : 'Auto checking'} for updates...`);
|
||||
|
||||
// Log detailed updater configuration for debugging
|
||||
const inferredChannel =
|
||||
autoUpdater.channel ||
|
||||
(autoUpdater.currentVersion?.prerelease?.[0]
|
||||
@@ -133,7 +113,6 @@ export class UpdaterManager {
|
||||
logger.info('[Updater Config] usingFallbackProvider:', this.usingFallbackProvider);
|
||||
logger.info('[Updater Config] GitHub config:', JSON.stringify(githubConfig));
|
||||
|
||||
// If manual check, notify renderer process about check start
|
||||
if (manual) {
|
||||
this.mainWindow.broadcast('manualUpdateCheckStart');
|
||||
}
|
||||
@@ -143,7 +122,6 @@ export class UpdaterManager {
|
||||
} catch (error) {
|
||||
logger.error('Error checking for updates:', error.message);
|
||||
|
||||
// If manual check, notify renderer process about check error
|
||||
if (manual) {
|
||||
this.mainWindow.broadcast('updateError', (error as Error).message);
|
||||
}
|
||||
@@ -162,7 +140,6 @@ export class UpdaterManager {
|
||||
this.downloading = true;
|
||||
logger.info(`${manual ? 'Manually downloading' : 'Auto downloading'} update...`);
|
||||
|
||||
// If manual download or manual check, notify renderer process about download start
|
||||
if (manual || this.isManualCheck) {
|
||||
this.mainWindow.broadcast('updateDownloadStart');
|
||||
}
|
||||
@@ -173,7 +150,6 @@ export class UpdaterManager {
|
||||
this.downloading = false;
|
||||
logger.error('Error downloading update:', error);
|
||||
|
||||
// If manual download or manual check, notify renderer process about download error
|
||||
if (manual || this.isManualCheck) {
|
||||
this.mainWindow.broadcast('updateError', (error as Error).message);
|
||||
}
|
||||
@@ -186,14 +162,10 @@ export class UpdaterManager {
|
||||
public installNow = () => {
|
||||
logger.info('Installing update now...');
|
||||
|
||||
// Mark application for exit
|
||||
this.app.isQuiting = true;
|
||||
|
||||
// Close all windows first to ensure clean exit
|
||||
logger.info('Closing all windows before update installation...');
|
||||
const { BrowserWindow, app } = require('electron');
|
||||
// do not close windows and quit first
|
||||
// on Windows, window-all-closed -> app.quit()` can terminate the process before the timer fires
|
||||
if (!isWindows) {
|
||||
const allWindows = BrowserWindow.getAllWindows();
|
||||
allWindows.forEach((window) => {
|
||||
@@ -203,16 +175,10 @@ export class UpdaterManager {
|
||||
});
|
||||
}
|
||||
|
||||
// Release single instance lock before quitting
|
||||
// This ensures the new instance can acquire the lock
|
||||
logger.info('Releasing single instance lock...');
|
||||
app.releaseSingleInstanceLock();
|
||||
|
||||
// Small delay to ensure windows are closed and lock is released
|
||||
setTimeout(() => {
|
||||
// quitAndInstall parameters:
|
||||
// - isSilent: true (don't show installation UI)
|
||||
// - isForceRunAfter: true (force start app after installation)
|
||||
logger.info('Calling autoUpdater.quitAndInstall...');
|
||||
autoUpdater.quitAndInstall(true, true);
|
||||
}, 100);
|
||||
@@ -224,10 +190,7 @@ export class UpdaterManager {
|
||||
public installLater = () => {
|
||||
logger.info('Update will be installed on next restart');
|
||||
|
||||
// Mark for installation on next launch, but don't exit application
|
||||
autoUpdater.autoInstallOnAppQuit = true;
|
||||
|
||||
// Notify renderer process that update will be installed on next launch
|
||||
this.mainWindow.broadcast('updateWillInstallLater');
|
||||
};
|
||||
|
||||
@@ -241,7 +204,6 @@ export class UpdaterManager {
|
||||
logger.info('Simulating update available...');
|
||||
|
||||
const mainWindow = this.mainWindow;
|
||||
// Simulate a new version update
|
||||
const mockUpdateInfo = {
|
||||
releaseDate: new Date().toISOString(),
|
||||
releaseNotes: ` #### Version 1.0.0 Release Notes
|
||||
@@ -253,14 +215,11 @@ export class UpdaterManager {
|
||||
version: '1.0.0',
|
||||
};
|
||||
|
||||
// Set update available state
|
||||
this.updateAvailable = true;
|
||||
|
||||
// Notify renderer process
|
||||
if (this.isManualCheck) {
|
||||
mainWindow.broadcast('manualUpdateAvailable', mockUpdateInfo);
|
||||
} else {
|
||||
// In auto-check mode, directly simulate download
|
||||
this.simulateDownloadProgress();
|
||||
}
|
||||
};
|
||||
@@ -276,7 +235,6 @@ export class UpdaterManager {
|
||||
|
||||
const mainWindow = this.app.browserManager.getMainWindow();
|
||||
if (mainWindow) {
|
||||
// Simulate a new version update
|
||||
const mockUpdateInfo = {
|
||||
releaseDate: new Date().toISOString(),
|
||||
releaseNotes: ` #### Version 1.0.0 Release Notes
|
||||
@@ -288,10 +246,7 @@ export class UpdaterManager {
|
||||
version: '1.0.0',
|
||||
};
|
||||
|
||||
// Set download state
|
||||
this.downloading = false;
|
||||
|
||||
// Notify renderer process
|
||||
mainWindow.broadcast('updateDownloaded', mockUpdateInfo);
|
||||
}
|
||||
};
|
||||
@@ -307,28 +262,22 @@ export class UpdaterManager {
|
||||
|
||||
const mainWindow = this.app.browserManager.getMainWindow();
|
||||
|
||||
// Set download state
|
||||
this.downloading = true;
|
||||
|
||||
// Only broadcast download start event if manual check
|
||||
if (this.isManualCheck) {
|
||||
mainWindow.broadcast('updateDownloadStart');
|
||||
}
|
||||
|
||||
// Simulate progress updates
|
||||
let progress = 0;
|
||||
const interval = setInterval(() => {
|
||||
progress += 10;
|
||||
|
||||
if (
|
||||
progress <= 100 && // Only broadcast download progress if manual check
|
||||
this.isManualCheck
|
||||
) {
|
||||
if (progress <= 100 && this.isManualCheck) {
|
||||
mainWindow.broadcast('updateDownloadProgress', {
|
||||
bytesPerSecond: 1024 * 1024,
|
||||
percent: progress, // 1MB/s
|
||||
total: 1024 * 1024 * 100, // 100MB
|
||||
transferred: 1024 * 1024 * progress, // Progress * 1MB
|
||||
percent: progress,
|
||||
total: 1024 * 1024 * 100,
|
||||
transferred: 1024 * 1024 * progress,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -348,8 +297,6 @@ export class UpdaterManager {
|
||||
*/
|
||||
private configureUpdateProvider() {
|
||||
if (isStableChannel && UPDATE_SERVER_URL && !this.usingFallbackProvider) {
|
||||
// Stable channel uses custom update server (generic HTTP) as primary
|
||||
// S3 has stable-mac.yml, so we set channel to 'stable'
|
||||
autoUpdater.channel = 'stable';
|
||||
logger.info(`Configuring generic provider for stable channel (primary)`);
|
||||
logger.info(`Update server URL: ${UPDATE_SERVER_URL}`);
|
||||
@@ -360,9 +307,6 @@ export class UpdaterManager {
|
||||
url: UPDATE_SERVER_URL,
|
||||
});
|
||||
} else {
|
||||
// GitHub provider:
|
||||
// - stable: use default latest-mac.yml (GitHub uploads latest* only)
|
||||
// - beta/nightly: leave channel unset so prerelease matching uses tag (e.g. next)
|
||||
const reason = this.usingFallbackProvider ? '(fallback from S3)' : '';
|
||||
logger.info(`Configuring GitHub provider for ${channel} channel ${reason}`);
|
||||
if (autoUpdater.channel !== null) {
|
||||
@@ -370,7 +314,6 @@ export class UpdaterManager {
|
||||
}
|
||||
logger.info('Channel left unset (defaults to latest-mac.yml for GitHub)');
|
||||
|
||||
// For beta/nightly channels, we need prerelease versions
|
||||
const needPrerelease = channel !== 'stable';
|
||||
|
||||
autoUpdater.setFeedURL({
|
||||
@@ -379,8 +322,6 @@ export class UpdaterManager {
|
||||
repo: githubConfig.repo,
|
||||
});
|
||||
|
||||
// Ensure allowPrerelease is set correctly after setFeedURL
|
||||
// setFeedURL may reset some internal states
|
||||
autoUpdater.allowPrerelease = needPrerelease;
|
||||
|
||||
logger.info(
|
||||
@@ -394,7 +335,6 @@ export class UpdaterManager {
|
||||
* Called when primary provider (S3) fails
|
||||
*/
|
||||
private switchToFallbackAndRetry = async () => {
|
||||
// Only fallback if we're on stable channel with S3 configured and haven't already fallen back
|
||||
if (!isStableChannel || !UPDATE_SERVER_URL || this.usingFallbackProvider) {
|
||||
return false;
|
||||
}
|
||||
@@ -403,7 +343,6 @@ export class UpdaterManager {
|
||||
this.usingFallbackProvider = true;
|
||||
this.configureUpdateProvider();
|
||||
|
||||
// Retry update check with fallback provider
|
||||
try {
|
||||
await autoUpdater.checkForUpdates();
|
||||
return true;
|
||||
@@ -437,13 +376,11 @@ export class UpdaterManager {
|
||||
logger.info(`Update available: ${info.version}`);
|
||||
this.updateAvailable = true;
|
||||
|
||||
// Reset to primary provider for next check cycle
|
||||
this.resetToPrimaryProvider();
|
||||
|
||||
if (this.isManualCheck) {
|
||||
this.mainWindow.broadcast('manualUpdateAvailable', info);
|
||||
} else {
|
||||
// If it's an automatic check, start downloading automatically
|
||||
logger.info('Auto check found update, starting download automatically...');
|
||||
this.downloadUpdate();
|
||||
}
|
||||
@@ -452,7 +389,6 @@ export class UpdaterManager {
|
||||
autoUpdater.on('update-not-available', (info) => {
|
||||
logger.info(`Update not available. Current: ${info.version}`);
|
||||
|
||||
// Reset to primary provider for next check cycle
|
||||
this.resetToPrimaryProvider();
|
||||
|
||||
if (this.isManualCheck) {
|
||||
@@ -462,7 +398,6 @@ export class UpdaterManager {
|
||||
|
||||
autoUpdater.on('error', async (err) => {
|
||||
logger.error('Error in auto-updater:', err);
|
||||
// Log configuration state when error occurs for debugging
|
||||
logger.error('[Updater Error Context] Channel:', autoUpdater.channel);
|
||||
logger.error('[Updater Error Context] allowPrerelease:', autoUpdater.allowPrerelease);
|
||||
logger.error('[Updater Error Context] Build channel from config:', channel);
|
||||
@@ -471,12 +406,11 @@ export class UpdaterManager {
|
||||
logger.error('[Updater Error Context] usingFallbackProvider:', this.usingFallbackProvider);
|
||||
logger.error('[Updater Error Context] GitHub config:', JSON.stringify(githubConfig));
|
||||
|
||||
// Try fallback to GitHub if S3 failed
|
||||
if (!this.usingFallbackProvider && isStableChannel && UPDATE_SERVER_URL) {
|
||||
logger.info('Attempting fallback to GitHub provider...');
|
||||
const fallbackSucceeded = await this.switchToFallbackAndRetry();
|
||||
if (fallbackSucceeded) {
|
||||
return; // Fallback initiated, don't report error yet
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,7 +431,6 @@ export class UpdaterManager {
|
||||
autoUpdater.on('update-downloaded', (info) => {
|
||||
logger.info(`Update downloaded: ${info.version}`);
|
||||
this.downloading = false;
|
||||
// Always notify about downloaded update
|
||||
this.mainWindow.broadcast('updateDownloaded', info);
|
||||
});
|
||||
|
||||
|
||||
@@ -76,7 +76,6 @@ vi.mock('@/modules/updater/configs', () => ({
|
||||
checkUpdateInterval: 60 * 60 * 1000,
|
||||
},
|
||||
enableAppUpdate: true,
|
||||
enableRenderHotUpdate: true,
|
||||
},
|
||||
}));
|
||||
|
||||
|
||||
@@ -27,10 +27,6 @@ export const updaterConfig = {
|
||||
// Update check interval (milliseconds)
|
||||
checkUpdateInterval: 60 * 60 * 1000, // 1 hour
|
||||
},
|
||||
|
||||
// Whether to enable application updates
|
||||
enableAppUpdate: !isDev,
|
||||
|
||||
// 是否启用渲染层热更新
|
||||
enableRenderHotUpdate: !isDev,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user