electron-builder: 17.1.1
target: 'nsis'
Sorry for the long post.
I've been working on getting an app to autoupdate with electron-updater and nuts server. After reading much of the source code and trying most configs, I've landed here for help. Let me explain some of the approaches I have taken and the results from each.
I am building for both Mac and Windows. I was able to get Mac's autoupdate to work with electron's native autoUpdate module. However, building for nsis did not allow me to continue with that module for Windows. I have switched to electron-updater, building the app with electron-builder. Note, I am using Nuts as a release server, with a private Github repo connected (yes, GH_TOKEN is set).
"publish": [
{
"provider": "generic",
"url": "https://example.herokuapp.com/download"
},
{
"provider": "github",
}
],
This is the suggested config in this issue. Hopeful, I worked with this for a while, but I continued to receive a "Cannot parse JSON" error when checkForUpdates ran. I narrowed down the issue to my config url. Since it is set to /download, electron-updater attempts to find the latest-mac.json at /download/latest-mac.json. Believe it or not, Nuts just serves the latest release at this route. The actual build file was being downloaded. So, it made sense that there was a JSON parse error, since it was trying to parse a .zip file!
"publish": [
{
"provider": "generic",
"url": "https://example.herokuapp.com/download/latest"
},
{
"provider": "github",
}
],
After discovering the error in my first config, I set the url to /download/latest. Since now I knew electron-updater would add /latest-mac.json to my url, /download/latest/latest-mac.json correctly serves the latest-mac.json file from Github. I thought everything would be fixed, but I got errors after the update-available event saying the release url was invalid. Puzzled (because the latest-mac.json file generated looked correct), I decided to manually check the file by downloaded it from /download/latest/latest-mac.json.
The /download/latest/latest-mac.json file looked like this.
{
"version": "0.10.0",
"releaseDate": "2017-04-28T01:53:36.389Z",
"url": "https://github.com/exampleowner/examplerepo/releases/download/v0.10.0/AppName-0.10.0-mac.zip"
}
See how the url points to the GitHub release? That confused me, because my local latest-mac.json was pointing to my release server, not GitHub. After further digging, I discovered that electron-builder creates a github folder with a custom latest-mac.json in there. That custom file is what's published to GitHub. So, this direct GitHub link may work for the majority of apps, but since my repo is private, I was getting "unavailable url" errors.
This seems like a bug? The GitHub version of latest-mac.json should not be uploaded if there is a generic provider. Only the generic latest-mac.json should be uploaded.
Even so, I figured it was easy enough to work around. I would just manually overwrite the latest-mac.json file uploaded to Github with my correct local latest-mac.json file. That cleared the "unavailable url" error, but there were still errors thrown. Looking at my "correct" latest-mac.json (the one generated in the root build directory by electron-builder), I saw that it was pointing to an invalid route on my release server.
Here's the root latest-mac.json file:
{
"version": "0.10.0",
"releaseDate": "2017-04-28T20:45:52.703Z",
"url": "https://example.herokuapp.com/download/latest/AppName-0.10.0-mac.zip"
}
See the url field? On the Nuts server, that path leads to a 500 error. To get it to work, I had to remove the /latest path to turn it into this: https://example.herokuapp.com/download/AppName-0.10.0-mac.zip. That path correctly downloads the file.
This is a doable work-around, yet it removes the ability to successfully publish to GitHub with electron-updater. Instead, the originally uploaded github/latest-mac.json file must be removed from the GitHub release, and then this /latest-mac.json must be manually updated and then uploaded to the GitHub release. Not great, but not horrible. Ideally, since the config url must be set to /download/latest for the latest-mac.json to be found correctly on the Nuts server, there would be a way to alternately set an additional base url for the download url, which would be /download in this case.
Anyways, after clearing those errors, electron-updater could not read the file after it was downloaded by electron-updater.
When using electron's native autoUpdater module, I would manually set the feed url to the Nuts route https://example.herokuapp.com/update/${platform}/${version}. After the autoUpdater module downloaded this file, it would successfully unpack and updating the app.
However, after switching to electron-updater, I'm getting these "read" errors after the latest version is downloaded (running the app with DEBUG=electron-builder).
Wait for app ready
Checking for update
electron-builder request: {
electron-builder "hostname": "example.herokuapp.com",
electron-builder "path": "/download/latest/latest-mac.json",
electron-builder "protocol": "https:",
electron-builder "headers": {
electron-builder "User-Agent": "electron-builder",
electron-builder "Cache-Control": "no-cache"
electron-builder }
electron-builder } +0ms
electron-builder Response status: 200 OK, request options: {
electron-builder "hostname": "example.herokuapp.com",
electron-builder "path": "/download/latest/latest-mac.json",
electron-builder "protocol": "https:",
electron-builder "headers": {
electron-builder "User-Agent": "electron-builder",
electron-builder "Cache-Control": "no-cache"
electron-builder }
electron-builder } +13s
Found version 0.18.5 (url: https://example.herokuapp.com/download/AppName-0.10.0-mac.zip)
Downloading update from https://example.herokuapp.com/download/AppName-0.10.0-mac.zip
2017-04-28 16:40:26.548 AppName[46751:2396017] Download completed to: file:///Users/derekduncan/Library/Caches/com.appname.AppName.ShipIt/update.zcSpOeW/AppName-0.10.0-mac.zip
{ Error: ditto: Couldn't read PKZip signature
preventDefault: [Function: preventDefault],
sender:
AutoUpdater {
_events: { error: [Function], 'update-downloaded': [Function] },
_eventsCount: 2 } }
Error: Error: ditto: Couldn't read PKZip signature
Specifically, see the Error: Error: ditto: Couldn't read PKZip signature. It could be related to #1492, but there isn't a solution there yet, so not sure.
So, I finally got electron-updater to find and download the new version, but it cannot read it. I obviously want to apply these changes to Windows auto updating as well, but I need to resolve these Mac errors first.
I'm not sure what to try next, as I've already read a lot of source code and tried all different configs. I need some help to continue using electron-updater, and I will gladly create a PR to add all my learnings to the docs once this is resolve.
Thanks for all your hard work.
@derek-duncan Did you ever find a workaround or solution for this? I'm stuck at this step too where I'm flip-flopping between a Windows build working and a mac build working but neither at the same time. I'm using the exact setup are are/were (nuts, config)
Wondering if I should head another direction.
@tlackemann yep! I'll post the solution in the morning :)
@derek-duncan No worries! I ended up patching something together.
I ended up adding S3 as another publish option. Across the code, it looks something like this
// package.json
{
"provider": "generic",
"url": "https://example.herokuapp.com/download"
},
{
"provider": "github"
},
{
"provider": "s3",
"bucket": "example-releases",
"path": "${version}"
}
// wherever autoUpdater lives
const { platform } = process
if (platform === 'darwin') {
autoUpdater.setFeedURL({
provider: 's3',
bucket: 'example-releases',
})
}
}
If the platform is Windows, updates come from Nuts/Windows.Squirrel. If macOS, I default to grabbing it from S3 since I encountered that same bug(?) with Nuts that you did.
There's a small manual step of moving the release files from the S3 folder into the main bucket but I'm okay with this for now (easy enough to write a Webhook into our API.)
Hope this helps although would be eager to hear your solution!
Nuts provider is planned and will be released soon.
@develar was the nuts provider released? Or is there a solution for this?
@kitze No. And in general no need — consider to use S3 (amazon, digital ocean) or GitHub.
If someone still looking for this solution, I use https://my-updater.herokuapp.com/download/latest as feed URL. Based on this route https://github.com/GitbookIO/nuts/blob/master/lib/nuts.js#L57 auto-updater will download latest-mac.yml automatically at https://my-updater.herokuapp.com/download/latest/latest-mac.yml.
Here's my snippet:
const { autoUpdater } = require('electron-updater')
app.on('ready', () => {
autoUpdater.setFeedURL({
provider: 'generic',
url: 'https://my-updater.herokuapp.com/download/latest'
})
autoUpdater.checkForUpdatesAndNotify()
...
})
Most helpful comment
Nuts provider is planned and will be released soon.