chezmoi icon indicating copy to clipboard operation
chezmoi copied to clipboard

Add winget package

Open twpayne opened this issue 4 years ago • 15 comments

Describe the solution you'd like

chezmoi should be installable with winget.

Describe alternatives you've considered

Installing chezmoi with chocolatey, scoop, or manually.

Additional context

winget requires an installer. https://github.com/goreleaser/goreleaser/issues/1295 tracks adding support for this to goreleaser.

twpayne avatar Jul 16 '20 11:07 twpayne

Not sure if you've seen this, but you might not need an installer soon™.

bradenhilton avatar Feb 02 '22 23:02 bradenhilton

As an update on this, this is not something that is chezmoi-specific. We're waiting for either winget to support installing utilities from archives (e.g. https://github.com/microsoft/winget-cli/issues/182), or GoReleaser to generate MSIs (https://github.com/goreleaser/goreleaser/issues/1295). If you want to help, please contribute to either of these issues.

twpayne avatar Mar 08 '22 23:03 twpayne

Small update: Winget merged the spec in https://github.com/microsoft/winget-cli/pull/2012. I think we need to wait for the next release now.

bradenhilton avatar Mar 17 '22 11:03 bradenhilton

Awesome, thank you for tracking this.

twpayne avatar Mar 17 '22 13:03 twpayne

Related to this, 5a143268e7f623b8d93dd47d0055d5b6d708e5fe added generating raw (unpackaged) binaries to chezmoi's releases, i.e. you can down directly download a .exe from chezmoi's releases page.

twpayne avatar Mar 17 '22 18:03 twpayne

Small update: Winget merged the spec in microsoft/winget-cli#2012. I think we need to wait for the next release now.

In Preview: https://github.com/microsoft/winget-cli/releases/tag/v1.3.1251-preview

jthoward64 avatar May 10 '22 17:05 jthoward64

Small update: Winget merged the spec in microsoft/winget-cli#2012. I think we need to wait for the next release now.

It's already in stable release for quite some times: https://github.com/microsoft/winget-cli/releases/tag/v1.3.2091 Example github workflows: https://github.com/jandedobbeleer/oh-my-posh/blob/main/.github/workflows/winget.yml

latipun7 avatar Sep 02 '22 11:09 latipun7

Thanks for the link. I did a bit of digging into jandedobbeleer/oh-my-posh and I think it's generating winget packages from an installer. Specifically:

  • The GitHub workflow file calls a script called build.ps1: https://github.com/jandedobbeleer/oh-my-posh/blob/8bab255361f85b4ec3781f7cb6a8184ee68c4f31/.github/workflows/winget.yml#L23
  • build.ps1 does a bunch of substitutions in a bunch of YAML files: https://github.com/JanDeDobbeleer/oh-my-posh/blob/8bab255361f85b4ec3781f7cb6a8184ee68c4f31/packages/winget/build.ps1
  • These files refer to binaries called install-${ARCH}.exe: https://github.com/JanDeDobbeleer/oh-my-posh/blob/8bab255361f85b4ec3781f7cb6a8184ee68c4f31/packages/winget/JanDeDobbeleer.OhMyPosh.installer.yaml#L14
  • These binaries seem to be installer binaries created by Inno Setup: https://github.com/JanDeDobbeleer/oh-my-posh/tree/8bab255361f85b4ec3781f7cb6a8184ee68c4f31/packages/inno

So, I don't think jabdedobbeleer/oh-my-posh is using winget with ZIP files or raw .exes.

