electron / update.electronjs.org

📡 A free service that makes it easy for open-source Electron apps to update themselves.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Does not support multiple Windows architectures at the same time

jviotti opened this issue · comments

As pointed out by @dsanders11 and discussed in the last Ecosystem WG meeting (cc @erickzhao @Toinane), this project causes problems for applications supporting multiple Windows architectures, due to how Squirrel.Windows works and the features offered by GitHub Releases.

Summary

If multiple architectures for Windows are supported, the latest build to post its files to GitHub Releases will be the active one. This problem is seen on Electron Fiddle. If x86 is published after x64, then any x64 application will silently and automatically update to x86. The problem is exacerbated by the fact that Electron Fiddle now supports Windows for ARM. If such build is the latest one to be published, the setup of all non-ARM users is suddenly broken.

Problem

Using Squirrel.Windows to package an application typically results in 3 artifacts:

  • The setup executable used for first-time installs. This binary includes the architecture on its file name.
  • The nupkg package for updates (with or without deltas). This ZIP includes the architecture on its file name.
  • A RELEASES text file that includes the name to the nupkg package.

When an Electron.js application tries to auto-update itself, it asks update.electronjs.org for the latest RELEASES file. If the contents described there are different from what the local user has, then the corresponding nupkg is downloaded and the auto-update process kicks-in.

GitHub Releases offers a simple flat bucket for files. When multiple Squirrel.Windows builds targeting different architectures are uploaded to the same GitHub Releases entry, the latest RELEASES file to be uploaded takes precedence, whether that file corresponds to the right architecture or not.

Common Solutions

What people typically for proprietary apps (including Postman) is to include the architecture in the URL where the RELEASES file is uploaded. However, this strategy is not possible using GitHub Releases given its flat structure.

Proposed Solution

I believe there is a path forward that is backwards-compatible and does not require making significant changes to Squirrel.Windows, which is currently unmaintained and not taking any further PRs. I'll take Electron Fiddle as an example, but the solution should work for any Squirrel.Windows-powered app.

  • Modify packaging tools that make use of Squirrel.Windows such as electron-forge to output both a RELEASES file and a RELEASES-<arch> file. We will be using the latter, but the former is kept for backwards-compatibility.

  • Modify the HTTP endpoint provided by update.electronjs.org to redirect requests for the RELEASES file to the corresponding RELEASES-<arch> file on GitHub Releases. If such file is not there, fallback to RELEASES. The server knows which architecture is requested as such information is present on the URL.

Given these changes, an app like Electron Fiddle will publish RELEASES-x64, RELEASES-x86 and RELEASES-arm64 files and update.electronjs.org will resolve requests for updates correctly. The changes to i.e. electron-forge would be considered minor changes and most people using this service will be upgraded automatically.

What do you think? Its a pity we have to change various components to make this work, but I can't think of a better way that preserves backwards-compatibility without introducing significant changes to Squirrel.Windows (and potentially releases a major version of it).

@dsanders11 and I can help lead the fixes if we agree on the approach.

@jviotti, great write-up of the problem.

Modify packaging tools that make use of Squirrel.Windows such as electron-forge to output both a RELEASES file and a RELEASES- file. We will be using the latter, but the former is kept for backwards-compatibility.

The nupkg also needs the architecture added to the name. Outputting a duplicate of nupkg, one with the current name, one with the name with the architecture, doesn't seem like a great option to me, I know someone who doesn't use GitHub releases will complain about the unnecessary duplicated nupkg since it's another 100+ MB. We also don't want duplicate files with different names being uploaded to GitHub releases as artifacts, since that's messy.

I propose we update @electron-forge/maker-squirrel to allow configurable names for the nupkg and RELEASES file, like it currently allows for setupExe, and change their default names to include the architecture. Then anyone who upgrades and experiences breakage for their usage of @electron-forge/maker-squirrel can simply change their config to put them back to what they were before this change.

Modify the HTTP endpoint provided by update.electronjs.org to redirect requests for the RELEASES file to the corresponding RELEASES- file on GitHub Releases. If such file is not there, fallback to RELEASES. The server knows which architecture is requested as such information is present on the URL.

I think this fallback behavior could be problematic, if new releases include both say a RELEASES-x64 and a RELEASES file. I think any GitHub release with the architecture suffixes on RELEASES should not include a bare RELEASES, otherwise you could have behavior where an app drops 32-bit Windows support, the app tries to update, the RELEASES-ia32 file isn't found, so it falls back to RELEASES, which say is the 64-bit version, and now that app updates to the wrong architecture, rather than simply seeing no release as available, which is the ideal behavior.

This issue refs electron/fiddle#694 as well, so let's make sure that gets closed once this is resolved.

@dsanders11

The nupkg also needs the architecture added to the name.

Ah, I totally missed that one. I was under the impression the nupkg did include the architecture, but I was indeed wrong.

I propose we update @electron-forge/maker-squirrel to allow configurable names for the nupkg and RELEASES file, like it currently allows for setupExe, and change their default names to include the architecture. Then anyone who upgrades and experiences breakage for their usage of @electron-forge/maker-squirrel can simply change their config to put them back to what they were before this change.

My only concern with that approach is that everyone using update.electronjs.org will have to tweak their settings to make their applications work. I'm not sure how many people use this service, but I was thinking it would be cool to have it fixed and working for everybody out of the box. Do you know how big the list of users is?

I think this fallback behavior could be problematic, if new releases include both say a RELEASES-x64 and a RELEASES file. I think any GitHub release with the architecture suffixes on RELEASES should not include a bare RELEASES, otherwise you could have behavior where an app drops 32-bit Windows support, the app tries to update, the RELEASES-ia32 file isn't found, so it falls back to RELEASES, which say is the 64-bit version, and now that app updates to the wrong architecture, rather than simply seeing no release as available, which is the ideal behavior.

The fallback file is mainly for people that use other backends for Squirrel.Windows, as none of them would be aware of the architecture-suffixed RELEASES. It would also not work for people using GitHub Releases but other Squirrel.Windows open-source backends.

The drop of architecture support is a very good point though. I think we can not provide the fallback on the update.electronjs.org routing but still keep the file in there, and then it would work for everyone (at least where "work" means with potentially the current issue :P)

@dsanders11 @jviotti I'm open to picking this up in the coming week :)

Hello @jviotti and @dsanders11. Thanks so much for this detailed explanation of this problem and outlining proposed solutions for this problem. I am actively working on an open-source electron project, and we just started releasing an application for windows x64 via update.electronjs.org. The service seems to be working well so far!

We are keen to be able to support multiple architectures moving forward. @twitharshil, I'm wondering if you know where this issue landed? Are there any plans to pick up on this issue / known workarounds to support multiple architectures? Any recommendations if update.electronjs.org cannot support this moving forward?

If there is a workable path forward to enable this feature and alignment on a solution, I would be happy to contribute code and help find resources to support this initiative. Any help or guidance for navigating this issue would be greatly appreciated. Thanks!