Skip to content

PrivateGitHubProvider: getLatestVersionInfo does not filter out draft releases when searching for latest version #9691

@ppatel-volley

Description

@ppatel-volley

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

  1. Configure autoUpdater.setFeedURL({ provider: 'github', owner: '…', repo: '…', private: true, token: '…' }) with allowPrerelease = true against a private repo.
  2. 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).
  3. Create a draft prerelease with an older tag, e.g. gui-v1.0.0-alpha.18 (prerelease: true, draft: true).
  4. Trigger autoUpdater.checkForUpdates().
  5. Observed: the updater offers v1.0.0-alpha.18 as the available update.
  6. 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)

Metadata

Metadata

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions