You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When the following conditions are met in an electron app that uses electron-updater:
GitHubProvider is used
autoUpdater.allowPrerelease = true
No explicit update channel is set
The electron app is currently in a stable version
if autoUpdater.checkForUpdates is called, GitHubProvider.getLatestVersion method will pick the version of the first release entry in the GitHub Releases Atom feed without any validation, regardless of what that first release is!
While this current behavior works just fine in a repository dedicated to a single Electron app where every consecutive release is naturally a newer version, it becomes an issue in monorepos where other sub-packages are also released with their own custom tags in the same repository alongside an Electron app that uses electron-updater.
Example:
If the GitHub Releases Atom feed looks like this (very possible in monorepos):
<feed>
<entry>
<title>some-packageA@1.27.2</title>
</entry>
<entry>
<title>v3.0.0-beta.1</title> <!-- what's supposed to be picked and offered as the new available update -->
</entry>
<entry>
<title>v2.3.0</title>
</entry>
<entry>
<title>v2.2.0</title>
</entry>
<entry>
<title>some-toolB@3.0.0</title>
</entry>
<entry>
<title>v2.1.0</title>
</entry>
</feed>
GitHubProvider.getLatestVersion will pick "some-packageA@1.27.2" release as the latest version just because it's the first release to appear in the GitHub Releases Atom feed!, and that will cause autoUpdater.checkForUpdates to throw "Cannot find latest-linux.yml in the latest release artifacts" error every time it's called blocking the update process completely.
The cause of the bug:
This problem comes from here (line 69 and line 79 specifically):
At line 69, latestRelease variable is initialized with the first entry in the GitHub Releases Atom feed,
which seems to me an unnecessary initialization as we can't be 100% sure that the first entry in the feed is always the latest/newest version, and we were going to update latestRelease variable anyway in later steps when we select the right latest release.
Then if the required conditions are met and the code reached line 79, the version/tag of latestRelease will be assigned to tag variable, which means "this is the version/tag of the release we are going to pick and offer as the new update to users"
Bug Reproduction
I created a simple single-file electron app in issue-reproduction branch on my electron-builder fork to reproduce the bug.
I added the app as a new package in the pnpm workspace under packages/app directory so it can use electron-updater by depending on it this:
I made it this way because after you reproduce the bug, you can apply a fix to the packages/electron-updater package in the codebase, re-compile, run the app and see the result of your fix in the same place.
Enter electron-updater_issue-reproduction, Install dependencies and compile packages
cd electron-updater_issue-reproduction && pnpm install && pnpm run compile
Run the reproduction app and see the error
pnpm run --filter=./packages/app reproduce
You should see an error like this:
Error: Cannot find latest-linux.yml in the latest release artifacts (https://github.com/AbdulrhmanGoni/electron-updater-playground/releases/download/xyz%402.0.0/latest-linux.yml): HttpError: 404
...
The important thing to notice in the error message is the link between the parentheses, which tells us from which release the updater tried to get the update file (latest-linux.yml, latest-mac.yml, or latest.yml), we can infer from this link that the updater picked xyz@2.0.0 release (which isn't the expected one) as the latest version.
You can take a look at the Atom feed of the repository where this reproduction electron app is configured to look for updates from, and notice that xyz@2.0.0 release comes first in the atom feed, which is why the updater picked it.
Solution
I think a proper solution could be replacing line 79 with a loop that goes through the releases atom feed and finds the newest release (whether it's a pre-release or a stable release) and reassigns latestRelease and tag variables with it:
We can also initialize the latestRelease variable with null at line 69 just like tag variable because these variables are going to be reassigned later with the actual latest release/version anyway, therefore there is no need to initialize them with something earlier.
If you are on Windows or Mac, implemented the fix and run the reproduction app, you are still going to see the "Cannot find latest.yml in the latest release artifacts" error because the repository where the updates are pulled from doesn't in fact have update files for these two platforms, so to check if your fix works and the updater actually picks the right release (which is v2.0.0, not xyz@2.0.0), just look at the link in the error message and check if it's a download link to an asset of the v2.0.0 release.
Description
When the following conditions are met in an electron app that uses
electron-updater:GitHubProvideris usedautoUpdater.allowPrerelease = trueif
autoUpdater.checkForUpdatesis called,GitHubProvider.getLatestVersionmethod will pick the version of the first release entry in the GitHub Releases Atom feed without any validation, regardless of what that first release is!While this current behavior works just fine in a repository dedicated to a single Electron app where every consecutive release is naturally a newer version, it becomes an issue in monorepos where other sub-packages are also released with their own custom tags in the same repository alongside an Electron app that uses
electron-updater.Example:
If the GitHub Releases Atom feed looks like this (very possible in monorepos):
GitHubProvider.getLatestVersionwill pick "some-packageA@1.27.2" release as the latest version just because it's the first release to appear in the GitHub Releases Atom feed!, and that will causeautoUpdater.checkForUpdatesto throw "Cannot find latest-linux.yml in the latest release artifacts" error every time it's called blocking the update process completely.The cause of the bug:
This problem comes from here (line 69 and line 79 specifically):
electron-builder/packages/electron-updater/src/providers/GitHubProvider.ts
Lines 67 to 80 in 319535a
At line 69,
latestReleasevariable is initialized with the first entry in the GitHub Releases Atom feed,which seems to me an unnecessary initialization as we can't be 100% sure that the first entry in the feed is always the latest/newest version, and we were going to update
latestReleasevariable anyway in later steps when we select the right latest release.Then if the required conditions are met and the code reached line 79, the version/tag of
latestReleasewill be assigned totagvariable, which means "this is the version/tag of the release we are going to pick and offer as the new update to users"Bug Reproduction
I created a simple single-file electron app in
issue-reproductionbranch on myelectron-builderfork to reproduce the bug.I added the app as a new package in the pnpm workspace under
packages/appdirectory so it can useelectron-updaterby depending on it this:I made it this way because after you reproduce the bug, you can apply a fix to the
packages/electron-updaterpackage in the codebase, re-compile, run the app and see the result of your fix in the same place.Follow these steps to reproduce the bug:
issue-reproductionbranch ofAbdulrhmanGoni/electron-builderfork intoelectron-updater_issue-reproductiondirectoryelectron-updater_issue-reproduction, Install dependencies and compile packagesYou should see an error like this:
The important thing to notice in the error message is the link between the parentheses, which tells us from which release the updater tried to get the update file (latest-linux.yml, latest-mac.yml, or latest.yml), we can infer from this link that the updater picked
xyz@2.0.0release (which isn't the expected one) as the latest version.You can take a look at the Atom feed of the repository where this reproduction electron app is configured to look for updates from, and notice that
xyz@2.0.0release comes first in the atom feed, which is why the updater picked it.Solution
I think a proper solution could be replacing line 79 with a loop that goes through the releases atom feed and finds the newest release (whether it's a pre-release or a stable release) and reassigns
latestReleaseandtagvariables with it:We can also initialize the
latestReleasevariable withnullat line 69 just liketagvariable because these variables are going to be reassigned later with the actual latest release/version anyway, therefore there is no need to initialize them with something earlier.Note
If you are on Windows or Mac, implemented the fix and run the reproduction app, you are still going to see the "Cannot find latest.yml in the latest release artifacts" error because the repository where the updates are pulled from doesn't in fact have update files for these two platforms, so to check if your fix works and the updater actually picks the right release (which is v2.0.0, not xyz@2.0.0), just look at the link in the error message and check if it's a download link to an asset of the v2.0.0 release.