Summary
PrivateGitHubProvider.getLatestVersionInfo selects the latest release with:
return version.find(it => it.prerelease) || version[0];
There is no filter on release.draft. The GitHub /releases API returns releases ordered by created_at desc, and authenticated requests include drafts. So a single draft release with prerelease: true (e.g. left over from an electron-builder publish run that failed before flipping draft: false) becomes the "latest version" for every client, blocking real published releases that come later in the array.
Source link in v6.8.4
Reproduction
- Configure
autoUpdater.setFeedURL({ provider: 'github', owner: '…', repo: '…', private: true, token: '…' }) with allowPrerelease = true against a private repo.
- On that repo, ensure there are several published prereleases (e.g.
v1.0.0-alpha.20 through v1.0.0-alpha.30, all prerelease: true, draft: false).
- Create a draft prerelease with an older tag, e.g.
gui-v1.0.0-alpha.18 (prerelease: true, draft: true).
- Trigger
autoUpdater.checkForUpdates().
- Observed: the updater offers
v1.0.0-alpha.18 as the available update.
- Expected: the updater offers
v1.0.0-alpha.30 (the highest published prerelease).
The draft has a created_at newer than the published releases (or matches them, with id ordering favouring the draft), so it appears first in the /releases array, and .find(it => it.prerelease) returns it.
Why this matters
- electron-builder's own publish flow regularly creates drafts and only flips them to
draft: false on success. A failed publish (notarisation flake, signing error, network issue mid-upload) leaves a draft. End users are then silently steered to that draft on every check, even though it was never meant to be released.
- For private repos the draft is invisible via the regular UI to non-collaborators, so triage is harder than for public repos.
- The 'wrong release wins .find()' is permanent until the draft is manually deleted on GitHub.
Suggested fix
// Filter drafts first, then prefer the prerelease, fall back to any non-draft.
const candidates = version.filter(it => !it.draft);
return candidates.find(it => it.prerelease) || candidates[0] || version[0];
(|| version[0] preserved as a safety net for the empty-published-but-has-drafts case, though arguably that should throw.)
Workaround for affected users
Delete the offending draft on GitHub (Releases → Drafts → delete). Until upstream is fixed, project release workflows should clean up their own staging drafts on failure.
Environment
- electron-updater: 6.8.3 (verified the same code is in 6.8.4)
- Reproduced against: GitHub Enterprise Cloud, private repo
- Provider: PrivateGitHubProvider (i.e.
private: true in setFeedURL)
Summary
PrivateGitHubProvider.getLatestVersionInfoselects the latest release with:There is no filter on
release.draft. The GitHub/releasesAPI returns releases ordered bycreated_at desc, and authenticated requests include drafts. So a single draft release withprerelease: true(e.g. left over from an electron-builder publish run that failed before flippingdraft: false) becomes the "latest version" for every client, blocking real published releases that come later in the array.Source link in v6.8.4
Reproduction
autoUpdater.setFeedURL({ provider: 'github', owner: '…', repo: '…', private: true, token: '…' })withallowPrerelease = trueagainst a private repo.v1.0.0-alpha.20throughv1.0.0-alpha.30, allprerelease: true, draft: false).gui-v1.0.0-alpha.18(prerelease: true, draft: true).autoUpdater.checkForUpdates().v1.0.0-alpha.18as the available update.v1.0.0-alpha.30(the highest published prerelease).The draft has a
created_atnewer than the published releases (or matches them, with id ordering favouring the draft), so it appears first in the/releasesarray, and.find(it => it.prerelease)returns it.Why this matters
draft: falseon success. A failed publish (notarisation flake, signing error, network issue mid-upload) leaves a draft. End users are then silently steered to that draft on every check, even though it was never meant to be released.Suggested fix
(
|| version[0]preserved as a safety net for the empty-published-but-has-drafts case, though arguably that should throw.)Workaround for affected users
Delete the offending draft on GitHub (Releases → Drafts → delete). Until upstream is fixed, project release workflows should clean up their own staging drafts on failure.
Environment
private: trueinsetFeedURL)