├── .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 |
--------------------------------------------------------------------------------