├── .gitignore ├── version.html ├── package.json ├── LICENSE ├── README.md └── main.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist/ 3 | yarn.lock 4 | package-lock.json 5 | -------------------------------------------------------------------------------- /version.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Electron Updater Example 5 | 6 | 7 | Current version: vX.Y.Z 8 |
9 | 23 | 24 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "electron-updater-example", 3 | "version": "0.8.1", 4 | "main": "main.js", 5 | "description": "electron-updater example project", 6 | "author": "Matt Haggard", 7 | "scripts": { 8 | "publish": "electron-builder -p always" 9 | }, 10 | "devDependencies": { 11 | "electron": "^14.0.1", 12 | "electron-builder": "^22.11.7", 13 | "electron-notarize": "^1.1.1" 14 | }, 15 | "dependencies": { 16 | "electron-log": "^4.4.1", 17 | "electron-updater": "^4.3.9" 18 | }, 19 | "build": { 20 | "appId": "com.github.iffy.electronupdaterexample", 21 | "afterSign": "./build/notarize.js", 22 | "mac": { 23 | "category": "your.app.category.type" 24 | }, 25 | "win": { 26 | "target": "nsis" 27 | }, 28 | "nsis": { 29 | "oneClick": false 30 | }, 31 | "linux": { 32 | "category": "your.app.category.type", 33 | "target": "AppImage" 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This repo contains the **bare minimum code** to have an auto-updating Electron app using [`electron-updater`](https://github.com/electron-userland/electron-builder/tree/master/packages/electron-updater) with releases stored on GitHub. 2 | 3 | If you can't use GitHub, you can use other providers: 4 | 5 | - [Complete electron-updater HTTP example](https://gist.github.com/iffy/0ff845e8e3f59dbe7eaf2bf24443f104) 6 | - [Complete electron-updater from gitlab.com private repo example](https://gist.github.com/Slauta/5b2bcf9fa1f6f6a9443aa6b447bcae05) 7 | 8 | **NOTE:** If you want to run through this whole process, either fork this repo or [start your own from a template](https://github.com/iffy/electron-updater-example/generate). Then replace all instances of `iffy` with your GitHub username before doing the following steps. 9 | 10 | 1. For macOS, you will need a code-signing certificate. 11 | 12 | Install Xcode (from the App Store), then follow [these instructions](https://developer.apple.com/library/content/documentation/IDEs/Conceptual/AppDistributionGuide/MaintainingCertificates/MaintainingCertificates.html#//apple_ref/doc/uid/TP40012582-CH31-SW6) to make sure you have a "Developer ID Application" certificate. If you'd like to export the certificate (for automated building, for instance) [you can](https://developer.apple.com/library/content/documentation/IDEs/Conceptual/AppDistributionGuide/MaintainingCertificates/MaintainingCertificates.html#//apple_ref/doc/uid/TP40012582-CH31-SW7). You would then follow [these instructions](https://www.electron.build/code-signing). 13 | 14 | This example application is set up to perform code-signing and notarization on Mac OS provided that a `Developer ID 15 | Application` certificate is installed in the default keychain. The following environment variables are important for the signing process: 16 | 17 | - `CSC_IDENTITY_AUTO_DISCOVERY` - controls whether `electron-builder` tries to sign the application; default is `true`, set to `false` to skip signing 18 | - `APPLE_ID` - the Apple ID to use for notarization (required for signing). 19 | - `APPLE_ID_PASSWORD` - the password to use with the specified Apple ID for notarization (required for signing). Apple recommends setting up an app-specific password to safeguard the Apple ID password (see [Apple Support](https://support.apple.com/en-us/HT204397)) for more information. 20 | 21 | To enable code-signing and notarization: 22 | 23 | export CSC_IDENTITY_AUTO_DISCOVERY="true" 24 | export APPLE_ID="" 25 | export APPLE_ID_PASSWORD="" 26 | 27 | 2. Adjust `package.json` if needed. 28 | 29 | By default, `electron-updater` will try to detect the GitHub settings (such as the repo name and owner) from reading the `.git/config` or from reading other attributes within `package.json`. If the auto-detected settings are not what you want, configure the [`publish`](https://github.com/electron-userland/electron-builder/wiki/Publishing-Artifacts#PublishConfiguration) property as follows: 30 | 31 | { 32 | ... 33 | "build": { 34 | "publish": [{ 35 | "provider": "github", 36 | "owner": "iffy", 37 | "repo": "electron-updater-example" 38 | }], 39 | ... 40 | } 41 | } 42 | 43 | 3. Install necessary dependencies with: 44 | 45 | yarn 46 | 47 | or 48 | 49 | npm install 50 | 51 | 4. Generate a GitHub access token by going to . The access token should have the `repo` scope/permission. Once you have the token, assign it to an environment variable 52 | 53 | On macOS/linux: 54 | 55 | export GH_TOKEN="" 56 | 57 | On Windows, run in powershell: 58 | 59 | [Environment]::SetEnvironmentVariable("GH_TOKEN","","User") 60 | 61 | Make sure to restart your IDE/Terminal to inherit latest env variable. 62 | 63 | 5. Publish for your platform with: 64 | 65 | electron-builder -p always 66 | 67 | or 68 | 69 | npm run publish 70 | 71 | If you want to publish for more platforms, edit the `publish` script in `package.json`. For instance, to build for Windows and macOS: 72 | 73 | ... 74 | "scripts": { 75 | "publish": "electron-builder --mac --win -p always" 76 | }, 77 | ... 78 | 79 | NOTE: The Mac OS signing/notarization process must be run on Mac OS. 80 | 81 | 6. Release the release on GitHub by going to , editing the release and clicking "Publish release." 82 | 83 | 7. Download and install the app from . 84 | 85 | 8. Update the version in `package.json`, commit and push to GitHub. 86 | 87 | 9. Do steps 5 and 6 again. 88 | 89 | 10. Open the installed version of the app and see that it updates itself. 90 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | // This is free and unencumbered software released into the public domain. 2 | // See LICENSE for details 3 | 4 | const {app, BrowserWindow, Menu} = require('electron'); 5 | const log = require('electron-log'); 6 | const {autoUpdater} = require("electron-updater"); 7 | 8 | //------------------------------------------------------------------- 9 | // Logging 10 | // 11 | // THIS SECTION IS NOT REQUIRED 12 | // 13 | // This logging setup is not required for auto-updates to work, 14 | // but it sure makes debugging easier :) 15 | //------------------------------------------------------------------- 16 | autoUpdater.logger = log; 17 | autoUpdater.logger.transports.file.level = 'info'; 18 | log.info('App starting...'); 19 | 20 | //------------------------------------------------------------------- 21 | // Define the menu 22 | // 23 | // THIS SECTION IS NOT REQUIRED 24 | //------------------------------------------------------------------- 25 | let template = [] 26 | if (process.platform === 'darwin') { 27 | // OS X 28 | const name = app.getName(); 29 | template.unshift({ 30 | label: name, 31 | submenu: [ 32 | { 33 | label: 'About ' + name, 34 | role: 'about' 35 | }, 36 | { 37 | label: 'Quit', 38 | accelerator: 'Command+Q', 39 | click() { app.quit(); } 40 | }, 41 | ] 42 | }) 43 | } 44 | 45 | 46 | //------------------------------------------------------------------- 47 | // Open a window that displays the version 48 | // 49 | // THIS SECTION IS NOT REQUIRED 50 | // 51 | // This isn't required for auto-updates to work, but it's easier 52 | // for the app to show a window than to have to click "About" to see 53 | // that updates are working. 54 | //------------------------------------------------------------------- 55 | let win; 56 | 57 | function sendStatusToWindow(text) { 58 | log.info(text); 59 | win.webContents.send('message', text); 60 | } 61 | function createDefaultWindow() { 62 | win = new BrowserWindow({ 63 | webPreferences: { 64 | nodeIntegration: true, 65 | contextIsolation: false 66 | } 67 | }); 68 | win.webContents.openDevTools(); 69 | win.on('closed', () => { 70 | win = null; 71 | }); 72 | win.loadURL(`file://${__dirname}/version.html#v${app.getVersion()}`); 73 | return win; 74 | } 75 | autoUpdater.on('checking-for-update', () => { 76 | sendStatusToWindow('Checking for update...'); 77 | }) 78 | autoUpdater.on('update-available', (info) => { 79 | sendStatusToWindow('Update available.'); 80 | }) 81 | autoUpdater.on('update-not-available', (info) => { 82 | sendStatusToWindow('Update not available.'); 83 | }) 84 | autoUpdater.on('error', (err) => { 85 | sendStatusToWindow('Error in auto-updater. ' + err); 86 | }) 87 | autoUpdater.on('download-progress', (progressObj) => { 88 | let log_message = "Download speed: " + progressObj.bytesPerSecond; 89 | log_message = log_message + ' - Downloaded ' + progressObj.percent + '%'; 90 | log_message = log_message + ' (' + progressObj.transferred + "/" + progressObj.total + ')'; 91 | sendStatusToWindow(log_message); 92 | }) 93 | autoUpdater.on('update-downloaded', (info) => { 94 | sendStatusToWindow('Update downloaded'); 95 | }); 96 | app.on('ready', function() { 97 | // Create the Menu 98 | const menu = Menu.buildFromTemplate(template); 99 | Menu.setApplicationMenu(menu); 100 | 101 | createDefaultWindow(); 102 | }); 103 | app.on('window-all-closed', () => { 104 | app.quit(); 105 | }); 106 | 107 | // 108 | // CHOOSE one of the following options for Auto updates 109 | // 110 | 111 | //------------------------------------------------------------------- 112 | // Auto updates - Option 1 - Simplest version 113 | // 114 | // This will immediately download an update, then install when the 115 | // app quits. 116 | //------------------------------------------------------------------- 117 | app.on('ready', function() { 118 | autoUpdater.checkForUpdatesAndNotify(); 119 | }); 120 | 121 | //------------------------------------------------------------------- 122 | // Auto updates - Option 2 - More control 123 | // 124 | // For details about these events, see the Wiki: 125 | // https://github.com/electron-userland/electron-builder/wiki/Auto-Update#events 126 | // 127 | // The app doesn't need to listen to any events except `update-downloaded` 128 | // 129 | // Uncomment any of the below events to listen for them. Also, 130 | // look in the previous section to see them being used. 131 | //------------------------------------------------------------------- 132 | // app.on('ready', function() { 133 | // autoUpdater.checkForUpdates(); 134 | // }); 135 | // autoUpdater.on('checking-for-update', () => { 136 | // }) 137 | // autoUpdater.on('update-available', (info) => { 138 | // }) 139 | // autoUpdater.on('update-not-available', (info) => { 140 | // }) 141 | // autoUpdater.on('error', (err) => { 142 | // }) 143 | // autoUpdater.on('download-progress', (progressObj) => { 144 | // }) 145 | // autoUpdater.on('update-downloaded', (info) => { 146 | // autoUpdater.quitAndInstall(); 147 | // }) 148 | --------------------------------------------------------------------------------