Closed ubruhin closed 7 months ago
What about not using a classical installer, but building an MSIX instead? https://learn.microsoft.com/en-us/windows/msix/overview We do that for Threema Desktop, it's quite painless and Windows ships all necessary tools.
Only caveat: Signing is required.
Sure, I do not care about the packaging method as long as it fulfills the criteria listed above. But yes, if there's an alternative which doesn't require signing, that would be a very good reason to decide against MSIX.
Note: One advantage of a MSIX would be that you can upload it to the Microsoft store. (I'm not sure if that's desireable or not though, in the case of LibrePCB.)
The Windows Package Manager supports MSIX, MSI, and executable installers. Some well known formats (Inno, Nullsoft, WiX, and Burn) provide standard sets of installer switches to provide different installer experiences.
Written in documents of microsoft/winget-pkgs
Despite from uploading package to Microsoft Store, submit a manifest of this package to The Windows Package Manager Community Repository will be another choice. Users can install this package by invoking winget install -s winget LibrePCB.LibrePCB
.
Solving this issue will make librepcb available to be distributed via winget and chocolatey.
Yep, this issue is now part of the NLnet sponsoring, I plan to implement it either for LibrePCB 1.1.0 or (more likely) the following release.
So I started with this task now and I think generally we have the following options:
I think *.exe installers have the advantage that they will work relatively painless on any existing or upcoming Windows version because binary compatibility between Windows versions is very good. I think we could set up such an installer today and it will still work in 5 years without spending any time for maintenance.
On the other side, I'd prefer something MSI based because it is much cleaner (e.g. easier installation, uninstallation handled by the OS instead of custom *.exe, standardized silent installation, ...). I just worry about compatibility. It seems Microsoft is changing these things all the time and does not care about compatibility too much. Especially for MSIX for me it feels like we (developers and users) are enforced to always work with the latest available Windows version, otherwise it might not work. I really don't like this mindset. Also with MSIX we will have to sign it, so we generate an additional dependency to an external company. Not nice for an open-source project.
So in the end it's a hard decision. All options are painful in my opinion. But I slightly tend to MSIX because inclusion into the Microsoft Store is a big plus (though I don't know how many users are actually using it). And even outside the Store, automatic updates can be implemented with an installer file which we can host on our server.
Let's take a look at the requirements listed in the initial post:
FOSS highly preferred
Not needed since everything comes from Microsoft directly.
Not reported as virus, ideally without requiring us to sign it
Signing needed, but I guess there's no solution available which works fine without signing. Maybe we could sign for free with SignPath, I'll ask them.
Allow upgrading older app versions
Should be possible (through Store or installer file).
Allow registering *.lpp[z] file extensions
Should be possible with the manifest file.
Somehow I don't like online installers (downloading the app on demand), so offline installation should be supported
MSIX contains the whole application.
CLI for headless & automated installation, uninstallation & update
Possible through Microsoft tools (e.g. PowerHell).
Toolkit installable in our Windows Docker image to allow building the installer on CI
Seems to work (https://github.com/LibrePCB/docker-librepcb-dev/pull/44).
Maybe support in-app updates (https://github.com/LibrePCB/LibrePCB/issues/648)?
Found some resources that this should be possible too.
Some links to MSIX:
Seems this is not so trivial :-/
So the only options left are *.exe installers, like we already have :sob: I think the main question left is which installer toolkit to use:
Although we already use the Qt Installer Framework (v3), the new major version 4 seems to be heavily improved, especially regarding unattended install which is the biggest problem of our current installer. Also I'd then switch from online installers to offline installers to allow users installing older versions (and just to simplify things).
Will now evaluate these three options...
Status update:
So I think Inno Setup is the way to go. Here's a nightly build which can be tested:
Silent install/upgrade (all options documented here):
librepcb-installer-nightly-windows-x86_64.exe /VERYSILENT /SUPPRESSMSGBOXES
Silent uninstall (all options documented here):
"C:\Program Files\LibrePCB\unins000.exe" /VERYSILENT /SUPPRESSMSGBOXES
The filename unins000.exe
is theoretically not deterministic because the number gets incremented when installing another Inno Setup software into the same directory. However, I think you can ignore this edge-case and just call unins000.exe
.
/cc @luzpaz @Dragon1573 in case you like to test this installer for usage in Chocolatey/winget, please don't publish this nightly build to users. I plan to make a new release very soon, this time with both the old installer and the new one (for a smooth migration).
@ubruhin - The above nightly build can be successfully inspected by Komac v2.1.0 and installed via winget.exe
version 1.7.10661.
[!NOTE]
We have to submit the manifest to microsoft/winget-pkgs for official tests.
There are both automated (by Azure Pipelines) and manual (by moderators) validation process. There may be some corner cases I have not tested yet. Official validation may check this installer further.
Awesome, thanks for testing! :tada:
Just two thoughts, not sure if relevant or not:
PackageVersion
in the manifest is set to 1.2.5.6-nightly - shouldn't this be the LibrePCB version (currently 1.0.1-nightly)? However, the reported DisplayVersion
is correct.winget uninstall
, is it really required to pass librepcb_is1
or would LibrePCB
also work? Just because librepcb_is1
is not intuitive for users, but unfortunately Inno Setup registers LibrePCB under this name in the Registry and this can't be changed.
- The
PackageVersion
in the manifest is set to 1.2.5.6-nightly - shouldn't this be the LibrePCB version (currently 1.0.1-nightly)? However, the reportedDisplayVersion
is correct.
From the above comments, I can't get the actual version number of this package. So I configured this to 1.2.5.6-nightly
because number 1256
in the filename.
PackageVersion
in manifest is configured manually by volunteers or contributors. They can be diverged with the DisplayVersion
and link through AppsAndFeaturesEntries
.
For most cases, volunteers or contributors will know the package version before they create the manifest. PackageVersion
is the same as DisplayVersion
.
- For
winget uninstall
, is it really required to passlibrepcb_is1
or wouldLibrePCB
also work? Just becauselibrepcb_is1
is not intuitive for users, but unfortunately Inno Setup registers LibrePCB under this name in the Registry and this can't be changed.
I haven't test this yet. I can winget list LibrePCB
to find the package, so it might by OK to just winget uninstall LibrePCB
.
There's an -e
switch (means "exact search") in my test, librepcb_is1
is required in this test case.
From the above comments, I can't get the actual version number of this package. So I configured this to 1.2.5.6-nightly because number 1256 in the filename.
Ah I see. But 1256 is just the number of this issue, not a version number :see_no_evil: Official releases will contain the version number in the filename (e.g. librepcb-installer-1.1.0-windows-x86_64.exe
for version 1.1.0). Also the version number is added as a property on the installer *.exe, but I don't know if this information can be accessed by the winget tooling:
I haven't test this yet. I can winget list LibrePCB to find the package, so it might by OK to just winget uninstall LibrePCB. There's an -e switch (means "exact search") in my test, librepcb_is1 is required in this test case.
Alright, thanks for clarifying :+1:
Official releases will contain the version number in the filename (e.g.
librepcb-installer-1.1.0-windows-x86_64.exe
for version 1.1.0).
For this case, I think volunteers or contributors may not be able to configure a wrong version number, except the bot account by Microsoft themselves (we found it behaves wierd in some corner cases).
Also the version number is added as a property on the installer
*.exe
, but I don't know if this information can be accessed by the winget tooling.
I think it can't. Not only Komac, but also wingetcreate.exe
and YamlCreate.ps1
are not able to inspect the version of package. Version information of a manifest is manually-configured. I didn't download the installer file prior to the creation of the manifest, so I make this mistake 😥
Excuse me @ubruhin, sorry to bother you again.
I see pull request #1340 is successfully merged and Qt6 based x86_64
build with InnoSetup packaged installer is finally released.
Do you interested in automating the release pipeline of The Microsoft community Windows Package Manager manifest repository via WinGet Releaser v2? It would be better maintaining a package by its owner instead of community volunteers.
However, enabling this pipeline requires at least one version of this package available in the repository. I can help creating the "very first" version of the manifest.
I see pull request https://github.com/LibrePCB/LibrePCB/pull/1340 is successfully merged and Qt6 based x86_64 build with InnoSetup packaged installer is finally released.
Wait wait wait, it's not released! :see_no_evil: Only nightly builds so far, no official release yet. So please don't publish it somewhere. Official releases will be available very soon and published at https://librepcb.org/download/.
Do you interested in automating the release pipeline of The Microsoft community Windows Package Manager manifest repository via WinGet Releaser v2? It would be better maintaining a package by its owner instead of community volunteers.
However, enabling this pipeline requires at least one version of this package available in the repository. I can help creating the "very first" version of the manifest.
Hm at the moment I don't see a need for a GitHub Action doing a release - we don't use GitHub Actions in this repository and in my experience for such a complex project it's better to do the (final step of) releasing manually. Releasing LibrePCB does not immediately mean releasing actual packages, because packages may require additional actions outside of this repository to get updated to a new version.
I agree about taking over packaging by the upstream maintainers would be nice. However, to be honest I'm already pretty busy with releasing all the other packages so I'm very happy about help of other people doing some of the packaging. Also I'm not familiar with Windows packages (don't use Windows for daily business) so the packaging & testing would be much easier for people familiar with these tools.
I'm not completely against taking it over, maybe I can look at it later. But at least for an initial version I'd be happy if someone else could do it. Of course I'm always available for any questions arising during packaging!
@Dragon1573 @luzpaz Now the new installer of the stable release 1.1.0 is available for inclusion in package managers:
https://download.librepcb.org/releases/1.1.0/librepcb-installer-1.1.0-windows-x86_64.exe
Can be silently installed/uninstalled as described in https://github.com/LibrePCB/LibrePCB/issues/1256#issuecomment-2015188804.
Excuse me @ubruhin, is there only x86_64
packaged with InnoSetup? I see there's also x86
installer file in download center.
@Dragon1573 from the release notes 1.1.0:
The move to Qt6 forced us to drop support for Windows 7, Windows 8 and any 32-bit versions — upcoming releases will require at least Windows 10 64-bit. Since Windows 7 and 8 are already end-of-life for quite some time, it is highly recommended anyway to not use these systems anymore. But for now you can still use the Qt5 builds on them.
I assume that answers your question? 🙂 I think the x86 installer is just the old, deprecated one.
@dbrgn - Thank you ❤️ x86
installer is not included in the manifest, users can only install x64
build by winget.exe
Yeah, the plan is that x86
releases won't be available anymore for upcoming releases, only x86_64
then.
SUMMARY
So far in my own tests, our installer did run on every Windows but initially it's blocked by some antivirus and requires to click a few (hidden) buttons to start it anyway. It's so cumbersome that some users might not even find this option, thinking the *.exe is a virus.
Another problem is that it seems the installer does not recognize already installed, older versions of LibrePCB. For example if LibrePCB 0.1.7 is installed, and you run the LibrePCB 1.0.0 installer, it reports that the directory "C:\Program Files\LibrePCB" (or something like that) already exists and rejects installing LibrePCB 1.0.0 unless you manually uninstall 0.1.7 first. This is not really user friendly, an installer shall allow to upgrade an installed older application version.
SOLUTION
For the antivirus problem, the most obvious solution would be to sign the installer. However, this costs money and probably it's a bit cumbersome to set it up.
Anyway, I think the main question is whether the Qt installer framework is really the right thing for us. Initially it made sense because we also provided installers for Linux and macOS, so a cross-platform installer framework made things simpler. But starting with LibrePCB 1.0.0, we do not provide these installers anymore, the only installer left is for Windows. So now we could switch to a Windows-only installer framework if there's something better.
Thus I'd propose to evaluate what installer frameworks exist and if they solve our problems. Some criteria:
Something interesting I already found some time ago is cpack - I didn't look at it in detail yet but it sounds like it is part of CMake, which would be quite nice actually (building the installer right from CMake, and maybe already available in our Docker image?)