You've already forked goreleaser
							
							
				mirror of
				https://github.com/goreleaser/goreleaser.git
				synced 2025-10-30 23:58:09 +02:00 
			
		
		
		
	feat: winget support (#4081)
this will add support to winget into goreleaser. Basically, the plan is: - we generate the 3 needed yaml files - we commit them to a repo and that's it. Initially, will probably have limited options support, and will only have the default locale. ###### TODO - [x] docs - [x] review by someone who knows how this works? - [x] test install somewhere - [x] more tests maybe? - [x] PR templates via API? https://github.com/goreleaser/goreleaser/pull/4105 - [x] real project test - [x] setup goreleaser to pr to winget as well - [x] document sync fork stuff https://github.com/goreleaser/goreleaser/pull/4106 --------- Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>
This commit is contained in:
		
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							81bd82b13b
						
					
				
				
					commit
					6afdb49c12
				
			| @@ -204,6 +204,23 @@ nix: | ||||
|       installManPage ./manpages/goreleaser.1.gz | ||||
|       installShellCompletion ./completions/* | ||||
|  | ||||
| winget: | ||||
|   - name: goreleaser | ||||
|     publisher: goreleaser | ||||
|     license: MIT | ||||
|     homepage: https://goreleaser.com | ||||
|     short_description: Deliver Go binaries as fast and easily as possible | ||||
|     repository: | ||||
|       owner: goreleaser | ||||
|       name: winget-pkgs | ||||
|       pull_request: | ||||
|         enabled: true | ||||
|         base: | ||||
|           owner: microsoft | ||||
|           name: winget-pkgs | ||||
|           branch: master | ||||
|           draft: true | ||||
|  | ||||
| aurs: | ||||
|   - homepage: https://goreleaser.com | ||||
|     description: Deliver Go binaries as fast and easily as possible | ||||
|   | ||||
| @@ -60,6 +60,12 @@ const ( | ||||
| 	BrewTap | ||||
| 	// Nixpkg is an uploadable nix package. | ||||
| 	Nixpkg | ||||
| 	// WingetInstaller winget installer file. | ||||
| 	WingetInstaller | ||||
| 	// WingetDefaultLocale winget default locale file. | ||||
| 	WingetDefaultLocale | ||||
| 	// WingetVersion winget version file. | ||||
| 	WingetVersion | ||||
| 	// PkgBuild is an Arch Linux AUR PKGBUILD file. | ||||
| 	PkgBuild | ||||
| 	// SrcInfo is an Arch Linux AUR .SRCINFO file. | ||||
| @@ -126,6 +132,8 @@ func (t Type) String() string { | ||||
| 		return "C Archive Library" | ||||
| 	case CShared: | ||||
| 		return "C Shared Library" | ||||
| 	case WingetInstaller, WingetDefaultLocale, WingetVersion: | ||||
| 		return "Winget Manifest" | ||||
| 	default: | ||||
| 		return "unknown" | ||||
| 	} | ||||
|   | ||||
| @@ -21,27 +21,32 @@ func RequireEqual(tb testing.TB, out []byte) { | ||||
|  | ||||
| func RequireEqualExt(tb testing.TB, out []byte, ext string) { | ||||
| 	tb.Helper() | ||||
| 	doRequireEqual(tb, out, ext, golden) | ||||
| 	doRequireEqual(tb, out, ext, golden, false) | ||||
| } | ||||
|  | ||||
| func RequireEqualExtSubfolder(tb testing.TB, out []byte, ext string) { | ||||
| 	tb.Helper() | ||||
| 	doRequireEqual(tb, out, ext, golden, true) | ||||
| } | ||||
|  | ||||
| func RequireEqualTxt(tb testing.TB, out []byte) { | ||||
| 	tb.Helper() | ||||
| 	doRequireEqual(tb, out, ".txt", golden) | ||||
| 	doRequireEqual(tb, out, ".txt", golden, false) | ||||
| } | ||||
|  | ||||
| func RequireEqualJSON(tb testing.TB, out []byte) { | ||||
| 	tb.Helper() | ||||
| 	doRequireEqual(tb, out, ".json", golden) | ||||
| 	doRequireEqual(tb, out, ".json", golden, false) | ||||
| } | ||||
|  | ||||
| func RequireEqualRb(tb testing.TB, out []byte) { | ||||
| 	tb.Helper() | ||||
| 	doRequireEqual(tb, out, ".rb", golden) | ||||
| 	doRequireEqual(tb, out, ".rb", golden, false) | ||||
| } | ||||
|  | ||||
| func RequireEqualYaml(tb testing.TB, out []byte) { | ||||
| 	tb.Helper() | ||||
| 	doRequireEqual(tb, out, ".yaml", "") | ||||
| 	doRequireEqual(tb, out, ".yaml", "", false) | ||||
| } | ||||
|  | ||||
| func RequireReadFile(tb testing.TB, path string) []byte { | ||||
| @@ -51,10 +56,13 @@ func RequireReadFile(tb testing.TB, path string) []byte { | ||||
| 	return bts | ||||
| } | ||||
|  | ||||
| func doRequireEqual(tb testing.TB, out []byte, ext, suffix string) { | ||||
| func doRequireEqual(tb testing.TB, out []byte, ext, suffix string, folder bool) { | ||||
| 	tb.Helper() | ||||
|  | ||||
| 	golden := "testdata/" + tb.Name() + ext + suffix | ||||
| 	golden := filepath.Join("testdata", tb.Name()+ext+suffix) | ||||
| 	if folder { | ||||
| 		golden = filepath.Join("testdata", tb.Name(), filepath.Base(tb.Name())+ext+suffix) | ||||
| 	} | ||||
| 	if *update { | ||||
| 		require.NoError(tb, os.MkdirAll(filepath.Dir(golden), 0o755)) | ||||
| 		require.NoError(tb, os.WriteFile(golden, out, 0o655)) | ||||
|   | ||||
| @@ -23,6 +23,7 @@ import ( | ||||
| 	"github.com/goreleaser/goreleaser/internal/pipe/sign" | ||||
| 	"github.com/goreleaser/goreleaser/internal/pipe/snapcraft" | ||||
| 	"github.com/goreleaser/goreleaser/internal/pipe/upload" | ||||
| 	"github.com/goreleaser/goreleaser/internal/pipe/winget" | ||||
| 	"github.com/goreleaser/goreleaser/pkg/context" | ||||
| ) | ||||
|  | ||||
| @@ -49,6 +50,7 @@ var publishers = []Publisher{ | ||||
| 	release.Pipe{}, | ||||
| 	// brew et al use the release URL, so, they should be last | ||||
| 	nix.NewPublish(), | ||||
| 	winget.Pipe{}, | ||||
| 	brew.Pipe{}, | ||||
| 	aur.Pipe{}, | ||||
| 	krew.Pipe{}, | ||||
|   | ||||
							
								
								
									
										122
									
								
								internal/pipe/winget/template.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								internal/pipe/winget/template.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,122 @@ | ||||
| package winget | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/caarlos0/log" | ||||
| 	"github.com/goreleaser/goreleaser/internal/artifact" | ||||
| 	"github.com/goreleaser/goreleaser/internal/yaml" | ||||
| 	"github.com/goreleaser/goreleaser/pkg/config" | ||||
| 	"github.com/goreleaser/goreleaser/pkg/context" | ||||
| ) | ||||
|  | ||||
| func createYAML(ctx *context.Context, winget config.Winget, in any, tp artifact.Type) error { | ||||
| 	versionContent, err := yaml.Marshal(in) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	filename := winget.Name + extFor(tp) | ||||
| 	path := filepath.Join(ctx.Config.Dist, winget.Path, filename) | ||||
| 	if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	log.WithField("path", path).Info("writing") | ||||
| 	if err := os.WriteFile(path, []byte(strings.Join([]string{ | ||||
| 		generatedHeader, | ||||
| 		langserverLineFor(tp), | ||||
| 		string(versionContent), | ||||
| 	}, "\n")), 0o644); err != nil { //nolint: gosec | ||||
| 		return fmt.Errorf("failed to write winget version: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	ctx.Artifacts.Add(&artifact.Artifact{ | ||||
| 		Name: filename, | ||||
| 		Path: path, | ||||
| 		Type: tp, | ||||
| 		Extra: map[string]interface{}{ | ||||
| 			wingetConfigExtra: winget, | ||||
| 			artifact.ExtraID:  winget.Name, | ||||
| 		}, | ||||
| 	}) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	manifestVersion         = "1.4.0" | ||||
| 	versionLangServer       = "# yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.4.0.schema.json" | ||||
| 	installerLangServer     = "# yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.4.0.schema.json" | ||||
| 	defaultLocaleLangServer = "# yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.4.0.schema.json" | ||||
| 	defaultLocale           = "en-US" | ||||
| 	generatedHeader         = `# This file was generated by GoReleaser. DO NOT EDIT.` | ||||
| ) | ||||
|  | ||||
| // nolint: tagliatelle | ||||
| type Version struct { | ||||
| 	PackageIdentifier string `yaml:"PackageIdentifier,omitempty"` | ||||
| 	PackageVersion    string `yaml:"PackageVersion,omitempty"` | ||||
| 	DefaultLocale     string `yaml:"DefaultLocale,omitempty"` | ||||
| 	ManifestType      string `yaml:"ManifestType,omitempty"` | ||||
| 	ManifestVersion   string `yaml:"ManifestVersion,omitempty"` | ||||
| } | ||||
|  | ||||
| // nolint: tagliatelle | ||||
| type InstallerItemFile struct { | ||||
| 	RelativeFilePath string `yaml:"RelativeFilePath,omitempty"` | ||||
| } | ||||
|  | ||||
| // nolint: tagliatelle | ||||
| type InstallerItem struct { | ||||
| 	Architecture         string              `yaml:"Architecture,omitempty"` | ||||
| 	NestedInstallerType  string              `yaml:"NestedInstallerType,omitempty"` | ||||
| 	NestedInstallerFiles []InstallerItemFile `yaml:"NestedInstallerFiles,omitempty"` | ||||
| 	InstallerURL         string              `yaml:"InstallerUrl,omitempty"` | ||||
| 	InstallerSha256      string              `yaml:"InstallerSha256,omitempty"` | ||||
| 	UpgradeBehavior      string              `yaml:"UpgradeBehavior,omitempty"` | ||||
| } | ||||
|  | ||||
| // nolint: tagliatelle | ||||
| type Installer struct { | ||||
| 	PackageIdentifier string          `yaml:"PackageIdentifier,omitempty"` | ||||
| 	PackageVersion    string          `yaml:"PackageVersion,omitempty"` | ||||
| 	InstallerLocale   string          `yaml:"InstallerLocale,omitempty"` | ||||
| 	InstallerType     string          `yaml:"InstallerType,omitempty"` | ||||
| 	Commands          []string        `yaml:"Commands,omitempty"` | ||||
| 	ReleaseDate       string          `yaml:"ReleaseDate,omitempty"` | ||||
| 	Installers        []InstallerItem `yaml:"Installers,omitempty"` | ||||
| 	ManifestType      string          `yaml:"ManifestType,omitempty"` | ||||
| 	ManifestVersion   string          `yaml:"ManifestVersion,omitempty"` | ||||
| } | ||||
|  | ||||
| // nolint: tagliatelle | ||||
| type Locale struct { | ||||
| 	PackageIdentifier string   `yaml:"PackageIdentifier,omitempty"` | ||||
| 	PackageVersion    string   `yaml:"PackageVersion,omitempty"` | ||||
| 	PackageLocale     string   `yaml:"PackageLocale,omitempty"` | ||||
| 	Publisher         string   `yaml:"Publisher,omitempty"` | ||||
| 	PublisherURL      string   `yaml:"PublisherUrl,omitempty"` | ||||
| 	Author            string   `yaml:"Author,omitempty"` | ||||
| 	PackageName       string   `yaml:"PackageName,omitempty"` | ||||
| 	PackageURL        string   `yaml:"PackageUrl,omitempty"` | ||||
| 	License           string   `yaml:"License,omitempty"` | ||||
| 	LicenseURL        string   `yaml:"LicenseUrl,omitempty"` | ||||
| 	Copyright         string   `yaml:"Copyright,omitempty"` | ||||
| 	ShortDescription  string   `yaml:"ShortDescription,omitempty"` | ||||
| 	Description       string   `yaml:"Description,omitempty"` | ||||
| 	Moniker           string   `yaml:"Moniker,omitempty"` | ||||
| 	Tags              []string `yaml:"Tags,omitempty"` | ||||
| 	ReleaseNotes      string   `yaml:"ReleaseNotes,omitempty"` | ||||
| 	ReleaseNotesURL   string   `yaml:"ReleaseNotesUrl,omitempty"` | ||||
| 	ManifestType      string   `yaml:"ManifestType,omitempty"` | ||||
| 	ManifestVersion   string   `yaml:"ManifestVersion,omitempty"` | ||||
| } | ||||
|  | ||||
| var fromGoArch = map[string]string{ | ||||
| 	"amd64": "x64", | ||||
| 	"386":   "x86", | ||||
| } | ||||
| @@ -0,0 +1,12 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.4.0.schema.json | ||||
| PackageIdentifier: Beckersoft.foo | ||||
| PackageVersion: 1.2.1 | ||||
| PackageLocale: en-US | ||||
| Publisher: Beckersoft | ||||
| PackageName: foo | ||||
| License: MIT | ||||
| ShortDescription: foo bar zaz | ||||
| Moniker: foo | ||||
| ManifestType: defaultLocale | ||||
| ManifestVersion: 1.4.0 | ||||
| @@ -0,0 +1,17 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.4.0.schema.json | ||||
| PackageIdentifier: Beckersoft.foo | ||||
| PackageVersion: 1.2.1 | ||||
| InstallerLocale: en-US | ||||
| InstallerType: zip | ||||
| ReleaseDate: "2023-06-12" | ||||
| Installers: | ||||
|   - Architecture: x64 | ||||
|     NestedInstallerType: portable | ||||
|     NestedInstallerFiles: | ||||
|       - RelativeFilePath: foo.exe | ||||
|     InstallerUrl: https://dummyhost/download/v1.2.1/foo_windows_amd64v1.zip | ||||
|     InstallerSha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 | ||||
|     UpgradeBehavior: uninstallPrevious | ||||
| ManifestType: installer | ||||
| ManifestVersion: 1.4.0 | ||||
| @@ -0,0 +1,7 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.4.0.schema.json | ||||
| PackageIdentifier: Beckersoft.foo | ||||
| PackageVersion: 1.2.1 | ||||
| DefaultLocale: en-US | ||||
| ManifestType: version | ||||
| ManifestVersion: 1.4.0 | ||||
							
								
								
									
										24
									
								
								internal/pipe/winget/testdata/TestRunPipe/full/full.en-US.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								internal/pipe/winget/testdata/TestRunPipe/full/full.en-US.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.4.0.schema.json | ||||
| PackageIdentifier: Beckersoft.foo | ||||
| PackageVersion: 1.2.1 | ||||
| PackageLocale: en-US | ||||
| Publisher: Beckersoft | ||||
| PublisherUrl: https://carlosbecker.com | ||||
| Author: Carlos Becker | ||||
| PackageName: foo | ||||
| PackageUrl: https://goreleaser.com | ||||
| License: MIT | ||||
| LicenseUrl: https://goreleaser.com/eula/ | ||||
| Copyright: bla bla bla | ||||
| ShortDescription: foo | ||||
| Description: |- | ||||
|   long foo bar | ||||
|  | ||||
|   				yadaa yada yada loooaaasssss | ||||
|  | ||||
|   				sss | ||||
| Moniker: foo | ||||
| ReleaseNotesUrl: https://github.com/goreleaser/goreleaser/tags/v1.2.1 | ||||
| ManifestType: defaultLocale | ||||
| ManifestVersion: 1.4.0 | ||||
							
								
								
									
										17
									
								
								internal/pipe/winget/testdata/TestRunPipe/full/full.installer.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								internal/pipe/winget/testdata/TestRunPipe/full/full.installer.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.4.0.schema.json | ||||
| PackageIdentifier: Beckersoft.foo | ||||
| PackageVersion: 1.2.1 | ||||
| InstallerLocale: en-US | ||||
| InstallerType: zip | ||||
| ReleaseDate: "2023-06-12" | ||||
| Installers: | ||||
|   - Architecture: x64 | ||||
|     NestedInstallerType: portable | ||||
|     NestedInstallerFiles: | ||||
|       - RelativeFilePath: foo.exe | ||||
|     InstallerUrl: https://dummyhost/download/v1.2.1/foo_windows_amd64v1.zip | ||||
|     InstallerSha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 | ||||
|     UpgradeBehavior: uninstallPrevious | ||||
| ManifestType: installer | ||||
| ManifestVersion: 1.4.0 | ||||
							
								
								
									
										7
									
								
								internal/pipe/winget/testdata/TestRunPipe/full/full.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								internal/pipe/winget/testdata/TestRunPipe/full/full.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.4.0.schema.json | ||||
| PackageIdentifier: Beckersoft.foo | ||||
| PackageVersion: 1.2.1 | ||||
| DefaultLocale: en-US | ||||
| ManifestType: version | ||||
| ManifestVersion: 1.4.0 | ||||
							
								
								
									
										12
									
								
								internal/pipe/winget/testdata/TestRunPipe/minimal/minimal.en-US.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								internal/pipe/winget/testdata/TestRunPipe/minimal/minimal.en-US.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.4.0.schema.json | ||||
| PackageIdentifier: Foo.min | ||||
| PackageVersion: 1.2.1 | ||||
| PackageLocale: en-US | ||||
| Publisher: Foo | ||||
| PackageName: min | ||||
| License: MIT | ||||
| ShortDescription: foo bar zaz | ||||
| Moniker: min | ||||
| ManifestType: defaultLocale | ||||
| ManifestVersion: 1.4.0 | ||||
							
								
								
									
										17
									
								
								internal/pipe/winget/testdata/TestRunPipe/minimal/minimal.installer.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								internal/pipe/winget/testdata/TestRunPipe/minimal/minimal.installer.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.4.0.schema.json | ||||
| PackageIdentifier: Foo.min | ||||
| PackageVersion: 1.2.1 | ||||
| InstallerLocale: en-US | ||||
| InstallerType: zip | ||||
| ReleaseDate: "2023-06-12" | ||||
| Installers: | ||||
|   - Architecture: x64 | ||||
|     NestedInstallerType: portable | ||||
|     NestedInstallerFiles: | ||||
|       - RelativeFilePath: foo.exe | ||||
|     InstallerUrl: https://dummyhost/download/v1.2.1/foo_windows_amd64v1.zip | ||||
|     InstallerSha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 | ||||
|     UpgradeBehavior: uninstallPrevious | ||||
| ManifestType: installer | ||||
| ManifestVersion: 1.4.0 | ||||
							
								
								
									
										7
									
								
								internal/pipe/winget/testdata/TestRunPipe/minimal/minimal.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								internal/pipe/winget/testdata/TestRunPipe/minimal/minimal.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.4.0.schema.json | ||||
| PackageIdentifier: Foo.min | ||||
| PackageVersion: 1.2.1 | ||||
| DefaultLocale: en-US | ||||
| ManifestType: version | ||||
| ManifestVersion: 1.4.0 | ||||
							
								
								
									
										14
									
								
								internal/pipe/winget/testdata/TestRunPipe/open-pr/open-pr.en-US.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								internal/pipe/winget/testdata/TestRunPipe/open-pr/open-pr.en-US.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.4.0.schema.json | ||||
| PackageIdentifier: Beckersoft.foo | ||||
| PackageVersion: 1.2.1 | ||||
| PackageLocale: en-US | ||||
| Publisher: Beckersoft | ||||
| PackageName: foo | ||||
| PackageUrl: https://goreleaser.com | ||||
| License: mit | ||||
| ShortDescription: foo bar zaz | ||||
| Description: my test | ||||
| Moniker: foo | ||||
| ManifestType: defaultLocale | ||||
| ManifestVersion: 1.4.0 | ||||
							
								
								
									
										17
									
								
								internal/pipe/winget/testdata/TestRunPipe/open-pr/open-pr.installer.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								internal/pipe/winget/testdata/TestRunPipe/open-pr/open-pr.installer.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.4.0.schema.json | ||||
| PackageIdentifier: Beckersoft.foo | ||||
| PackageVersion: 1.2.1 | ||||
| InstallerLocale: en-US | ||||
| InstallerType: zip | ||||
| ReleaseDate: "2023-06-12" | ||||
| Installers: | ||||
|   - Architecture: x64 | ||||
|     NestedInstallerType: portable | ||||
|     NestedInstallerFiles: | ||||
|       - RelativeFilePath: foo.exe | ||||
|     InstallerUrl: https://dummyhost/download/v1.2.1/foo_windows_amd64v1.zip | ||||
|     InstallerSha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 | ||||
|     UpgradeBehavior: uninstallPrevious | ||||
| ManifestType: installer | ||||
| ManifestVersion: 1.4.0 | ||||
							
								
								
									
										7
									
								
								internal/pipe/winget/testdata/TestRunPipe/open-pr/open-pr.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								internal/pipe/winget/testdata/TestRunPipe/open-pr/open-pr.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.4.0.schema.json | ||||
| PackageIdentifier: Beckersoft.foo | ||||
| PackageVersion: 1.2.1 | ||||
| DefaultLocale: en-US | ||||
| ManifestType: version | ||||
| ManifestVersion: 1.4.0 | ||||
							
								
								
									
										12
									
								
								internal/pipe/winget/testdata/TestRunPipe/partial/partial.en-US.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								internal/pipe/winget/testdata/TestRunPipe/partial/partial.en-US.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.4.0.schema.json | ||||
| PackageIdentifier: Beckersoft.partial | ||||
| PackageVersion: 1.2.1 | ||||
| PackageLocale: en-US | ||||
| Publisher: Beckersoft | ||||
| PackageName: partial | ||||
| License: MIT | ||||
| ShortDescription: foo bar zaz | ||||
| Moniker: partial | ||||
| ManifestType: defaultLocale | ||||
| ManifestVersion: 1.4.0 | ||||
							
								
								
									
										17
									
								
								internal/pipe/winget/testdata/TestRunPipe/partial/partial.installer.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								internal/pipe/winget/testdata/TestRunPipe/partial/partial.installer.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.4.0.schema.json | ||||
| PackageIdentifier: Beckersoft.partial | ||||
| PackageVersion: 1.2.1 | ||||
| InstallerLocale: en-US | ||||
| InstallerType: zip | ||||
| ReleaseDate: "2023-06-12" | ||||
| Installers: | ||||
|   - Architecture: x64 | ||||
|     NestedInstallerType: portable | ||||
|     NestedInstallerFiles: | ||||
|       - RelativeFilePath: foo.exe | ||||
|     InstallerUrl: https://dummyhost/download/v1.2.1/foo_windows_amd64v1.zip | ||||
|     InstallerSha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 | ||||
|     UpgradeBehavior: uninstallPrevious | ||||
| ManifestType: installer | ||||
| ManifestVersion: 1.4.0 | ||||
							
								
								
									
										7
									
								
								internal/pipe/winget/testdata/TestRunPipe/partial/partial.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								internal/pipe/winget/testdata/TestRunPipe/partial/partial.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.4.0.schema.json | ||||
| PackageIdentifier: Beckersoft.partial | ||||
| PackageVersion: 1.2.1 | ||||
| DefaultLocale: en-US | ||||
| ManifestType: version | ||||
| ManifestVersion: 1.4.0 | ||||
							
								
								
									
										12
									
								
								internal/pipe/winget/testdata/TestRunPipe/skip-upload-auto/skip-upload-auto.en-US.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								internal/pipe/winget/testdata/TestRunPipe/skip-upload-auto/skip-upload-auto.en-US.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.4.0.schema.json | ||||
| PackageIdentifier: Beckersoft.doesnotmatter | ||||
| PackageVersion: 1.2.1 | ||||
| PackageLocale: en-US | ||||
| Publisher: Beckersoft | ||||
| PackageName: doesnotmatter | ||||
| License: MIT | ||||
| ShortDescription: foo bar zaz | ||||
| Moniker: doesnotmatter | ||||
| ManifestType: defaultLocale | ||||
| ManifestVersion: 1.4.0 | ||||
| @@ -0,0 +1,17 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.4.0.schema.json | ||||
| PackageIdentifier: Beckersoft.doesnotmatter | ||||
| PackageVersion: 1.2.1 | ||||
| InstallerLocale: en-US | ||||
| InstallerType: zip | ||||
| ReleaseDate: "2023-06-12" | ||||
| Installers: | ||||
|   - Architecture: x64 | ||||
|     NestedInstallerType: portable | ||||
|     NestedInstallerFiles: | ||||
|       - RelativeFilePath: foo.exe | ||||
|     InstallerUrl: https://dummyhost/download/v1.2.1/foo_windows_amd64v1.zip | ||||
|     InstallerSha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 | ||||
|     UpgradeBehavior: uninstallPrevious | ||||
| ManifestType: installer | ||||
| ManifestVersion: 1.4.0 | ||||
							
								
								
									
										7
									
								
								internal/pipe/winget/testdata/TestRunPipe/skip-upload-auto/skip-upload-auto.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								internal/pipe/winget/testdata/TestRunPipe/skip-upload-auto/skip-upload-auto.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.4.0.schema.json | ||||
| PackageIdentifier: Beckersoft.doesnotmatter | ||||
| PackageVersion: 1.2.1 | ||||
| DefaultLocale: en-US | ||||
| ManifestType: version | ||||
| ManifestVersion: 1.4.0 | ||||
							
								
								
									
										12
									
								
								internal/pipe/winget/testdata/TestRunPipe/skip-upload/skip-upload.en-US.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								internal/pipe/winget/testdata/TestRunPipe/skip-upload/skip-upload.en-US.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.4.0.schema.json | ||||
| PackageIdentifier: Beckersoft.doesnotmatter | ||||
| PackageVersion: 1.2.1 | ||||
| PackageLocale: en-US | ||||
| Publisher: Beckersoft | ||||
| PackageName: doesnotmatter | ||||
| License: MIT | ||||
| ShortDescription: foo bar zaz | ||||
| Moniker: doesnotmatter | ||||
| ManifestType: defaultLocale | ||||
| ManifestVersion: 1.4.0 | ||||
							
								
								
									
										17
									
								
								internal/pipe/winget/testdata/TestRunPipe/skip-upload/skip-upload.installer.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								internal/pipe/winget/testdata/TestRunPipe/skip-upload/skip-upload.installer.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.4.0.schema.json | ||||
| PackageIdentifier: Beckersoft.doesnotmatter | ||||
| PackageVersion: 1.2.1 | ||||
| InstallerLocale: en-US | ||||
| InstallerType: zip | ||||
| ReleaseDate: "2023-06-12" | ||||
| Installers: | ||||
|   - Architecture: x64 | ||||
|     NestedInstallerType: portable | ||||
|     NestedInstallerFiles: | ||||
|       - RelativeFilePath: foo.exe | ||||
|     InstallerUrl: https://dummyhost/download/v1.2.1/foo_windows_amd64v1.zip | ||||
|     InstallerSha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 | ||||
|     UpgradeBehavior: uninstallPrevious | ||||
| ManifestType: installer | ||||
| ManifestVersion: 1.4.0 | ||||
							
								
								
									
										7
									
								
								internal/pipe/winget/testdata/TestRunPipe/skip-upload/skip-upload.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								internal/pipe/winget/testdata/TestRunPipe/skip-upload/skip-upload.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.4.0.schema.json | ||||
| PackageIdentifier: Beckersoft.doesnotmatter | ||||
| PackageVersion: 1.2.1 | ||||
| DefaultLocale: en-US | ||||
| ManifestType: version | ||||
| ManifestVersion: 1.4.0 | ||||
							
								
								
									
										16
									
								
								internal/pipe/winget/testdata/TestRunPipe/wrapped-in-dir/wrapped-in-dir.en-US.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								internal/pipe/winget/testdata/TestRunPipe/wrapped-in-dir/wrapped-in-dir.en-US.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.4.0.schema.json | ||||
| PackageIdentifier: Beckersoft.wrapped-in-dir | ||||
| PackageVersion: 1.2.1 | ||||
| PackageLocale: en-US | ||||
| Publisher: Beckersoft | ||||
| PackageName: wrapped-in-dir | ||||
| PackageUrl: https://goreleaser.com | ||||
| License: mit | ||||
| LicenseUrl: https://goreleaser.com/license | ||||
| ShortDescription: foo bar zaz | ||||
| Description: my test | ||||
| Moniker: wrapped-in-dir | ||||
| ReleaseNotesUrl: https://github.com/goreleaser/goreleaser/tags/v1.2.1 | ||||
| ManifestType: defaultLocale | ||||
| ManifestVersion: 1.4.0 | ||||
							
								
								
									
										17
									
								
								internal/pipe/winget/testdata/TestRunPipe/wrapped-in-dir/wrapped-in-dir.installer.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								internal/pipe/winget/testdata/TestRunPipe/wrapped-in-dir/wrapped-in-dir.installer.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.4.0.schema.json | ||||
| PackageIdentifier: Beckersoft.wrapped-in-dir | ||||
| PackageVersion: 1.2.1 | ||||
| InstallerLocale: en-US | ||||
| InstallerType: zip | ||||
| ReleaseDate: "2023-06-12" | ||||
| Installers: | ||||
|   - Architecture: x64 | ||||
|     NestedInstallerType: portable | ||||
|     NestedInstallerFiles: | ||||
|       - RelativeFilePath: foo\foo.exe | ||||
|     InstallerUrl: https://dummyhost/download/v1.2.1/foo_windows_amd64v1.zip | ||||
|     InstallerSha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 | ||||
|     UpgradeBehavior: uninstallPrevious | ||||
| ManifestType: installer | ||||
| ManifestVersion: 1.4.0 | ||||
							
								
								
									
										7
									
								
								internal/pipe/winget/testdata/TestRunPipe/wrapped-in-dir/wrapped-in-dir.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								internal/pipe/winget/testdata/TestRunPipe/wrapped-in-dir/wrapped-in-dir.yaml.golden
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| # This file was generated by GoReleaser. DO NOT EDIT. | ||||
| # yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.4.0.schema.json | ||||
| PackageIdentifier: Beckersoft.wrapped-in-dir | ||||
| PackageVersion: 1.2.1 | ||||
| DefaultLocale: en-US | ||||
| ManifestType: version | ||||
| ManifestVersion: 1.4.0 | ||||
							
								
								
									
										432
									
								
								internal/pipe/winget/winget.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										432
									
								
								internal/pipe/winget/winget.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,432 @@ | ||||
| package winget | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"regexp" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/caarlos0/log" | ||||
| 	"github.com/goreleaser/goreleaser/internal/artifact" | ||||
| 	"github.com/goreleaser/goreleaser/internal/client" | ||||
| 	"github.com/goreleaser/goreleaser/internal/commitauthor" | ||||
| 	"github.com/goreleaser/goreleaser/internal/pipe" | ||||
| 	"github.com/goreleaser/goreleaser/internal/tmpl" | ||||
| 	"github.com/goreleaser/goreleaser/pkg/config" | ||||
| 	"github.com/goreleaser/goreleaser/pkg/context" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	errNoRepoName               = pipe.Skip("winget.repository.name name is required") | ||||
| 	errNoPublisher              = pipe.Skip("winget.publisher is required") | ||||
| 	errNoLicense                = pipe.Skip("winget.license is required") | ||||
| 	errNoShortDescription       = pipe.Skip("winget.short_description is required") | ||||
| 	errInvalidPackageIdentifier = pipe.Skip("winget.package_identifier is invalid") | ||||
| 	errSkipUpload               = pipe.Skip("winget.skip_upload is set") | ||||
| 	errSkipUploadAuto           = pipe.Skip("winget.skip_upload is set to 'auto', and current version is a pre-release") | ||||
| 	errMultipleArchives         = pipe.Skip("found multiple archives for the same platform, please consider filtering by id") | ||||
| 	packageIdentifierValid      = regexp.MustCompile("^[^\\.\\s\\\\/:\\*\\?\"<>\\|\\x01-\\x1f]{1,32}(\\.[^\\.\\s\\\\/:\\*\\?\"<>\\|\\x01-\\x1f]{1,32}){1,7}$") | ||||
| ) | ||||
|  | ||||
| type errNoArchivesFound struct { | ||||
| 	goamd64 string | ||||
| 	ids     []string | ||||
| } | ||||
|  | ||||
| func (e errNoArchivesFound) Error() string { | ||||
| 	return fmt.Sprintf("no zip archives found matching goos=[windows] goarch=[amd64 386] goamd64=%s ids=%v", e.goamd64, e.ids) | ||||
| } | ||||
|  | ||||
| const wingetConfigExtra = "WingetConfig" | ||||
|  | ||||
| type Pipe struct{} | ||||
|  | ||||
| func (Pipe) String() string { return "winget" } | ||||
| func (p Pipe) Skip(ctx *context.Context) bool { | ||||
| 	return len(ctx.Config.Winget) == 0 | ||||
| } | ||||
|  | ||||
| func (Pipe) Default(ctx *context.Context) error { | ||||
| 	for i := range ctx.Config.Winget { | ||||
| 		winget := &ctx.Config.Winget[i] | ||||
|  | ||||
| 		winget.CommitAuthor = commitauthor.Default(winget.CommitAuthor) | ||||
|  | ||||
| 		if winget.CommitMessageTemplate == "" { | ||||
| 			winget.CommitMessageTemplate = "{{ .ProjectName }}: {{ .PreviousTag }} -> {{ .Tag }}" | ||||
| 		} | ||||
| 		if winget.Name == "" { | ||||
| 			winget.Name = ctx.Config.ProjectName | ||||
| 		} | ||||
| 		if winget.Goamd64 == "" { | ||||
| 			winget.Goamd64 = "v1" | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (p Pipe) Run(ctx *context.Context) error { | ||||
| 	cli, err := client.New(ctx) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return p.runAll(ctx, cli) | ||||
| } | ||||
|  | ||||
| // Publish . | ||||
| func (p Pipe) Publish(ctx *context.Context) error { | ||||
| 	cli, err := client.New(ctx) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return p.publishAll(ctx, cli) | ||||
| } | ||||
|  | ||||
| func (p Pipe) runAll(ctx *context.Context, cli client.Client) error { | ||||
| 	for _, winget := range ctx.Config.Winget { | ||||
| 		err := p.doRun(ctx, winget, cli) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (p Pipe) doRun(ctx *context.Context, winget config.Winget, cl client.ReleaserURLTemplater) error { | ||||
| 	if winget.Repository.Name == "" { | ||||
| 		return errNoRepoName | ||||
| 	} | ||||
|  | ||||
| 	publisher, err := tmpl.New(ctx).Apply(winget.Publisher) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if publisher == "" { | ||||
| 		return errNoPublisher | ||||
| 	} | ||||
| 	winget.Publisher = publisher | ||||
|  | ||||
| 	if winget.License == "" { | ||||
| 		return errNoLicense | ||||
| 	} | ||||
|  | ||||
| 	name, err := tmpl.New(ctx).Apply(winget.Name) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	winget.Name = name | ||||
|  | ||||
| 	author, err := tmpl.New(ctx).Apply(winget.Author) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	winget.Author = author | ||||
|  | ||||
| 	publisherURL, err := tmpl.New(ctx).Apply(winget.PublisherURL) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	winget.PublisherURL = publisherURL | ||||
|  | ||||
| 	homepage, err := tmpl.New(ctx).Apply(winget.Homepage) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	winget.Homepage = homepage | ||||
|  | ||||
| 	ref, err := client.TemplateRef(tmpl.New(ctx).Apply, winget.Repository) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	winget.Repository = ref | ||||
|  | ||||
| 	skipUpload, err := tmpl.New(ctx).Apply(winget.SkipUpload) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	winget.SkipUpload = skipUpload | ||||
|  | ||||
| 	description, err := tmpl.New(ctx).Apply(winget.Description) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	winget.Description = description | ||||
|  | ||||
| 	shortDescription, err := tmpl.New(ctx).Apply(winget.ShortDescription) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	winget.ShortDescription = shortDescription | ||||
|  | ||||
| 	if winget.ShortDescription == "" { | ||||
| 		return errNoShortDescription | ||||
| 	} | ||||
|  | ||||
| 	releaseNotesURL, err := tmpl.New(ctx).Apply(winget.ReleaseNotesURL) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	winget.ReleaseNotesURL = releaseNotesURL | ||||
|  | ||||
| 	if winget.URLTemplate == "" { | ||||
| 		url, err := cl.ReleaseURLTemplate(ctx) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		winget.URLTemplate = url | ||||
| 	} | ||||
|  | ||||
| 	path, err := tmpl.New(ctx).Apply(winget.Path) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if path == "" { | ||||
| 		path = filepath.Join("manifests", strings.ToLower(string(winget.Publisher[0])), winget.Publisher, winget.Name, ctx.Version) | ||||
| 	} | ||||
| 	winget.Path = path | ||||
|  | ||||
| 	filters := []artifact.Filter{ | ||||
| 		artifact.ByGoos("windows"), | ||||
| 		artifact.ByFormats("zip"), | ||||
| 		artifact.ByType(artifact.UploadableArchive), | ||||
| 		artifact.Or( | ||||
| 			artifact.ByGoarch("386"), | ||||
| 			artifact.And( | ||||
| 				artifact.ByGoamd64(winget.Goamd64), | ||||
| 				artifact.ByGoarch("amd64"), | ||||
| 			), | ||||
| 		), | ||||
| 	} | ||||
| 	if len(winget.IDs) > 0 { | ||||
| 		filters = append(filters, artifact.ByIDs(winget.IDs...)) | ||||
| 	} | ||||
| 	archives := ctx.Artifacts.Filter(artifact.And(filters...)).List() | ||||
| 	if len(archives) == 0 { | ||||
| 		return errNoArchivesFound{ | ||||
| 			goamd64: winget.Goamd64, | ||||
| 			ids:     winget.IDs, | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if winget.PackageIdentifier == "" { | ||||
| 		winget.PackageIdentifier = publisher + "." + name | ||||
| 	} | ||||
|  | ||||
| 	if !packageIdentifierValid.MatchString(winget.PackageIdentifier) { | ||||
| 		return fmt.Errorf("%w: %s", errInvalidPackageIdentifier, winget.PackageIdentifier) | ||||
| 	} | ||||
|  | ||||
| 	if err := createYAML(ctx, winget, Version{ | ||||
| 		PackageIdentifier: winget.PackageIdentifier, | ||||
| 		PackageVersion:    ctx.Version, | ||||
| 		DefaultLocale:     defaultLocale, | ||||
| 		ManifestType:      "version", | ||||
| 		ManifestVersion:   manifestVersion, | ||||
| 	}, artifact.WingetVersion); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	installer := Installer{ | ||||
| 		PackageIdentifier: winget.PackageIdentifier, | ||||
| 		PackageVersion:    ctx.Version, | ||||
| 		InstallerLocale:   defaultLocale, | ||||
| 		InstallerType:     "zip", | ||||
| 		Commands:          []string{}, | ||||
| 		ReleaseDate:       ctx.Date.Format(time.DateOnly), | ||||
| 		Installers:        []InstallerItem{}, | ||||
| 		ManifestType:      "installer", | ||||
| 		ManifestVersion:   manifestVersion, | ||||
| 	} | ||||
|  | ||||
| 	var amd64Count, i386count int | ||||
| 	for _, archive := range archives { | ||||
| 		sha256, err := archive.Checksum("sha256") | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		var files []InstallerItemFile | ||||
| 		folder := artifact.ExtraOr(*archive, artifact.ExtraWrappedIn, ".") | ||||
| 		for _, bin := range artifact.ExtraOr(*archive, artifact.ExtraBinaries, []string{}) { | ||||
| 			files = append(files, InstallerItemFile{ | ||||
| 				RelativeFilePath: windowsJoin([2]string{folder, bin}), | ||||
| 			}) | ||||
| 		} | ||||
| 		url, err := tmpl.New(ctx).WithArtifact(archive).Apply(winget.URLTemplate) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		installer.Installers = append(installer.Installers, InstallerItem{ | ||||
| 			Architecture:         fromGoArch[archive.Goarch], | ||||
| 			NestedInstallerType:  "portable", | ||||
| 			NestedInstallerFiles: files, | ||||
| 			InstallerURL:         url, | ||||
| 			InstallerSha256:      sha256, | ||||
| 			UpgradeBehavior:      "uninstallPrevious", | ||||
| 		}) | ||||
| 		switch archive.Goarch { | ||||
| 		case "386": | ||||
| 			i386count++ | ||||
| 		case "amd64": | ||||
| 			amd64Count++ | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if i386count > 1 || amd64Count > 1 { | ||||
| 		return errMultipleArchives | ||||
| 	} | ||||
|  | ||||
| 	if err := createYAML(ctx, winget, installer, artifact.WingetInstaller); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return createYAML(ctx, winget, Locale{ | ||||
| 		PackageIdentifier: winget.PackageIdentifier, | ||||
| 		PackageVersion:    ctx.Version, | ||||
| 		PackageLocale:     defaultLocale, | ||||
| 		Publisher:         publisher, | ||||
| 		PublisherURL:      winget.PublisherURL, | ||||
| 		Author:            author, | ||||
| 		PackageName:       name, | ||||
| 		PackageURL:        winget.Homepage, | ||||
| 		License:           winget.License, | ||||
| 		LicenseURL:        winget.LicenseURL, | ||||
| 		Copyright:         winget.Copyright, | ||||
| 		ShortDescription:  shortDescription, | ||||
| 		Description:       description, | ||||
| 		Moniker:           name, | ||||
| 		Tags:              []string{}, | ||||
| 		ReleaseNotes:      ctx.ReleaseNotes, | ||||
| 		ReleaseNotesURL:   winget.ReleaseNotesURL, | ||||
| 		ManifestType:      "defaultLocale", | ||||
| 		ManifestVersion:   manifestVersion, | ||||
| 	}, artifact.WingetDefaultLocale) | ||||
| } | ||||
|  | ||||
| func (p Pipe) publishAll(ctx *context.Context, cli client.Client) error { | ||||
| 	skips := pipe.SkipMemento{} | ||||
| 	for _, files := range ctx.Artifacts.Filter(artifact.Or( | ||||
| 		artifact.ByType(artifact.WingetInstaller), | ||||
| 		artifact.ByType(artifact.WingetVersion), | ||||
| 		artifact.ByType(artifact.WingetDefaultLocale), | ||||
| 	)).GroupByID() { | ||||
| 		err := doPublish(ctx, cli, files) | ||||
| 		if err != nil && pipe.IsSkip(err) { | ||||
| 			skips.Remember(err) | ||||
| 			continue | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return skips.Evaluate() | ||||
| } | ||||
|  | ||||
| func doPublish(ctx *context.Context, cl client.Client, wingets []*artifact.Artifact) error { | ||||
| 	winget, err := artifact.Extra[config.Winget](*wingets[0], wingetConfigExtra) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if strings.TrimSpace(winget.SkipUpload) == "true" { | ||||
| 		return errSkipUpload | ||||
| 	} | ||||
|  | ||||
| 	if strings.TrimSpace(winget.SkipUpload) == "auto" && ctx.Semver.Prerelease != "" { | ||||
| 		return errSkipUploadAuto | ||||
| 	} | ||||
|  | ||||
| 	msg, err := tmpl.New(ctx).Apply(winget.CommitMessageTemplate) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	author, err := commitauthor.Get(ctx, winget.CommitAuthor) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	repo := client.RepoFromRef(winget.Repository) | ||||
|  | ||||
| 	var files []client.RepoFile | ||||
| 	for _, pkg := range wingets { | ||||
| 		content, err := os.ReadFile(pkg.Path) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		files = append(files, client.RepoFile{ | ||||
| 			Content: content, | ||||
| 			Path:    filepath.Join(winget.Path, pkg.Name), | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
| 	if winget.Repository.Git.URL != "" { | ||||
| 		return client.NewGitUploadClient(repo.Branch). | ||||
| 			CreateFiles(ctx, author, repo, msg, files) | ||||
| 	} | ||||
|  | ||||
| 	cl, err = client.NewIfToken(ctx, cl, winget.Repository.Token) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	for _, file := range files { | ||||
| 		if err := cl.CreateFile(ctx, author, repo, file.Content, file.Path, msg); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if !winget.Repository.PullRequest.Enabled { | ||||
| 		log.Debug("winget.pull_request disabled") | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	log.Info("winget.pull_request enabled, creating a PR") | ||||
| 	pcl, ok := cl.(client.PullRequestOpener) | ||||
| 	if !ok { | ||||
| 		return fmt.Errorf("client does not support pull requests") | ||||
| 	} | ||||
|  | ||||
| 	title := fmt.Sprintf("Updated %s to %s", ctx.Config.ProjectName, ctx.Version) | ||||
| 	return pcl.OpenPullRequest(ctx, client.Repo{ | ||||
| 		Name:   winget.Repository.PullRequest.Base.Name, | ||||
| 		Owner:  winget.Repository.PullRequest.Base.Owner, | ||||
| 		Branch: winget.Repository.PullRequest.Base.Branch, | ||||
| 	}, repo, title, winget.Repository.PullRequest.Draft) | ||||
| } | ||||
|  | ||||
| func langserverLineFor(tp artifact.Type) string { | ||||
| 	switch tp { | ||||
| 	case artifact.WingetInstaller: | ||||
| 		return installerLangServer | ||||
| 	case artifact.WingetDefaultLocale: | ||||
| 		return defaultLocaleLangServer | ||||
| 	default: | ||||
| 		return versionLangServer | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func extFor(tp artifact.Type) string { | ||||
| 	switch tp { | ||||
| 	case artifact.WingetVersion: | ||||
| 		return ".yaml" | ||||
| 	case artifact.WingetInstaller: | ||||
| 		return ".installer.yaml" | ||||
| 	case artifact.WingetDefaultLocale: | ||||
| 		return "." + defaultLocale + ".yaml" | ||||
| 	default: | ||||
| 		// should never happen | ||||
| 		return "" | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func windowsJoin(elem [2]string) string { | ||||
| 	if elem[0] == "" { | ||||
| 		return elem[1] | ||||
| 	} | ||||
| 	return elem[0] + "\\" + elem[1] | ||||
| } | ||||
							
								
								
									
										579
									
								
								internal/pipe/winget/winget_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										579
									
								
								internal/pipe/winget/winget_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,579 @@ | ||||
| package winget | ||||
|  | ||||
| import ( | ||||
| 	"html/template" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 	"testing" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/goreleaser/goreleaser/internal/artifact" | ||||
| 	"github.com/goreleaser/goreleaser/internal/client" | ||||
| 	"github.com/goreleaser/goreleaser/internal/golden" | ||||
| 	"github.com/goreleaser/goreleaser/internal/testctx" | ||||
| 	"github.com/goreleaser/goreleaser/pkg/config" | ||||
| 	"github.com/stretchr/testify/require" | ||||
| ) | ||||
|  | ||||
| func TestString(t *testing.T) { | ||||
| 	require.NotEmpty(t, Pipe{}.String()) | ||||
| } | ||||
|  | ||||
| func TestSkip(t *testing.T) { | ||||
| 	t.Run("should", func(t *testing.T) { | ||||
| 		require.True(t, Pipe{}.Skip(testctx.New())) | ||||
| 	}) | ||||
| 	t.Run("should not", func(t *testing.T) { | ||||
| 		require.False(t, Pipe{}.Skip(testctx.NewWithCfg(config.Project{ | ||||
| 			Winget: []config.Winget{{}}, | ||||
| 		}))) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func TestRunPipe(t *testing.T) { | ||||
| 	for _, tt := range []struct { | ||||
| 		name                 string | ||||
| 		expectRunErrorIs     error | ||||
| 		expectPublishErrorIs error | ||||
| 		expectPath           string | ||||
| 		winget               config.Winget | ||||
| 	}{ | ||||
| 		{ | ||||
| 			name:       "minimal", | ||||
| 			expectPath: "manifests/f/Foo/min/1.2.1/min.", | ||||
| 			winget: config.Winget{ | ||||
| 				Name:             "min", | ||||
| 				Publisher:        "Foo", | ||||
| 				License:          "MIT", | ||||
| 				ShortDescription: "foo bar zaz", | ||||
| 				IDs:              []string{"foo"}, | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner: "foo", | ||||
| 					Name:  "bar", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:       "full", | ||||
| 			expectPath: "manifests/b/Beckersoft LTDA/foo/1.2.1", | ||||
| 			winget: config.Winget{ | ||||
| 				Name:                  "foo", | ||||
| 				Publisher:             "Beckersoft", | ||||
| 				PublisherURL:          "https://carlosbecker.com", | ||||
| 				Copyright:             "bla bla bla", | ||||
| 				Author:                "Carlos Becker", | ||||
| 				Path:                  "manifests/b/Beckersoft LTDA/foo/{{.Version}}", | ||||
| 				Repository:            config.RepoRef{Owner: "foo", Name: "bar"}, | ||||
| 				CommitAuthor:          config.CommitAuthor{}, | ||||
| 				CommitMessageTemplate: "update foo to latest and greatest", | ||||
| 				IDs:                   []string{"foo"}, | ||||
| 				Goamd64:               "v1", | ||||
| 				SkipUpload:            "false", | ||||
| 				ShortDescription:      "foo", | ||||
| 				Description: `long foo bar | ||||
|  | ||||
| 				yadaa yada yada loooaaasssss | ||||
|  | ||||
| 				sss`, | ||||
| 				Homepage:        "https://goreleaser.com", | ||||
| 				License:         "MIT", | ||||
| 				LicenseURL:      "https://goreleaser.com/eula/", | ||||
| 				ReleaseNotesURL: "https://github.com/goreleaser/goreleaser/tags/{{.Tag}}", | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "open-pr", | ||||
| 			winget: config.Winget{ | ||||
| 				Name:             "foo", | ||||
| 				Publisher:        "Beckersoft", | ||||
| 				IDs:              []string{"foo"}, | ||||
| 				Description:      "my test", | ||||
| 				Homepage:         "https://goreleaser.com", | ||||
| 				License:          "mit", | ||||
| 				Path:             "pkgs/foo.winget", | ||||
| 				ShortDescription: "foo bar zaz", | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner:  "foo", | ||||
| 					Name:   "bar", | ||||
| 					Branch: "update-{{.Version}}", | ||||
| 					PullRequest: config.PullRequest{ | ||||
| 						Enabled: true, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "wrapped-in-dir", | ||||
| 			winget: config.Winget{ | ||||
| 				Name:             "wrapped-in-dir", | ||||
| 				Publisher:        "Beckersoft", | ||||
| 				IDs:              []string{"wrapped-in-dir"}, | ||||
| 				Description:      "my test", | ||||
| 				Homepage:         "https://goreleaser.com", | ||||
| 				License:          "mit", | ||||
| 				LicenseURL:       "https://goreleaser.com/license", | ||||
| 				ReleaseNotesURL:  "https://github.com/goreleaser/goreleaser/tags/{{.Tag}}", | ||||
| 				ShortDescription: "foo bar zaz", | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner: "foo", | ||||
| 					Name:  "bar", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "no-archives", | ||||
| 			expectRunErrorIs: errNoArchivesFound{ | ||||
| 				goamd64: "v2", | ||||
| 				ids:     []string{"nopenopenope"}, | ||||
| 			}, | ||||
| 			winget: config.Winget{ | ||||
| 				Name:             "no-archives", | ||||
| 				Publisher:        "Beckersoft", | ||||
| 				IDs:              []string{"nopenopenope"}, | ||||
| 				Goamd64:          "v2", | ||||
| 				License:          "MIT", | ||||
| 				ShortDescription: "foo bar zaz", | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner: "foo", | ||||
| 					Name:  "bar", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:             "too-many-archives", | ||||
| 			expectRunErrorIs: errMultipleArchives, | ||||
| 			winget: config.Winget{ | ||||
| 				Name:             "min", | ||||
| 				Publisher:        "Foo", | ||||
| 				License:          "MIT", | ||||
| 				ShortDescription: "foo bar zaz", | ||||
| 				IDs:              []string{}, | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner: "foo", | ||||
| 					Name:  "bar", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "partial", | ||||
| 			winget: config.Winget{ | ||||
| 				Name:             "partial", | ||||
| 				Publisher:        "Beckersoft", | ||||
| 				IDs:              []string{"partial"}, | ||||
| 				License:          "MIT", | ||||
| 				ShortDescription: "foo bar zaz", | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner: "foo", | ||||
| 					Name:  "bar", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:             "no-repo-name", | ||||
| 			expectRunErrorIs: errNoRepoName, | ||||
| 			winget: config.Winget{ | ||||
| 				Name:             "doesnotmatter", | ||||
| 				Publisher:        "Beckersoft", | ||||
| 				License:          "MIT", | ||||
| 				ShortDescription: "foo bar zaz", | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner: "foo", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:             "no-license", | ||||
| 			expectRunErrorIs: errNoLicense, | ||||
| 			winget: config.Winget{ | ||||
| 				Name:             "doesnotmatter", | ||||
| 				Publisher:        "Beckersoft", | ||||
| 				ShortDescription: "aa", | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Name:  "foo", | ||||
| 					Owner: "foo", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:             "no-short-description", | ||||
| 			expectRunErrorIs: errNoShortDescription, | ||||
| 			winget: config.Winget{ | ||||
| 				Name:      "doesnotmatter", | ||||
| 				Publisher: "Beckersoft", | ||||
| 				License:   "MIT", | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Name:  "foo", | ||||
| 					Owner: "foo", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:             "invalid-package-identifier", | ||||
| 			expectRunErrorIs: errInvalidPackageIdentifier, | ||||
| 			winget: config.Winget{ | ||||
| 				Name:              "min", | ||||
| 				PackageIdentifier: "foobar", | ||||
| 				Publisher:         "Foo", | ||||
| 				License:           "MIT", | ||||
| 				ShortDescription:  "foo bar zaz", | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner: "foo", | ||||
| 					Name:  "bar", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:             "no-publisher", | ||||
| 			expectRunErrorIs: errNoPublisher, | ||||
| 			winget: config.Winget{ | ||||
| 				Name:             "min", | ||||
| 				License:          "MIT", | ||||
| 				ShortDescription: "foo bar zaz", | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner: "foo", | ||||
| 					Name:  "bar", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:             "bad-name-tmpl", | ||||
| 			expectRunErrorIs: &template.Error{}, | ||||
| 			winget: config.Winget{ | ||||
| 				Name:             "{{ .Nope }}", | ||||
| 				Publisher:        "Beckersoft", | ||||
| 				License:          "MIT", | ||||
| 				ShortDescription: "foo bar zaz", | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner: "foo", | ||||
| 					Name:  "bar", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:             "bad-publisher-tmpl", | ||||
| 			expectRunErrorIs: &template.Error{}, | ||||
| 			winget: config.Winget{ | ||||
| 				Name:             "foo", | ||||
| 				Publisher:        "{{ .Nope }}", | ||||
| 				License:          "MIT", | ||||
| 				ShortDescription: "foo bar zaz", | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner: "foo", | ||||
| 					Name:  "bar", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:             "bad-publisher-url-tmpl", | ||||
| 			expectRunErrorIs: &template.Error{}, | ||||
| 			winget: config.Winget{ | ||||
| 				Name:             "foo", | ||||
| 				Publisher:        "Beckersoft", | ||||
| 				PublisherURL:     "{{ .Nope }}", | ||||
| 				License:          "MIT", | ||||
| 				ShortDescription: "foo bar zaz", | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner: "foo", | ||||
| 					Name:  "bar", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:             "bad-author-tmpl", | ||||
| 			expectRunErrorIs: &template.Error{}, | ||||
| 			winget: config.Winget{ | ||||
| 				Name:             "foobar", | ||||
| 				Publisher:        "Beckersoft", | ||||
| 				Author:           "{{ .Nope }}", | ||||
| 				License:          "MIT", | ||||
| 				ShortDescription: "foo bar zaz", | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner: "foo", | ||||
| 					Name:  "bar", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:             "bad-homepage-tmpl", | ||||
| 			expectRunErrorIs: &template.Error{}, | ||||
| 			winget: config.Winget{ | ||||
| 				Name:             "foobar", | ||||
| 				Publisher:        "Beckersoft", | ||||
| 				Homepage:         "{{ .Nope }}", | ||||
| 				License:          "MIT", | ||||
| 				ShortDescription: "foo bar zaz", | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner: "foo", | ||||
| 					Name:  "bar", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:             "bad-description-tmpl", | ||||
| 			expectRunErrorIs: &template.Error{}, | ||||
| 			winget: config.Winget{ | ||||
| 				Name:             "foobar", | ||||
| 				Publisher:        "Beckersoft", | ||||
| 				Description:      "{{ .Nope }}", | ||||
| 				License:          "MIT", | ||||
| 				ShortDescription: "foo bar zaz", | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner: "foo", | ||||
| 					Name:  "bar", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:             "bad-short-description-tmpl", | ||||
| 			expectRunErrorIs: &template.Error{}, | ||||
| 			winget: config.Winget{ | ||||
| 				Name:             "foobar", | ||||
| 				Publisher:        "Beckersoft", | ||||
| 				ShortDescription: "{{ .Nope }}", | ||||
| 				License:          "MIT", | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner: "foo", | ||||
| 					Name:  "bar", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:             "bad-repo-tmpl", | ||||
| 			expectRunErrorIs: &template.Error{}, | ||||
| 			winget: config.Winget{ | ||||
| 				Name:             "doesnotmatter", | ||||
| 				Publisher:        "Beckersoft", | ||||
| 				License:          "MIT", | ||||
| 				ShortDescription: "foo bar zaz", | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner: "foo", | ||||
| 					Name:  "{{ .Nope }}", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:             "bad-skip-upload-tmpl", | ||||
| 			expectRunErrorIs: &template.Error{}, | ||||
| 			winget: config.Winget{ | ||||
| 				Name:             "doesnotmatter", | ||||
| 				Publisher:        "Beckersoft", | ||||
| 				SkipUpload:       "{{ .Nope }}", | ||||
| 				License:          "MIT", | ||||
| 				ShortDescription: "foo bar zaz", | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner: "foo", | ||||
| 					Name:  "bar", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:             "bad-release-notes-url-tmpl", | ||||
| 			expectRunErrorIs: &template.Error{}, | ||||
| 			winget: config.Winget{ | ||||
| 				Name:             "foo", | ||||
| 				Publisher:        "Beckersoft", | ||||
| 				ReleaseNotesURL:  `https://goo/bar/asdfsd/{{.nope}}`, | ||||
| 				License:          "MIT", | ||||
| 				ShortDescription: "foo bar zaz", | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner: "foo", | ||||
| 					Name:  "bar", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:             "bad-release-url-tmpl", | ||||
| 			expectRunErrorIs: &template.Error{}, | ||||
| 			winget: config.Winget{ | ||||
| 				Name:             "foo", | ||||
| 				Publisher:        "Beckersoft", | ||||
| 				URLTemplate:      "{{.BadURL}}", | ||||
| 				License:          "MIT", | ||||
| 				ShortDescription: "foo bar zaz", | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner: "foo", | ||||
| 					Name:  "bar", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:             "bad-path-tmpl", | ||||
| 			expectRunErrorIs: &template.Error{}, | ||||
| 			winget: config.Winget{ | ||||
| 				Name:             "foo", | ||||
| 				Publisher:        "Beckersoft", | ||||
| 				License:          "MIT", | ||||
| 				Path:             "{{ .Nope }}", | ||||
| 				ShortDescription: "foo bar zaz", | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner: "foo", | ||||
| 					Name:  "bar", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:                 "bad-commit-msg-tmpl", | ||||
| 			expectPublishErrorIs: &template.Error{}, | ||||
| 			winget: config.Winget{ | ||||
| 				Name:                  "foo", | ||||
| 				Publisher:             "Beckersoft", | ||||
| 				License:               "MIT", | ||||
| 				ShortDescription:      "foo bar zaz", | ||||
| 				CommitMessageTemplate: "{{.Foo}}", | ||||
| 				IDs:                   []string{"foo"}, | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner: "foo", | ||||
| 					Name:  "bar", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:                 "skip-upload", | ||||
| 			expectPublishErrorIs: errSkipUpload, | ||||
| 			winget: config.Winget{ | ||||
| 				Name:             "doesnotmatter", | ||||
| 				Publisher:        "Beckersoft", | ||||
| 				SkipUpload:       "true", | ||||
| 				License:          "MIT", | ||||
| 				IDs:              []string{"foo"}, | ||||
| 				ShortDescription: "foo bar zaz", | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner: "foo", | ||||
| 					Name:  "bar", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:                 "skip-upload-auto", | ||||
| 			expectPublishErrorIs: errSkipUploadAuto, | ||||
| 			winget: config.Winget{ | ||||
| 				Name:             "doesnotmatter", | ||||
| 				Publisher:        "Beckersoft", | ||||
| 				License:          "MIT", | ||||
| 				ShortDescription: "foo bar zaz", | ||||
| 				IDs:              []string{"foo"}, | ||||
| 				SkipUpload:       "auto", | ||||
| 				Repository: config.RepoRef{ | ||||
| 					Owner: "foo", | ||||
| 					Name:  "bar", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} { | ||||
| 		t.Run(tt.name, func(t *testing.T) { | ||||
| 			folder := t.TempDir() | ||||
| 			ctx := testctx.NewWithCfg( | ||||
| 				config.Project{ | ||||
| 					Dist:        folder, | ||||
| 					ProjectName: "foo", | ||||
| 					Winget:      []config.Winget{tt.winget}, | ||||
| 				}, | ||||
| 				testctx.WithVersion("1.2.1"), | ||||
| 				testctx.WithCurrentTag("v1.2.1"), | ||||
| 				testctx.WithSemver(1, 2, 1, "rc1"), | ||||
| 				testctx.WithDate(time.Date(2023, 6, 12, 20, 32, 10, 12, time.Local)), | ||||
| 			) | ||||
| 			createFakeArtifact := func(id, goos, goarch, goamd64, goarm string, extra map[string]any) { | ||||
| 				path := filepath.Join(folder, "dist/foo_"+goos+goarch+goamd64+goarm+".zip") | ||||
| 				art := artifact.Artifact{ | ||||
| 					Name:    "foo_" + goos + "_" + goarch + goamd64 + goarm + ".zip", | ||||
| 					Path:    path, | ||||
| 					Goos:    goos, | ||||
| 					Goarch:  goarch, | ||||
| 					Goarm:   goarm, | ||||
| 					Goamd64: goamd64, | ||||
| 					Type:    artifact.UploadableArchive, | ||||
| 					Extra: map[string]interface{}{ | ||||
| 						artifact.ExtraID:        id, | ||||
| 						artifact.ExtraFormat:    "zip", | ||||
| 						artifact.ExtraBinaries:  []string{"foo.exe"}, | ||||
| 						artifact.ExtraWrappedIn: "", | ||||
| 					}, | ||||
| 				} | ||||
| 				for k, v := range extra { | ||||
| 					art.Extra[k] = v | ||||
| 				} | ||||
| 				ctx.Artifacts.Add(&art) | ||||
|  | ||||
| 				require.NoError(t, os.MkdirAll(filepath.Dir(path), 0o755)) | ||||
| 				f, err := os.Create(path) | ||||
| 				require.NoError(t, err) | ||||
| 				require.NoError(t, f.Close()) | ||||
| 			} | ||||
|  | ||||
| 			goos := "windows" | ||||
| 			goarch := "amd64" | ||||
| 			createFakeArtifact("partial", goos, goarch, "v1", "", nil) | ||||
| 			createFakeArtifact("foo", goos, goarch, "v1", "", nil) | ||||
| 			createFakeArtifact("wrapped-in-dir", goos, goarch, "v1", "", map[string]any{artifact.ExtraWrappedIn: "foo"}) | ||||
|  | ||||
| 			goarch = "3864" | ||||
| 			createFakeArtifact("foo", goos, goarch, "", "", nil) | ||||
| 			createFakeArtifact("wrapped-in-dir", goos, goarch, "", "", map[string]any{artifact.ExtraWrappedIn: "foo"}) | ||||
|  | ||||
| 			client := client.NewMock() | ||||
| 			pipe := Pipe{} | ||||
|  | ||||
| 			// default | ||||
| 			require.NoError(t, pipe.Default(ctx)) | ||||
|  | ||||
| 			// run | ||||
| 			if tt.expectRunErrorIs != nil { | ||||
| 				err := pipe.runAll(ctx, client) | ||||
| 				require.Error(t, err) | ||||
| 				require.ErrorAs(t, err, &tt.expectPublishErrorIs) | ||||
| 				return | ||||
| 			} | ||||
|  | ||||
| 			require.NoError(t, pipe.runAll(ctx, client)) | ||||
| 			for _, winget := range ctx.Artifacts.Filter(artifact.Or( | ||||
| 				artifact.ByType(artifact.WingetInstaller), | ||||
| 				artifact.ByType(artifact.WingetVersion), | ||||
| 				artifact.ByType(artifact.WingetDefaultLocale), | ||||
| 			)).List() { | ||||
| 				bts, err := os.ReadFile(winget.Path) | ||||
| 				require.NoError(t, err) | ||||
| 				golden.RequireEqualExtSubfolder(t, bts, extFor(winget.Type)) | ||||
| 			} | ||||
|  | ||||
| 			// publish | ||||
| 			if tt.expectPublishErrorIs != nil { | ||||
| 				err := pipe.publishAll(ctx, client) | ||||
| 				require.Error(t, err) | ||||
| 				require.ErrorAs(t, err, &tt.expectPublishErrorIs) | ||||
| 				return | ||||
| 			} | ||||
| 			require.NoError(t, pipe.publishAll(ctx, client)) | ||||
| 			require.True(t, client.CreatedFile) | ||||
|  | ||||
| 			require.NotEmpty(t, client.Path) | ||||
| 			if tt.expectPath != "" { | ||||
| 				require.Truef(t, strings.HasPrefix(client.Path, tt.expectPath), "expected %q to begin with %q", client.Path, tt.expectPath) | ||||
| 			} | ||||
|  | ||||
| 			if tt.winget.Repository.PullRequest.Enabled { | ||||
| 				require.True(t, client.OpenedPullRequest) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestErrNoArchivesFound(t *testing.T) { | ||||
| 	require.EqualError(t, errNoArchivesFound{ | ||||
| 		goamd64: "v1", | ||||
| 		ids:     []string{"foo", "bar"}, | ||||
| 	}, "no zip archives found matching goos=[windows] goarch=[amd64 386] goamd64=v1 ids=[foo bar]") | ||||
| } | ||||
|  | ||||
| func TestDefault(t *testing.T) { | ||||
| 	ctx := testctx.NewWithCfg(config.Project{ | ||||
| 		ProjectName: "foo", | ||||
| 		Winget:      []config.Winget{{}}, | ||||
| 	}) | ||||
| 	require.NoError(t, Pipe{}.Default(ctx)) | ||||
| 	winget := ctx.Config.Winget[0] | ||||
| 	require.Equal(t, "v1", winget.Goamd64) | ||||
| 	require.NotEmpty(t, winget.CommitMessageTemplate) | ||||
| 	require.Equal(t, "foo", winget.Name) | ||||
| } | ||||
| @@ -36,6 +36,7 @@ import ( | ||||
| 	"github.com/goreleaser/goreleaser/internal/pipe/sourcearchive" | ||||
| 	"github.com/goreleaser/goreleaser/internal/pipe/universalbinary" | ||||
| 	"github.com/goreleaser/goreleaser/internal/pipe/upx" | ||||
| 	"github.com/goreleaser/goreleaser/internal/pipe/winget" | ||||
| 	"github.com/goreleaser/goreleaser/pkg/context" | ||||
| ) | ||||
|  | ||||
| @@ -112,6 +113,8 @@ var Pipeline = append( | ||||
| 	aur.Pipe{}, | ||||
| 	// create nixpkgs | ||||
| 	nix.NewBuild(), | ||||
| 	// winget installers | ||||
| 	winget.Pipe{}, | ||||
| 	// create brew tap | ||||
| 	brew.Pipe{}, | ||||
| 	// krew plugins | ||||
|   | ||||
| @@ -260,6 +260,29 @@ type Nix struct { | ||||
| 	License               string       `yaml:"license,omitempty" json:"license,omitempty"` | ||||
| } | ||||
|  | ||||
| type Winget struct { | ||||
| 	Name                  string       `yaml:"name,omitempty" json:"name,omitempty"` | ||||
| 	PackageIdentifier     string       `yaml:"package_identifier,omitempty" json:"package_identifier,omitempty"` | ||||
| 	Publisher             string       `yaml:"publisher,omitempty" json:"publisher,omitempty"` | ||||
| 	PublisherURL          string       `yaml:"publisher_url,omitempty" json:"publisher_url,omitempty"` | ||||
| 	Copyright             string       `yaml:"copyright,omitempty" json:"copyright,omitempty"` | ||||
| 	Author                string       `yaml:"author,omitempty" json:"author,omitempty"` | ||||
| 	Path                  string       `yaml:"path,omitempty" json:"path,omitempty"` | ||||
| 	Repository            RepoRef      `yaml:"repository,omitempty" json:"repository,omitempty"` | ||||
| 	CommitAuthor          CommitAuthor `yaml:"commit_author,omitempty" json:"commit_author,omitempty"` | ||||
| 	CommitMessageTemplate string       `yaml:"commit_msg_template,omitempty" json:"commit_msg_template,omitempty"` | ||||
| 	IDs                   []string     `yaml:"ids,omitempty" json:"ids,omitempty"` | ||||
| 	Goamd64               string       `yaml:"goamd64,omitempty" json:"goamd64,omitempty"` | ||||
| 	SkipUpload            string       `yaml:"skip_upload,omitempty" json:"skip_upload,omitempty" jsonschema:"oneof_type=string;boolean"` | ||||
| 	URLTemplate           string       `yaml:"url_template,omitempty" json:"url_template,omitempty"` | ||||
| 	ShortDescription      string       `yaml:"short_description,omitempty" json:"short_description,omitempty"` | ||||
| 	Description           string       `yaml:"description,omitempty" json:"description,omitempty"` | ||||
| 	Homepage              string       `yaml:"homepage,omitempty" json:"homepage,omitempty"` | ||||
| 	License               string       `yaml:"license,omitempty" json:"license,omitempty"` | ||||
| 	LicenseURL            string       `yaml:"license_url,omitempty" json:"license_url,omitempty"` | ||||
| 	ReleaseNotesURL       string       `yaml:"release_notes_url,omitempty" json:"release_notes_url,omitempty"` | ||||
| } | ||||
|  | ||||
| // Krew contains the krew section. | ||||
| type Krew struct { | ||||
| 	IDs                   []string     `yaml:"ids,omitempty" json:"ids,omitempty"` | ||||
| @@ -1036,6 +1059,7 @@ type Project struct { | ||||
| 	Milestones      []Milestone      `yaml:"milestones,omitempty" json:"milestones,omitempty"` | ||||
| 	Brews           []Homebrew       `yaml:"brews,omitempty" json:"brews,omitempty"` | ||||
| 	Nix             []Nix            `yaml:"nix,omitempty" json:"nix,omitempty"` | ||||
| 	Winget          []Winget         `yaml:"winget,omitempty" json:"winget,omitempty"` | ||||
| 	AURs            []AUR            `yaml:"aurs,omitempty" json:"aurs,omitempty"` | ||||
| 	Krews           []Krew           `yaml:"krews,omitempty" json:"krews,omitempty"` | ||||
| 	Kos             []Ko             `yaml:"kos,omitempty" json:"kos,omitempty"` | ||||
|   | ||||
| @@ -43,6 +43,7 @@ import ( | ||||
| 	"github.com/goreleaser/goreleaser/internal/pipe/upload" | ||||
| 	"github.com/goreleaser/goreleaser/internal/pipe/upx" | ||||
| 	"github.com/goreleaser/goreleaser/internal/pipe/webhook" | ||||
| 	"github.com/goreleaser/goreleaser/internal/pipe/winget" | ||||
| 	"github.com/goreleaser/goreleaser/pkg/context" | ||||
| ) | ||||
|  | ||||
| @@ -80,6 +81,7 @@ var Defaulters = []Defaulter{ | ||||
| 	upload.Pipe{}, | ||||
| 	aur.Pipe{}, | ||||
| 	nix.Pipe{}, | ||||
| 	winget.Pipe{}, | ||||
| 	brew.Pipe{}, | ||||
| 	krew.Pipe{}, | ||||
| 	ko.Pipe{}, | ||||
|   | ||||
							
								
								
									
										111
									
								
								www/docs/customization/winget.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								www/docs/customization/winget.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | ||||
| # Winget | ||||
|  | ||||
| > Since: v1.19 | ||||
|  | ||||
| After releasing to GitHub, GitLab, or Gitea, GoReleaser can generate and publish | ||||
| a _winget manifest_ and commit to a git repository, and PR it to `winget-pkgs` | ||||
| if instructed to. | ||||
|  | ||||
| The `winget` section specifies how the **manifests** should be created: | ||||
|  | ||||
| ```yaml | ||||
| # .goreleaser.yaml | ||||
| winget: | ||||
|   - # Name of the recipe | ||||
|     # | ||||
|     # Default: ProjectName | ||||
|     # Templates: allowed | ||||
|     name: myproject | ||||
|  | ||||
|     # Publisher name. | ||||
|     # | ||||
|     # Templates: allowed | ||||
|     # Required. | ||||
|     publisher: Foo Inc | ||||
|  | ||||
|     # Your app's description. | ||||
|     # | ||||
|     # Templates: allowed | ||||
|     # Required. | ||||
|     short_description: "Software to create fast and easy drum rolls." | ||||
|  | ||||
|     # License name. | ||||
|     # Required. | ||||
|     license: "mit" | ||||
|  | ||||
|     # Publisher URL. | ||||
|     # | ||||
|     # Templates: allowed | ||||
|     publisher_url: https://goreleaser.com | ||||
|  | ||||
|     # Package identifier. | ||||
|     # | ||||
|     # Default: Publisher.ProjectName | ||||
|     # Templates: allowed | ||||
|     package_identifier: myproject.myproject | ||||
|  | ||||
|     # IDs of the archives to use. | ||||
|     # Empty means all IDs. | ||||
|     ids: | ||||
|       - foo | ||||
|       - bar | ||||
|  | ||||
|     # GOAMD64 to specify which amd64 version to use if there are multiple | ||||
|     # versions from the build section. | ||||
|     # | ||||
|     # Default: v1 | ||||
|     goamd64: v1 | ||||
|  | ||||
|     # URL which is determined by the given Token (github, gitlab or gitea). | ||||
|     # | ||||
|     # Default depends on the client. | ||||
|     # Templates: allowed | ||||
|     url_template: "https://github.mycompany.com/foo/bar/releases/download/{{ .Tag }}/{{ .ArtifactName }}" | ||||
|  | ||||
|     # Git author used to commit to the repository. | ||||
|     commit_author: | ||||
|       name: goreleaserbot | ||||
|       email: bot@goreleaser.com | ||||
|  | ||||
|     # The project name and current git tag are used in the format string. | ||||
|     # | ||||
|     # Templates: allowed | ||||
|     commit_msg_template: "{{ .ProjectName }}: {{ .Tag }}" | ||||
|  | ||||
|     # Path for the file inside the repository. | ||||
|     # | ||||
|     # Default: manifests/<lowercased first char of publisher>/<publisher>/<version> | ||||
|     path: manifests/g/goreleaser/1.19 | ||||
|  | ||||
|     # Your app's homepage. | ||||
|     homepage: "https://example.com/" | ||||
|  | ||||
|     # Your app's long description. | ||||
|     # | ||||
|     # Templates: allowed | ||||
|     description: "Software to create fast and easy drum rolls." | ||||
|  | ||||
|     # License URL. | ||||
|     license_url: "https://goreleaser.com/license" | ||||
|  | ||||
|     # Copyright. | ||||
|     copyright: "Becker Software LTDA" | ||||
|  | ||||
|     # Setting this will prevent goreleaser to actually try to commit the updated | ||||
|     # package - instead, it will be stored on the dist folder only, | ||||
|     # leaving the responsibility of publishing it to the user. | ||||
|     # | ||||
|     # If set to auto, the release will not be uploaded to the repository | ||||
|     # in case there is an indicator for prerelease in the tag e.g. v1.0.0-rc1 | ||||
|     # | ||||
|     # Templates: allowed | ||||
|     skip_upload: true | ||||
|  | ||||
| {% include-markdown "../includes/repository.md" comments=false %} | ||||
| ``` | ||||
|  | ||||
| !!! tip | ||||
|  | ||||
|     Learn more about the [name template engine](/customization/templates/). | ||||
|  | ||||
| {% include-markdown "../includes/prs.md" comments=false %} | ||||
| @@ -131,6 +131,7 @@ nav: | ||||
|           - customization/fury.md | ||||
|           - customization/homebrew.md | ||||
|           - customization/nix.md | ||||
|           - customization/winget.md | ||||
|           - customization/aur.md | ||||
|           - customization/krew.md | ||||
|           - customization/scoop.md | ||||
|   | ||||
		Reference in New Issue
	
	Block a user