Squirrel.windows: Align with Squirrel.Mac

Created on 8 Jun 2015  Â·  7Comments  Â·  Source: Squirrel/Squirrel.Windows

This project definitely works very well for most use cases. But there are a few ideas which I think are worth discussing for future _breaking_ changes, specifically about the current divergence from Squirrel/Squirrel.Mac.

Here's what I really like about how things are currently done:

  • I can use Squirrel.Windows to wrap pretty much any executable there is, thanks to --squirrel-install & friends;
  • There are tools that help me easily create update packages and setup executables for distribution.

Here's what I like about the Mac counterpart and believe this project could benefit too from adopting them:

  • The need for a smart server which can answer fine-grained questions such as _does this paid Windows 7 user from Switzerland need an update?_
  • An absolute ignorance of the product's version and versioning scheme; whatever the server tells the client to update to, that's what'll get installed;
  • A zip archive of my application files serves as both the distribution and the update package.

These points enable users to do very cool things such as selective updates and high-frequency continuous deployments; things that are only possible nowadays using Squirrel.Windows with a bit of software acrobatics.

Correct me if I'm wrong but I assume NuGet to be the main technology holding the project back from these points, since it surfaces both in the current packaging format and the server protocol.

Given that, I would love a solution in which:

  • The tooling could create a Setup.exe given

    1. a zip archive of the application to distribute (up to the user to create); and

    2. a declarative metadata file with properties such as setup.exe icon, location to main executable, etc;

  • The same zip archive could be used as the full update package;
  • Update.exe could be dumber than currently, merely behaving according to a smarter server, just like in Squirrel.Mac.

@paulcbetts Let me know your thoughts.

All 7 comments

Here's what I like about the Mac counterpart

Hah! These are mostly things about the Mac counterpart that I hate :) One of the red threads about Squirrel.Windows is that you _don't_ have to set up a server, S3 is your server. Or Blob storage. Or whatever.

That being said, I think we can mostly get what you're looking for wrt server-side update logic without any breaking changes, so people can run updates in an Squirrel.Mac style if they _want_ to, or they can just do updates with Squirrel.Windows Zen Natureâ„¢ and implement the _paid Windows 7 user from Switzerland need an update?_ logic on the client side.

So basically, you could write a server which would dynamically serve up RELEASES - the only thing we're missing is a way to provide information _to_ the server, which we could pass in as the query string. (i.e. instead of just requesting https://myserver.com/update/RELEASES, we'd request https://myserver.com/update/RELEASES?os=win7&locale=switzerland&paid=datmoney). Then, your server can then return what it wants for RELEASES.

Thoughts?

I do see the value of pure directory serving. I just wonder if that's both the majority of your users and the lowest common denominator of what the framework could offer.

On the project I'm working at I actually implemented that. The update server has a dynamic /releases route and returns URLs, which themselves 302 to the real bits.

Understanding the protocol wasn't the a big problem. Not as big as getting nightly builds deployed under such a mechanism. This was a must-have: we want to selfhost on the update mechanism ourselves, so every build our CI server runs ends up as an automatic update for ourselves.

Now, in order for the wheels to turn, the version listed on the /releases response must be semver-higher than the version the client uses. Considering that Squirrel.Windows owns the labels on the semver version of my app -full and -delta (ignoring the fact that these aren't taken into account for version sorting) I'm left with the major, minor and patch version numbers to play with. My solution: the server simply increments the patch version number by 1 to whatever version is sent by the client, making the patch number unreliable for any measure of tracing. The consequence: every time we release, we can only touch the major or minor version in order to avoid getting Squirrel.Windows confused. On the Mac platform, since the versions are fully ignored, I can even use a git commit hash as a release identifier. Works very nicely.

Finally, I can't simply upload the file somewhere and point to it from my webserver. I must also save its SHA1 sum and size, save it somewhere and have the server read that so it returns the correct values on the /releases request. Security measure or otherwise, it's yet another infrastructure I've forced to build.

Hopefully this puts my point of view in writing and argues for my suggestions. Let me know if you have suggestions on how I can simplify my process.

Considering that Squirrel.Windows owns the labels on the semver version of my app -full and -delta (ignoring the fact that these aren't taken into account for version sorting) I'm left with the major, minor and patch version numbers to play with.

So, while NuGet _suggests_ you use SemVer (and warns you if you don't), you can actually use the 4th digit of the version number, that's supported today. While this doesn't 100% solve your problem, at least it helps?

Finally, I can't simply upload the file somewhere and point to it from my webserver. I must also save its SHA1 sum and size, save it somewhere and have the server read that so it returns the correct values on the /releases request. Security measure or otherwise, it's yet another infrastructure I've forced to build.

The SHA1 / Size isn't for security so much as ensuring download integrity - if we downloaded and applied updates without checking them, we would see a _lot_ of failures. HTTPS is generally the mechanism we trust to ensure that files have not been tampered with, and that we're talking to the person we say we are.

For what it's worth, here's what we do for part of the problem: We have a number of channels (alpha, beta, release, + one enterprise-customer-specific one). Our CI server has builds for each,with only the alpha being automatically triggered. The squirrel output for each is put in a different S3 folder, named after the channel. The application knows which channel it is on, so it when it goes looking for updates, it looks in the corresponding folder.

@hatton Yep, your design is basically how Squirrel was intended to be used, that to support multiple update channels, you just use different URLs

@joaomoreno thanks for starting this. I'm writing something on Electron right now, so that's what brought me here. I was wondering what the fundamental reason for divergence was. I assumed there was something on the client-sidethat needed to be different because Windows was awkward in some way, but it seems now like it's just a design choice?

@hatton why can't what you're saying be done with Squirrel.Mac?

Disclaimer: I've had a lot more experience in this area with NW.js (no Squirrel at all). I've done something like @hatton said on S3 with node-webkit-updater. The client hits a latest.json in a channel's directory, parses the version and if it's higher (semver), then it downloads it in the background (the URL is in latest.json). The downloads are just versioned directories alongside the latest.json. As far as I know, the server setup needed for Squirrel.Mac is really simple, so I don't see why it can't check S3 and stuff.

I guess I'm not sure I see the reason why you can't support multiple update channels with Squirrel.Mac but you can with Squirrel.Windows.

@joaomoreno Sorry, I don't know anything about Squirrel.Mac.

Was this page helpful?
0 / 5 - 0 ratings