If anyone has time to spend on this together (my understanding of Windows and winget is very limited, but I know chezmoi's release process quite well) then I'd be very happy to work on this together.

twpayne avatar Sep 02 '22 19:09 twpayne

@twpayne correct, the winget package for jandedobbeleer/oh-my-posh uses Inno: https://github.com/microsoft/winget-pkgs/blob/218451e5f3feae0191d6b1d7417ac21689735219/manifests/j/JanDeDobbeleer/OhMyPosh/8.9.2/JanDeDobbeleer.OhMyPosh.installer.yaml#L9

Based on https://github.com/microsoft/winget-pkgs#authoring-a-manifest:

There are 3 primary options for creating the manifest:

wingetcreate:

  • Seems to be very CI/CD friendly: https://github.com/microsoft/winget-create#using-windows-package-manager-manifest-creator-in-a-cicd-pipeline

  • I tried to create a manifest with it and got a vague error, not sure why yet:

    ❯ wingetcreate new 'https://github.com/twpayne/chezmoi/releases/download/v2.22.0/chezmoi-windows-amd64.exe'
    Downloading and parsing: https://github.com/twpayne/chezmoi/releases/download/v2.22.0/chezmoi-windows-amd64.exe...
    Failed to parse the package from [https://github.com/twpayne/chezmoi/releases/download/v2.22.0/chezmoi-windows-amd64.exe]
    

    I thought it might be an issue with parsing the architecture from the URL (currently only looks for these substrings: https://github.com/microsoft/winget-create/blob/ea9e220b873eda0ba15484f59a58d3e8b95c23df/src/WingetCreateCore/Common/PackageParser.cs#L518-L526) but some installer URLs don't even have an architecture. Perhaps we could create a temporary prerelease where the exe has one of those substrings to test?

    If wingetcreate new doesn't work for us for some reason, we could still potentially use wingetcreate update in the future once chezmoi has been added to winget-pkgs.

YamlCreate.ps1 (documentation):

  • Seems to work better than wingetcreate(?), judging by how many packages are using it.
  • Requires a fork of microsoft/winget-pkgs, which must be cloned in order to run the script, so not sure how it impacts CI/CD.

Substituting values in a manually created manifest:

  • Should also be decently CI/CD friendly.
  • (Naturally) lacks some of the automation of the other 2 methods.

bradenhilton avatar Sep 02 '22 20:09 bradenhilton

  • I tried to create a manifest with it and got a vague error, not sure why yet:

Is this error from parsing the URL or the contents of the .exe file? My admittedly very poor understanding of the error message is that wingetcreate expected to download an MSI installer (which it could then unpack for files) but instead found a .exe file that looked nothing like an MSI installer.

twpayne avatar Sep 06 '22 20:09 twpayne

@twpayne I opened an issue to see if we can get to the bottom of it.

What I can say is it tries to detect some information from the binary which is not available (perhaps a limitation of goreleaser? I tried to see if it's possible to set this information in built binaries and didn't find anything), but my understanding is that it should ask for user input for anything it can't determine automatically instead of just failing outright.

chezmoi binary

image

For contrast, here's a Discord installer:

Discord installer binary

image

Note that none of this means winget support is impossible, we could always fall back to substituting values in manifest templates.

bradenhilton avatar Sep 06 '22 20:09 bradenhilton

Thank you for the investigation! The chezmoi binary is currently just the chezmoi program itself, not an installer like DiscordSetup.exe.

twpayne avatar Sep 06 '22 20:09 twpayne

I am aware of this, I just picked it because it was right next to the chezmoi binary in my downloads folder. The intention was just to provide an example of what it looks for by default. Those fields are not only populated on installers.

See Nvidia ICAT for another example, which I believe is a standalone binary:

Nvidia ICAT binary

image

Looks like VERSIONINFO is responsible for it.

Following https://stackoverflow.com/a/66702321/11000543, I am able to force-populate the fields:

chezmoi binary via ResourceHacker

image

I wouldn't at all be surprised if populating the fields is impossible with goreleaser.

bradenhilton avatar Sep 06 '22 21:09 bradenhilton

Sorry for my assumptions here - I was wrong.

I suspect that the population of VERSIONINFO should be done by the go toolchain and that goreleaser has no control over this (goreleaser invokes go build for all OSes and architectures, but does not otherwise manipulate the resulting binaries, if my understanding is correct). I don't know if populating VERSIONINFO is currently possible. Maybe it would be possible with something like Go 1.18's debug/buildinfo.

twpayne avatar Sep 06 '22 21:09 twpayne

Perhaps GoVersionInfo is sufficient for this. It even supports embedding an icon.

rclone is using GoVersionInfo.

bradenhilton avatar Sep 06 '22 22:09 bradenhilton

Another issue might be that chezmoi's Windows executables are not signed (AFAICT). Maybe the gh release workflow helps? They use goreleaser as well and sign executables with https://github.com/mtrojnar/osslsigncode AFAICT.

or GoReleaser to generate MSIs (goreleaser/goreleaser#1295)

The workflow ☝🏻 uses a separate job to build and sign MSIs.

dpprdan avatar Oct 26 '22 11:10 dpprdan

@dpprdan https://github.com/twpayne/chezmoi/pull/2394

bradenhilton avatar Oct 26 '22 12:10 bradenhilton

The release signing in #2394 uses cosign, whereas Windows has its own signing system which we'd need to use.

twpayne avatar Oct 26 '22 12:10 twpayne

Another issue might be that chezmoi's Windows executables are not signed (AFAICT).

Here is a post that describes the process in detail: Automatic Code-signing on Windows using GitHub Actions

dpprdan avatar Nov 05 '22 12:11 dpprdan

Thanks for the link. According to that I need to pay $70/year and maintain a self-hosted Windows GitHub Actions runner. This is more than I am prepared to do.

twpayne avatar Nov 05 '22 13:11 twpayne

Understandable.

Sidenote: I am not entirely sure whether a self-hosted Windows GitHub Actions is strictly necessary, though probably more secure? At least the gh cli release workflow doesn't seem to use one, AFAICT. But I'm generally out of my depth here.

dpprdan avatar Nov 05 '22 14:11 dpprdan

Are we absolutely sure signing is necessary for portable apps?

I think we should just manually create a manifest and see if it gets accepted so we can know once and for all.

bradenhilton avatar Nov 05 '22 16:11 bradenhilton

Other than that, distribution through the Microsoft Store probably is an option too, then you don't need a certificate as Microsoft does the signing. And msstore is one of the sources of winget, so you can install through winget CLI too. Don't know if there's a good MSIX packager for Go apps though.

jonaskuske avatar Nov 05 '22 20:11 jonaskuske

Don't know if there's a good MSIX packager for Go apps though.

AFAIU that can be done in a separate job after building the exe with goreleaser

dpprdan avatar Nov 05 '22 20:11 dpprdan

Just seen vedantmgoyal2009/winget-releaser in my explore section, looks like it's an action wrapper around YamlCreate.ps1.

bradenhilton avatar Nov 20 '22 23:11 bradenhilton

Winget 1.4 has just released, adding support for zip installation. I already created a PR for chezmoi:

  • https://github.com/microsoft/winget-pkgs/pull/94759

Once this is merged, the Winget Releaser workflow as mentioned above should be used to set up automatic package updates.

sitiom avatar Jan 27 '23 04:01 sitiom

Awesome, thank you very much :)

twpayne avatar Jan 27 '23 08:01 twpayne

Zip installation wasn't the block for this issue, it was blocked by a lack of a sufficient manifest generation and PR automation tool. We could have manually written an initial manifest months ago when portable exe file support was added to the spec, the problem was keeping it updated. I'm unsure why zip was chosen over portable.

I'd just picked this back up over the last few days because my issue in wingetcreate was closed with an incomplete fix, and it hasn't yet been reopened or received any kind of response.

I thought it might have something to do with the exe missing a manifest, so I added a basic one and it still didn't work.

wingetcreate doesn't parse the exe (or zip) correctly, and YamlCreate.ps1 requires manually cloning your personal winget-pkgs fork to create the PR for every release (which is certainly possible, but quite clunky).

@sitiom the package identifier should ideally be chezmoi.chezmoi IMO, there are plans to move this repo to the chezmoi organization eventually.

bradenhilton avatar Jan 27 '23 11:01 bradenhilton

it was blocked by a lack of a sufficient manifest generation and PR automation tool

WingetCreate and YamlCreate.ps1 have already existed a long time ago.

I'm unsure why zip was chosen over portable.

The only unzipped executable in the releases is amd64 (https://github.com/twpayne/chezmoi/releases/download/v2.29.4/chezmoi-windows-amd64.exe). The zip files cover all architectures.

I'd just picked this back up over the last few days because my issue in wingetcreate was closed with an incomplete fix, and it hasn't yet been reopened or received any kind of response.

YamlCreate.ps1 is better based on my experience 😅. Please have a look at Komac as well, which is currently under development.

YamlCreate.ps1 requires manually cloning your personal winget-pkgs fork to create the PR for every release (which is certainly possible, but quite clunky).

Winget Releaser automates this exact use case. It's convenient. See examples: microsoft/winget-pkgs/pulls (Pull request has been automatically created using 🛫 WinGet Releaser).

@sitiom the package identifier should ideally be chezmoi.chezmoi IMO, there are plans to move this repo to the chezmoi organization eventually.

Sure, when is this? Can you point me to the specific discussion?

sitiom avatar Jan 27 '23 12:01 sitiom

it was blocked by a lack of a sufficient manifest generation and PR automation tool

WingetCreate and YamlCreate.ps1 have already existed a long time ago.

I am aware of this, I explained further in my comment why they are insufficient (wingetcreate) and clunky (YamlCreate.ps1).

I'm unsure why zip was chosen over portable.

The only unzipped executable in the releases is amd64 (https://github.com/twpayne/chezmoi/releases/download/v2.29.4/chezmoi-windows-amd64.exe). The zip files cover all architectures.

Good point.

YamlCreate.ps1 requires manually cloning your personal winget-pkgs fork to create the PR for every release (which is certainly possible, but quite clunky).

Winget Releaser automates this exact use case. It's convenient. See examples: microsoft/winget-pkgs/pulls (Pull request has been automatically created using 🛫 WinGet Releaser).

I am aware of this also, but was unsure of where the winget-pkgs fork should be set up to be used within the workflow.

@sitiom the package identifier should ideally be chezmoi.chezmoi IMO, there are plans to move this repo to the chezmoi organization eventually.

Sure, when is this? Can you point me to the specific discussion?

An email exchange between myself and @twpayne on 2022-06-09:

At some point we should move github.com/twpayne/chezmoi to github.com/chezmoi/chezmoi, but not quite yet :)

That said, it's only an ideal. We can move the manifest when needed, correct?

bradenhilton avatar Jan 27 '23 12:01 bradenhilton