NSIS-style update for all platforms (100% non-Squirrel)
See original GitHub issue- Version: 19.6.0
- Target: nsis, pkg, appImage
The NSIS update mechanism is accomplished by simply downloading the installer, launching it, and quitting. (possibly using elevate.exe
to request permissions if needed, though if installed per-user this is generally not necessary). When using the NSIS one-click installer, this is completely seamless for the user, and the new app starts up automatically after the update has finished. This also allows updates and initial-installs to use the same installer artifact, simplifying the build and hosting.
It would be nice to have this same functionality available for Mac and Linux platforms, where the installer artifact is also the update artifact, and no Squirrel trickery or .zip file is needed.
For MacOS:
The pkg
target can provide a fairly streamlined installer, much like nsis
, but by default it installs for all-users (this can now be adjusted per #1685 !), does not auto-start the app after install, and does require some user interaction with the UI during install. The app-auto-start can be accomplished by adding the following postinstall
script:
#!/bin/bash
# Try to find installer PID so as to be able to wait for it to close.
INSTALLER_PID=`/usr/sbin/lsof -cInstaller | grep "$1" | head -1 | cut -d' ' -f2`
( # do the following without blocking the installer
# Wait until the installer's PID is no longer present.
while ps "$INSTALLER_PID" >/dev/null 2>&1; do sleep 0.1; done
# Launch the app.
/bin/launchctl asuser `id -u "$USER"` /usr/bin/open -b "$INSTALL_PKG_SESSION_ID"
) & disown $!
exit 0
And a non-interactive update-install can be launched with the following commands (it may be advisable to detect if the current app is writable by the current user, and launch the GUI installer instead if elevation is going to be needed):
electron.app.relaunch({execPath: '/usr/sbin/installer', args: [
'-package', updateFile,
'-target', 'CurrentUserHomeDirectory',
]);
electron.app.quit();
For Linux:
The appImage
target can provide a streamlined Linux install without admin permission required. For updating an appImage
installation, the following command will work if the user has permission to overwrite the exsiting file (again, it may be advisable to detect permissions and use gksudo
for elevation of the cp
if necessary):
var currentFile = process.env.APPIMAGE;
var updateFileEsc = updateFile.replace(/'/g, '\'\\\'\'');
var currentFileEsc = currentFile.replace(/'/g, '\'\\\'\'');
var cmd = `cp '${updateFileEsc}' '${currentFileEsc}';( exec '${currentFileEsc}' ) & disown $!`;
// relaunch won't work - see: #1727...
//electron.app.relaunch({execPath: '/bin/bash', args: ['-c', cmd]});
// ...using spawn and some bash magic instead for now.
child_process.spawn('/bin/bash', ['-c',`while ps ${process.pid} >/dev/null 2>&1; do sleep 0.1; done; ${cmd}`], {detached: true});
electron.app.quit();
(Note: due to #1727, electron.app.relaunch
cannot be used to launch the update process)
You may or may not want to take this approach in electron-updater
, but I figured I should share since there are probably others who could make use of this technique too. I’m using it myself in a somewhat-non-standard updater scenario that is triggered programmatically rather than monitoring a feed automatically, so I’m not actually using the electron-updater
package right now - just the artifacts generated by electron-builder
.
Obviously this update mechanism is not as efficient as the delta-based updates that AppImageUpdate recommends, but it supports programmatic updates, non-sequential updates, and downgrades.
Also note that updating AppImages in this way can produce confusing filenames if the original AppImage filename included a version identifier - after the upgrade, the filename will remain the same, but the contents will be from the new version.
Issue Analytics
- State:
- Created 6 years ago
- Reactions:5
- Comments:11 (8 by maintainers)
Top GitHub Comments
@develar - yes, issue #2199 was what led me here. You mentioned user demand, so I was just expressing my interest. If I were in a position to donate, I would (unfortunately I’m not). If I wind up with any spare time, I’ll contribute the code myself.
I originally used sudo elevation, but it creates a poor experience for the end user. My users (about 50K of them) don’t want to be prompted all the time when the install/update process can do it in a streamlined manner. It’s also a better practice to isolate installer logic within the installer, as opposed to embedding everything in the Electron app.
Just because Docker uses a DMG doesn’t really mean anything to me. My app isn’t Docker. Using the “good enough for someone else logic” is a poor justification for doing something, but for those intent on following it, remember that Node.js uses a .pkg installer for macOS.
Anyhow, I’m not complaining… electron-builder has been helpful and I appreciate everything you’ve done. I run several OSS projects myself and know how demanding it is. I merely wanted to point out there’s at least one user interested in a pkg implementation 😉
I’d just like to cast my vote for .pkg delta support in some manner. My app installation process requires creation of a shell file (my app has a GUI and CLI component) and several other small but important OS operations at the time of install/update. The DMG format simply doesn’t support this on it’s own.