mirror of
https://github.com/The-Low-Code-Foundation/OpenNoodl.git
synced 2026-01-12 23:32:55 +01:00
11 KiB
11 KiB
Task 7.3: Configure Auto-Update Publishing
Overview
Connect the existing auto-update infrastructure to GitHub Releases so users receive update notifications without manual downloads.
What Already Exists
The codebase already has:
- electron-updater - Installed and configured in
autoupdater.js - Update UI - TitleBar shows "Update Available" state
- Confirmation Dialog - Asks user to restart
- IPC Handlers - Communication between main and renderer
What's missing: The publish URL configuration.
How Auto-Update Works
┌─────────────────────────────────────────────────────────────────────┐
│ Auto-Update Flow │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 1. App Starts │
│ │ │
│ ▼ │
│ 2. Check GitHub Releases for latest-{platform}.yml │
│ │ │
│ ▼ │
│ 3. Compare versions (semver) │
│ │ │
│ ├─── Same version ──► Do nothing, check again in 60s │
│ │ │
│ └─── New version ──► Download in background │
│ │ │
│ ▼ │
│ 4. Download complete ──► Show "Update Available" in TitleBar │
│ │ │
│ ▼ │
│ 5. User clicks ──► Show confirmation dialog │
│ │ │
│ ├─── "Later" ──► Dismiss │
│ │ │
│ └─── "Restart" ──► quitAndInstall() │
│ │ │
│ ▼ │
│ 6. App restarts with new version │
│ │
└─────────────────────────────────────────────────────────────────────┘
Implementation
Step 1: Add Publish Configuration
packages/noodl-editor/package.json
{
"build": {
"publish": {
"provider": "github",
"owner": "the-low-code-foundation",
"repo": "opennoodl",
"releaseType": "release"
}
}
}
Configuration Options:
| Setting | Value | Description |
|---|---|---|
provider |
"github" |
Use GitHub Releases |
owner |
"the-low-code-foundation" |
GitHub org/user |
repo |
"opennoodl" |
Repository name |
releaseType |
"release" |
Only stable releases (not drafts/prereleases) |
Step 2: Update autoupdater.js
packages/noodl-editor/src/main/src/autoupdater.js
const { app, ipcMain } = require('electron');
const { autoUpdater } = require('electron-updater');
const log = require('electron-log');
// Configure logging
autoUpdater.logger = log;
autoUpdater.logger.transports.file.level = 'info';
// Disable auto-download so user can choose
autoUpdater.autoDownload = false;
function setupAutoUpdate(window) {
// Skip in dev mode
if (process.env.devMode === 'true' || process.env.autoUpdate === 'no') {
log.info('Auto-update disabled in dev mode');
return;
}
// Linux: Only AppImage supports auto-update
if (process.platform === 'linux' && !process.env.APPIMAGE) {
log.info('Auto-update only available for AppImage on Linux');
return;
}
// Check for updates on startup
checkForUpdates();
// Check periodically (every 60 seconds)
setInterval(checkForUpdates, 60 * 1000);
function checkForUpdates() {
log.info('Checking for updates...');
autoUpdater.checkForUpdates().catch((err) => {
log.error('Update check failed:', err);
});
}
// Update available - ask user if they want to download
autoUpdater.on('update-available', (info) => {
log.info('Update available:', info.version);
// Start download automatically (runs in background)
autoUpdater.downloadUpdate().catch((err) => {
log.error('Download failed:', err);
});
});
// No update available
autoUpdater.on('update-not-available', (info) => {
log.info('No update available. Current version:', app.getVersion());
});
// Download progress
autoUpdater.on('download-progress', (progress) => {
log.info(`Download progress: ${progress.percent.toFixed(1)}%`);
// Optionally send to renderer for progress UI
if (window && !window.isDestroyed()) {
window.webContents.send('updateDownloadProgress', progress);
}
});
// Download complete - notify user
autoUpdater.on('update-downloaded', (info) => {
log.info('Update downloaded:', info.version);
if (window && !window.isDestroyed()) {
window.webContents.send('showAutoUpdatePopup', {
version: info.version,
releaseNotes: info.releaseNotes
});
}
});
// Handle user response
ipcMain.on('autoUpdatePopupClosed', (event, restartNow) => {
if (restartNow) {
log.info('User requested restart for update');
autoUpdater.quitAndInstall(false, true);
} else {
log.info('User deferred update');
}
});
// Error handling
autoUpdater.on('error', (error) => {
log.error('Auto-updater error:', error);
// Don't spam logs - wait before retrying
setTimeout(checkForUpdates, 5 * 60 * 1000); // Retry in 5 minutes
});
}
module.exports = {
setupAutoUpdate
};
Step 3: Enhance Update Dialog (Optional)
packages/noodl-editor/src/editor/src/views/windows/BaseWindow/BaseWindow.tsx
const [AutoUpdateDialog, autoUpdateConfirmation] = useConfirmationDialog({
title: 'Update Available',
message: `Version ${updateInfo?.version || 'new'} is ready to install.
Release notes:
${updateInfo?.releaseNotes || 'Bug fixes and improvements.'}
Restart now to update?`,
confirmButtonLabel: 'Restart Now',
cancelButtonLabel: 'Later'
});
Step 4: Update Manifests
When you build with --publish always, electron-builder creates:
latest.yml (Windows)
version: 1.2.0
files:
- url: Nodegex-Setup-1.2.0.exe
sha512: abc123...
size: 85000000
path: Nodegex-Setup-1.2.0.exe
sha512: abc123...
releaseDate: '2024-01-15T10:30:00.000Z'
latest-mac.yml (macOS)
version: 1.2.0
files:
- url: Nodegex-1.2.0-arm64.dmg
sha512: def456...
size: 150000000
- url: Nodegex-1.2.0-x64.dmg
sha512: ghi789...
size: 155000000
path: Nodegex-1.2.0-arm64.dmg
sha512: def456...
releaseDate: '2024-01-15T10:30:00.000Z'
latest-linux.yml (Linux)
version: 1.2.0
files:
- url: Nodegex-1.2.0-x64.AppImage
sha512: jkl012...
size: 120000000
path: Nodegex-1.2.0-x64.AppImage
sha512: jkl012...
releaseDate: '2024-01-15T10:30:00.000Z'
Step 5: Test Locally
Create a test release:
# Build with publish (but don't actually publish)
cd packages/noodl-editor
npx electron-builder --mac --publish never
# Check generated files
ls dist/
# Should include: latest-mac.yml
Test update detection:
# 1. Install an older version
# 2. Create a GitHub Release with newer version
# 3. Launch old version
# 4. Watch logs for update detection:
tail -f ~/Library/Logs/Nodegex/main.log
Step 6: Configure Release Channels (Optional)
For beta/alpha testing:
// In autoupdater.js
autoUpdater.channel = 'latest'; // Default
// Or allow user to opt into beta:
autoUpdater.channel = userPreferences.updateChannel || 'latest';
// Channels: 'latest' (stable), 'beta', 'alpha'
electron-builder creates separate manifests:
latest.yml- Stable releasesbeta.yml- Beta releasesalpha.yml- Alpha releases
Files to Modify
| File | Changes |
|---|---|
packages/noodl-editor/package.json |
Add publish configuration |
packages/noodl-editor/src/main/src/autoupdater.js |
Enhance with logging, progress |
packages/noodl-editor/src/editor/src/views/windows/BaseWindow/BaseWindow.tsx |
Optional: Better update dialog |
Testing Checklist
Local Testing
- Build produces
latest-*.ymlfiles - App connects to GitHub Releases API
- Update detection works (with test release)
- Download progress shown (optional)
- "Restart" installs update
- "Later" dismisses dialog
- App restarts with new version
Platform Testing
- macOS Intel: Download correct arch
- macOS ARM: Download correct arch
- Windows: NSIS installer works
- Linux AppImage: Update replaces file
Edge Cases
- Offline: Graceful failure, retry later
- Partial download: Resume or restart
- Corrupted download: SHA512 check fails, retry
- Downgrade prevention: Don't install older version
Troubleshooting
Update not detected
Check logs:
# macOS
cat ~/Library/Logs/Nodegex/main.log
# Windows
type %USERPROFILE%\AppData\Roaming\Nodegex\logs\main.log
# Linux
cat ~/.config/Nodegex/logs/main.log
Wrong architecture downloaded
Verify latest-mac.yml has both arch entries and correct sha512 values.
"Cannot find latest.yml"
Either:
- Build wasn't published to GitHub Releases
- Release is still in draft mode
- Network/proxy issues
Update downloads but doesn't install
Check:
- SHA512 mismatch (corrupted download)
- Disk space
- Permissions (can write to app directory)
Success Criteria
- ✅ App checks for updates on startup
- ✅ Update notification appears for new releases
- ✅ Background download doesn't interrupt work
- ✅ Restart installs update seamlessly
- ✅ User data preserved after update
- ✅ Works on all three platforms