-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Added ZIP support spec #1717
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added ZIP support spec #1717
Changes from all commits
afc2c6f
d05d7d9
528257f
81245ef
3156880
c5c9414
03f8a55
ffa63b5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,217 @@ | ||
| --- | ||
| author: Alexis Bekhdadi @midoriiro | ||
| created on: 2021-11-16 | ||
| last updated: 2021-11-30 | ||
| issue id: 140 | ||
| --- | ||
|
|
||
| # Zip Support | ||
|
|
||
| For [#140](https://github.com/microsoft/winget-cli/issues/140) | ||
|
|
||
| ## Abstract | ||
|
|
||
| This feature adds to winget-cli the ability to install application delivered through a ZIP archive. | ||
|
|
||
| ## Inspiration | ||
|
|
||
| A bunch of applications are only provided by developer's through a ZIP archive. There are three cases: | ||
| 1) The archive contains only one binary (a portable / standalone executable). | ||
| 2) The archive contains only one supported installer (msix, msi, or exe). | ||
| 3) The archive contains more than one file. | ||
|
|
||
| ## Solution Design | ||
|
|
||
| A new installation flow need to be created to execute different installation strategies regarding the three cases above. | ||
|
|
||
| First thing first, the archive needs to be extracted in a specific path (TEMP folder can be a good candidate). | ||
|
|
||
| Regarding case 1, installation flow check if TEMP folder contain a single binary and pass instruction to | ||
| installation flow (including setting PATH env var). | ||
|
|
||
| Regarding case 2, installation flow check if TEMP folder contain an installer (.exe, .msi, .msix, etc) and pass control | ||
| to proper installation flow. | ||
|
|
||
| Regarding case 3, installation flow check if TEMP folder does not contain an installer nor a single binary. | ||
| This case is the complex one, example with 'vagrant' hierarchy: | ||
| - root | ||
| - bin | ||
| - vagrant.exe | ||
| - other.exe | ||
| - embedded | ||
| - bin | ||
| - some other folders | ||
|
|
||
| This hierarchy can be packed into an MSI(X) installer or register the application in ARP at the end of installation | ||
| flow (see section below about repack or ARP entry). | ||
|
|
||
| This specification take on consideration schema on version 1.1.0. | ||
| A schema update should be necessary to take all the cases in consideration. | ||
|
|
||
| Take a look into the following manifest examples | ||
|
|
||
| ### Case 1 YAML manifest | ||
|
|
||
| ``` | ||
| PackageIdentifier: Editor.App | ||
| PackageVersion: 1.0 | ||
| MinimumOSVersion: 10.0.0.0 | ||
| InstallerType: zip | ||
| Scope: ... | ||
| InstallModes: ... | ||
| InstallerSwitches: | ||
| Silent: ... | ||
| SilentWithProgress: ... | ||
| UpgradeBehavior: install | ||
| Installers: | ||
| - Architecture: x64 | ||
| InstallerUrl: https://editor.com/app/1.0.zip | ||
| InstallerSha256: ... | ||
| ManifestType: installer | ||
| ManifestVersion: 1.0.0 | ||
| ``` | ||
|
|
||
| This is compliant with the actual schema v1.1.0 | ||
|
|
||
| ### Case 2 YAML manifest | ||
|
|
||
| If the archive contains an installer but not located at root folder (e.g. archive.zip/somefolder/installer.exe) | ||
|
|
||
| ``` | ||
| PackageIdentifier: Editor.App | ||
| PackageVersion: 1.0 | ||
| MinimumOSVersion: 10.0.0.0 | ||
| InstallerType: zip | ||
| Scope: ... | ||
| InstallModes: ... | ||
| InstallerSwitches: | ||
| Silent: ... | ||
| SilentWithProgress: ... | ||
| UpgradeBehavior: install | ||
| Installers: | ||
| - Architecture: x64 | ||
| InstallerUrl: https://editor.com/app/1.0.zip | ||
| InstallerSha256: ... | ||
| InstallerPath: somefolder/installer.exe | ||
| NestedInstallerType: msi | ||
| ManifestType: installer | ||
| ManifestVersion: 1.0.0 | ||
| ``` | ||
|
|
||
| This is not compliant with the actual schema v1.1.0. | ||
| ```InstallerPath``` key should be added to schema. | ||
| This optional key define where to find installer file after extraction if not located at root. | ||
|
|
||
| To specify installer type, ```NestedInstallerType``` key must be defined. | ||
| As mentioned in issue [#1242](https://github.com/microsoft/winget-cli/issues/1242). | ||
|
|
||
| ### Case 3 YAML manifest | ||
|
|
||
| ``` | ||
| PackageIdentifier: Editor.App | ||
| PackageVersion: 1.0 | ||
| MinimumOSVersion: 10.0.0.0 | ||
| InstallerType: zip | ||
| Scope: ... | ||
| InstallModes: ... | ||
| InstallerSwitches: | ||
| Silent: ... | ||
| SilentWithProgress: ... | ||
| UpgradeBehavior: install | ||
| Installers: | ||
| - Architecture: x64 | ||
| InstallerUrl: https://editor.com/app/1.0.zip | ||
| InstallerSha256: ... | ||
| BinaryPath: bin (e.g. bin folder where vagrant.exe is located in my example) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could this be simplified to "InstallerPath" as well, and have the cli determine if it is an installer or binary?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Case 2 cover installer (.exe, .msi, etc). You're pointing case 3, which is for complex hierarchy that does not include installer, only binary with complex folders structure. The base idea is to implement all the cases. Nonetheless, "BInaryPath" maybe not a good name, any idea ?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I’m saying that for case 2, you are suggesting that a key be added to define the path to the exe/msi/etc. Why can’t that same key be used for case 3?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I got confused you was quoting case 3. On case 3, BinaryPath key is for indicate to register a path after the zip extraction into user or system environment variables (need to be defined how to). Correct me if I'm wrong, but from my point of view regarding case 2 (excluding my example manifest 2.1). Case 2 assuming that the zip archive only contains one file, the installer. Case 2 also assuming that the installer will set the proper environment variables if needed (specifically $PATH) or not. that depend of the nature of the application and how editors package their applications. I don't know, how do you manage that kind of thing, winget-cli is agnostic regarding this aspect ? To answer your question, case 3 does not handle installer file. That the job of case 2 and 2.1. Case 2 does not need to define InstallerPath key because, the archive only contains the installer at the root archive. On the other hand, case 2.1 zip archive maybe not contains only one file and maybe not located at root, so InstallerPath key is needed to indicate where to find the installer after the extraction and execute it. To summarize, BinaryPath and InstallerPath are optional keys that depend on the context and they should be set properly by the package maintainer. To avoid messing up with these settings, updating the documentation and the helper script YAMLCreate.ps1 should be needed, in my opinion. For all cases, if the manifest is miss-configured the procedure should fail in an organic way. I don't know if I'm clear, my english is not perfect. Maybe I should clarify these aspects on the specification. |
||
| ManifestType: installer | ||
| ManifestVersion: 1.0.0 | ||
| ``` | ||
|
|
||
| This is not compliant with the actual schema v1.1.0. | ||
| We need to specify which binary folder to add in PATH env var. | ||
| ```BinaryPath``` attribute should be added to schema. | ||
|
|
||
| ### Processing uncompressed files after extraction | ||
|
|
||
| Two solutions can be taken in consideration. Repack uncompressed files into an installer or add an ARP entry in | ||
| registry. | ||
|
|
||
| For case 2, the manifest should contain all information needed to other installation flow. There is no need to repack | ||
| or add an ARP entry. | ||
|
|
||
| For all others cases, repacking a file structure might not be a good solution. This process require installing on client | ||
| side a third party repacking solution or installing Windows SDK that provide MakeAppx that repack our file structure | ||
| into a MSIX installer. But not everyone needs to install Windows SDK and repacking can take time and resources. | ||
|
|
||
| Adding an ARP entry into registry can be done more easily, actually winget-cli already read ARP entries through | ||
| [ARPHelper](https://github.com/microsoft/winget-cli/blob/master/src/AppInstallerRepositoryCore/Microsoft/ARPHelper.cpp) | ||
| struct. | ||
|
|
||
| Windows [documentation](https://docs.microsoft.com/en-us/windows/win32/msi/uninstall-registry-key) define properties for | ||
| an ARP entry (these properties are also defined in ARPHelper struct). | ||
|
|
||
| An ARP entry can be defined in two location: | ||
| - HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall (scope machine) | ||
| - HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall (scope user) | ||
|
|
||
| Uninstall key contains sub keys identified by the application product code, but for our case 1 and 3 a product code | ||
| might not exist. Two solutions can be considered, the package maintainer can generate a random GUID but this identifier | ||
| should be reused on each manifest for a particular application. The second solution is to set the sub key name by the | ||
| application name which can be retrieved on the manifest with the ```PackageName``` key. | ||
|
|
||
| Then the installation flow should register an ARP entry with the proper properties defined in manifest. | ||
|
|
||
| Our file structure should be moved into a proper installation folder. | ||
| Depending on the scope and the architecture we have different folders: | ||
| - %HOMEDRIVE%%HOMEPATH%/AppData/Local (scope user) | ||
| - %PROGRAMFILES% (scope machine, architecture x64) | ||
| - %PROGRAMFILES(X86)% (scope machine, architecture x86) | ||
|
|
||
| > Above section might need more specification about where to install the file structure | ||
|
|
||
| Finally, if manifest key ```BinaryPath``` is defined the installation flow should add to PATH environment variable the | ||
| resolved binary path folder. | ||
|
|
||
| ## UI/UX Design | ||
|
|
||
| If we exclude repacking solutions and prefer add/edit ARP entry, that should be transparent to the end-user. | ||
|
|
||
| - For case 2, the existing installation flow will take control and behave as expected | ||
| - For case 1 and 3, the new installation flow need to behave like other installation flow (showing steps and progress) | ||
|
|
||
| ## Capabilities | ||
|
|
||
| ### Accessibility | ||
|
|
||
| This should have no direct impact on accessibility. | ||
|
|
||
| ### Security | ||
|
|
||
| > Need more specification | ||
|
|
||
| ### Reliability | ||
|
|
||
| This is not expected to impact reliability. | ||
|
|
||
| ### Compatibility | ||
|
|
||
| This feature is intended be an experimental one, at least for a first step. | ||
| End-user need to toggle on the feature in order to install zip packages. | ||
|
|
||
| No code breaking, reuse existing code and add code to support zip installation. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would not be a backward compatible behavior. Only clients with the support for this feature would be able to install packages of this type. We would need to add something like "zip" to the enumeration of installer types. The initial implementation would also be an experimental feature until we have covered enough of the different use cases to confirm viability of the solution.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, you are right. For the moment this draft is only intended to schema 1.1.0. Like i suggested, we maybe need to update the schema (1.1.1?) to handle case 3 and other new cases. |
||
|
|
||
| ### Performance, Power, and Efficiency | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Building the installer is likely to take additional time and resources on the client. There will be performance considerations here with the client in the packaging phase. |
||
|
|
||
| Add/edit an ARP entry should not be an issue for performance, power and efficiency | ||
|
|
||
| ## Potential Issues | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MSIX packages are typically signed. There would likely be security issues related to signing. If the MSI route or some other mechanism is used for the package, we would also need to look at those considerations. Even if we just move the standalone / portable application (or set of files) to a directory path, any changes to those files could have unintended consequences. Some packages also generate additional files in their directories so those may need to be considered during an upgrade or uninstall flow.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
which is true of any package winget currently installs, as with admin rights (or for user scoped packages, normal rights) I can go mess around with anything the installer created. I think that might be a separate issue.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Like someone said on issue #140, if a file is modified is not the packager responsibility but it's an user fault. If files are created by a process delivered by the package, these files should be referenced somewhere to prevent overwriting them, or rather we can specify to overwrite theses files during an upgrade. Typically for config files, user need to edit them, that could be a problem if on each upgrade these files are overwritten. Concerning signing a MSIX package, A self-signed package could be acceptable ? |
||
|
|
||
| > Need more specification | ||
|
|
||
| ## Future considerations | ||
|
midoriiro marked this conversation as resolved.
|
||
|
|
||
| Initial implementation will only take in consideration .zip archive. However, when the feature will be stable enough, | ||
| we can consider other types of archives (e.g. *.gz. *.7z, etc). | ||
|
|
||
| ## Resources | ||
| [MakeAppx.exe Documentation](https://docs.microsoft.com/en-us/windows/msix/package/manual-packaging-root) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we may also need a key defining the secondary installer type.
It is likely that some of the exe’s shipped inside zip packages are actually nullsoft or inno, which should be preferred to exe since the CLI already handles their silent switches without having to define them
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A key definition already exist on schema 1.1.0 (line 459)
Maybe we can use it to tell which installation flow to choose?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That key, by definition, would be "zip" since the primary installer is inside of a .zip file. The issue I'm trying to get ahead of is that the zip file could contain different types of exes which have their own installation flow
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The key I'm pointing could be resolve that issue with something like this:
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe that is valid. Having the key at the manifest level is not compatible with the key at the installer level. One of them will override the other.
Then, what if a publisher distributes some apps via
msiand others viazip => nullsoft? Its possible that not all of the installers inside of a manifest will be zipped, and so we would need to use the installer level key to specify which ones are zip files and which ones are msiThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m not saying multiple installers may be in a .Zip archive. I’m saying a manifest may have different types of installers, and a zip archive may be one of them.
For example - the 7-zip manifest has installers for both exe and msi. Both are in the same manifest.
Some publishers pubish exe’s, msi’s, and zip files, which should all be able to be in a single manifest
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I understand now. And I agree with you about defining another key to specify the installer type. Maybe InstallerSubType ?
I need to clarify some points on the specification about previous conversations. I'll commit soon.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#1242 is how we're planning to capture some of the "nested installer type" issues. For example, PowerToys is distributed as an .exe, but it installs as an .msi. The installer is a wrapper to help with dependencies.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perfect, I think that as long as that issue is referenced in the spec, then there won't be an issue here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That should close this issue. Thank for your feedback.