github.com/windmeup/goreleaser@v1.21.95/internal/pipe/winget/winget_test.go (about)

     1  package winget
     2  
     3  import (
     4  	"html/template"
     5  	"os"
     6  	"path/filepath"
     7  	"strings"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/stretchr/testify/require"
    12  	"github.com/windmeup/goreleaser/internal/artifact"
    13  	"github.com/windmeup/goreleaser/internal/client"
    14  	"github.com/windmeup/goreleaser/internal/golden"
    15  	"github.com/windmeup/goreleaser/internal/skips"
    16  	"github.com/windmeup/goreleaser/internal/testctx"
    17  	"github.com/windmeup/goreleaser/pkg/config"
    18  )
    19  
    20  func TestContinueOnError(t *testing.T) {
    21  	require.True(t, Pipe{}.ContinueOnError())
    22  }
    23  
    24  func TestString(t *testing.T) {
    25  	require.NotEmpty(t, Pipe{}.String())
    26  }
    27  
    28  func TestSkip(t *testing.T) {
    29  	t.Run("should", func(t *testing.T) {
    30  		require.True(t, Pipe{}.Skip(testctx.New()))
    31  	})
    32  	t.Run("skip flag", func(t *testing.T) {
    33  		require.True(t, Pipe{}.Skip(testctx.NewWithCfg(config.Project{
    34  			Winget: []config.Winget{{}},
    35  		}, testctx.Skip(skips.Winget))))
    36  	})
    37  	t.Run("should not", func(t *testing.T) {
    38  		require.False(t, Pipe{}.Skip(testctx.NewWithCfg(config.Project{
    39  			Winget: []config.Winget{{}},
    40  		})))
    41  	})
    42  }
    43  
    44  func TestRunPipe(t *testing.T) {
    45  	for _, tt := range []struct {
    46  		name                 string
    47  		expectRunErrorIs     error
    48  		expectPublishErrorIs error
    49  		expectPath           string
    50  		winget               config.Winget
    51  	}{
    52  		{
    53  			name:       "minimal",
    54  			expectPath: "manifests/f/Foo/min/1.2.1/Foo.min.",
    55  			winget: config.Winget{
    56  				Name:             "min",
    57  				Publisher:        "Foo",
    58  				License:          "MIT",
    59  				ShortDescription: "foo bar zaz",
    60  				IDs:              []string{"foo"},
    61  				Repository: config.RepoRef{
    62  					Owner: "foo",
    63  					Name:  "bar",
    64  				},
    65  			},
    66  		},
    67  		{
    68  			name:       "full",
    69  			expectPath: "manifests/b/Beckersoft LTDA/foo/1.2.1",
    70  			winget: config.Winget{
    71  				Name:                "foo",
    72  				Publisher:           "Beckersoft",
    73  				PublisherURL:        "https://carlosbecker.com",
    74  				PublisherSupportURL: "https://carlosbecker.com/support",
    75  				Copyright:           "bla bla bla",
    76  				CopyrightURL:        "https://goreleaser.com/copyright",
    77  				Author:              "Carlos Becker",
    78  				Path:                "manifests/b/Beckersoft LTDA/foo/{{.Version}}",
    79  				Repository:          config.RepoRef{Owner: "foo", Name: "bar"},
    80  				CommitAuthor:        config.CommitAuthor{},
    81  				IDs:                 []string{"foo"},
    82  				Goamd64:             "v1",
    83  				SkipUpload:          "false",
    84  				ShortDescription:    "foo",
    85  				Description: `long foo bar
    86  
    87  				yadaa yada yada loooaaasssss
    88  
    89  				sss`,
    90  				Homepage:        "https://goreleaser.com",
    91  				License:         "MIT",
    92  				LicenseURL:      "https://goreleaser.com/eula/",
    93  				ReleaseNotesURL: "https://github.com/windmeup/goreleaser/tags/{{.Tag}}",
    94  				ReleaseNotes:    "{{.Changelog}}",
    95  				Tags:            []string{"foo", "bar"},
    96  			},
    97  		},
    98  		{
    99  			name: "open-pr",
   100  			winget: config.Winget{
   101  				Name:             "foo",
   102  				Publisher:        "Beckersoft",
   103  				IDs:              []string{"foo"},
   104  				Description:      "my test",
   105  				Homepage:         "https://goreleaser.com",
   106  				License:          "mit",
   107  				Path:             "pkgs/foo.winget",
   108  				ShortDescription: "foo bar zaz",
   109  				Repository: config.RepoRef{
   110  					Owner:  "foo",
   111  					Name:   "bar",
   112  					Branch: "update-{{.Version}}",
   113  					PullRequest: config.PullRequest{
   114  						Enabled: true,
   115  					},
   116  				},
   117  			},
   118  		},
   119  		{
   120  			name: "wrapped-in-dir",
   121  			winget: config.Winget{
   122  				Name:             "wrapped-in-dir",
   123  				Publisher:        "Beckersoft",
   124  				IDs:              []string{"wrapped-in-dir"},
   125  				Description:      "my test",
   126  				Homepage:         "https://goreleaser.com",
   127  				License:          "mit",
   128  				LicenseURL:       "https://goreleaser.com/license",
   129  				ReleaseNotesURL:  "https://github.com/windmeup/goreleaser/tags/{{.Tag}}",
   130  				ShortDescription: "foo bar zaz",
   131  				Repository: config.RepoRef{
   132  					Owner: "foo",
   133  					Name:  "bar",
   134  				},
   135  			},
   136  		},
   137  		{
   138  			name: "no-archives",
   139  			expectRunErrorIs: errNoArchivesFound{
   140  				goamd64: "v2",
   141  				ids:     []string{"nopenopenope"},
   142  			},
   143  			winget: config.Winget{
   144  				Name:             "no-archives",
   145  				Publisher:        "Beckersoft",
   146  				IDs:              []string{"nopenopenope"},
   147  				Goamd64:          "v2",
   148  				License:          "MIT",
   149  				ShortDescription: "foo bar zaz",
   150  				Repository: config.RepoRef{
   151  					Owner: "foo",
   152  					Name:  "bar",
   153  				},
   154  			},
   155  		},
   156  		{
   157  			name:             "too-many-archives",
   158  			expectRunErrorIs: errMultipleArchives,
   159  			winget: config.Winget{
   160  				Name:             "min",
   161  				Publisher:        "Foo",
   162  				License:          "MIT",
   163  				ShortDescription: "foo bar zaz",
   164  				IDs:              []string{},
   165  				Repository: config.RepoRef{
   166  					Owner: "foo",
   167  					Name:  "bar",
   168  				},
   169  			},
   170  		},
   171  		{
   172  			name: "partial",
   173  			winget: config.Winget{
   174  				Name:             "partial",
   175  				Publisher:        "Beckersoft",
   176  				IDs:              []string{"partial"},
   177  				License:          "MIT",
   178  				ShortDescription: "foo bar zaz",
   179  				Repository: config.RepoRef{
   180  					Owner: "foo",
   181  					Name:  "bar",
   182  				},
   183  			},
   184  		},
   185  		{
   186  			name:             "no-repo-name",
   187  			expectRunErrorIs: errNoRepoName,
   188  			winget: config.Winget{
   189  				Name:             "doesnotmatter",
   190  				Publisher:        "Beckersoft",
   191  				License:          "MIT",
   192  				ShortDescription: "foo bar zaz",
   193  				Repository: config.RepoRef{
   194  					Owner: "foo",
   195  				},
   196  			},
   197  		},
   198  		{
   199  			name:             "no-license",
   200  			expectRunErrorIs: errNoLicense,
   201  			winget: config.Winget{
   202  				Name:             "doesnotmatter",
   203  				Publisher:        "Beckersoft",
   204  				ShortDescription: "aa",
   205  				Repository: config.RepoRef{
   206  					Name:  "foo",
   207  					Owner: "foo",
   208  				},
   209  			},
   210  		},
   211  		{
   212  			name:             "no-short-description",
   213  			expectRunErrorIs: errNoShortDescription,
   214  			winget: config.Winget{
   215  				Name:      "doesnotmatter",
   216  				Publisher: "Beckersoft",
   217  				License:   "MIT",
   218  				Repository: config.RepoRef{
   219  					Name:  "foo",
   220  					Owner: "foo",
   221  				},
   222  			},
   223  		},
   224  		{
   225  			name:             "invalid-package-identifier",
   226  			expectRunErrorIs: errInvalidPackageIdentifier,
   227  			winget: config.Winget{
   228  				Name:              "min",
   229  				PackageIdentifier: "foobar",
   230  				Publisher:         "Foo",
   231  				License:           "MIT",
   232  				ShortDescription:  "foo bar zaz",
   233  				Repository: config.RepoRef{
   234  					Owner: "foo",
   235  					Name:  "bar",
   236  				},
   237  			},
   238  		},
   239  		{
   240  			name:             "no-publisher",
   241  			expectRunErrorIs: errNoPublisher,
   242  			winget: config.Winget{
   243  				Name:             "min",
   244  				License:          "MIT",
   245  				ShortDescription: "foo bar zaz",
   246  				Repository: config.RepoRef{
   247  					Owner: "foo",
   248  					Name:  "bar",
   249  				},
   250  			},
   251  		},
   252  		{
   253  			name:             "bad-name-tmpl",
   254  			expectRunErrorIs: &template.Error{},
   255  			winget: config.Winget{
   256  				Name:             "{{ .Nope }}",
   257  				Publisher:        "Beckersoft",
   258  				License:          "MIT",
   259  				ShortDescription: "foo bar zaz",
   260  				Repository: config.RepoRef{
   261  					Owner: "foo",
   262  					Name:  "bar",
   263  				},
   264  			},
   265  		},
   266  		{
   267  			name:             "bad-releasenotes-tmpl",
   268  			expectRunErrorIs: &template.Error{},
   269  			winget: config.Winget{
   270  				ReleaseNotes:     "{{ .Nope }}",
   271  				Publisher:        "Beckersoft",
   272  				License:          "MIT",
   273  				ShortDescription: "foo bar zaz",
   274  				Repository: config.RepoRef{
   275  					Owner: "foo",
   276  					Name:  "bar",
   277  				},
   278  			},
   279  		},
   280  		{
   281  			name:             "bad-publisher-tmpl",
   282  			expectRunErrorIs: &template.Error{},
   283  			winget: config.Winget{
   284  				Name:             "foo",
   285  				Publisher:        "{{ .Nope }}",
   286  				License:          "MIT",
   287  				ShortDescription: "foo bar zaz",
   288  				Repository: config.RepoRef{
   289  					Owner: "foo",
   290  					Name:  "bar",
   291  				},
   292  			},
   293  		},
   294  		{
   295  			name:             "bad-publisher-url-tmpl",
   296  			expectRunErrorIs: &template.Error{},
   297  			winget: config.Winget{
   298  				Name:             "foo",
   299  				Publisher:        "Beckersoft",
   300  				PublisherURL:     "{{ .Nope }}",
   301  				License:          "MIT",
   302  				ShortDescription: "foo bar zaz",
   303  				Repository: config.RepoRef{
   304  					Owner: "foo",
   305  					Name:  "bar",
   306  				},
   307  			},
   308  		},
   309  		{
   310  			name:             "bad-author-tmpl",
   311  			expectRunErrorIs: &template.Error{},
   312  			winget: config.Winget{
   313  				Name:             "foobar",
   314  				Publisher:        "Beckersoft",
   315  				Author:           "{{ .Nope }}",
   316  				License:          "MIT",
   317  				ShortDescription: "foo bar zaz",
   318  				Repository: config.RepoRef{
   319  					Owner: "foo",
   320  					Name:  "bar",
   321  				},
   322  			},
   323  		},
   324  		{
   325  			name:             "bad-homepage-tmpl",
   326  			expectRunErrorIs: &template.Error{},
   327  			winget: config.Winget{
   328  				Name:             "foobar",
   329  				Publisher:        "Beckersoft",
   330  				Homepage:         "{{ .Nope }}",
   331  				License:          "MIT",
   332  				ShortDescription: "foo bar zaz",
   333  				Repository: config.RepoRef{
   334  					Owner: "foo",
   335  					Name:  "bar",
   336  				},
   337  			},
   338  		},
   339  		{
   340  			name:             "bad-description-tmpl",
   341  			expectRunErrorIs: &template.Error{},
   342  			winget: config.Winget{
   343  				Name:             "foobar",
   344  				Publisher:        "Beckersoft",
   345  				Description:      "{{ .Nope }}",
   346  				License:          "MIT",
   347  				ShortDescription: "foo bar zaz",
   348  				Repository: config.RepoRef{
   349  					Owner: "foo",
   350  					Name:  "bar",
   351  				},
   352  			},
   353  		},
   354  		{
   355  			name:             "bad-short-description-tmpl",
   356  			expectRunErrorIs: &template.Error{},
   357  			winget: config.Winget{
   358  				Name:             "foobar",
   359  				Publisher:        "Beckersoft",
   360  				ShortDescription: "{{ .Nope }}",
   361  				License:          "MIT",
   362  				Repository: config.RepoRef{
   363  					Owner: "foo",
   364  					Name:  "bar",
   365  				},
   366  			},
   367  		},
   368  		{
   369  			name:             "bad-repo-tmpl",
   370  			expectRunErrorIs: &template.Error{},
   371  			winget: config.Winget{
   372  				Name:             "doesnotmatter",
   373  				Publisher:        "Beckersoft",
   374  				License:          "MIT",
   375  				ShortDescription: "foo bar zaz",
   376  				Repository: config.RepoRef{
   377  					Owner: "foo",
   378  					Name:  "{{ .Nope }}",
   379  				},
   380  			},
   381  		},
   382  		{
   383  			name:             "bad-skip-upload-tmpl",
   384  			expectRunErrorIs: &template.Error{},
   385  			winget: config.Winget{
   386  				Name:             "doesnotmatter",
   387  				Publisher:        "Beckersoft",
   388  				SkipUpload:       "{{ .Nope }}",
   389  				License:          "MIT",
   390  				ShortDescription: "foo bar zaz",
   391  				Repository: config.RepoRef{
   392  					Owner: "foo",
   393  					Name:  "bar",
   394  				},
   395  			},
   396  		},
   397  		{
   398  			name:             "bad-release-notes-url-tmpl",
   399  			expectRunErrorIs: &template.Error{},
   400  			winget: config.Winget{
   401  				Name:             "foo",
   402  				Publisher:        "Beckersoft",
   403  				ReleaseNotesURL:  `https://goo/bar/asdfsd/{{.nope}}`,
   404  				License:          "MIT",
   405  				ShortDescription: "foo bar zaz",
   406  				Repository: config.RepoRef{
   407  					Owner: "foo",
   408  					Name:  "bar",
   409  				},
   410  			},
   411  		},
   412  		{
   413  			name:             "bad-release-url-tmpl",
   414  			expectRunErrorIs: &template.Error{},
   415  			winget: config.Winget{
   416  				Name:             "foo",
   417  				Publisher:        "Beckersoft",
   418  				URLTemplate:      "{{.BadURL}}",
   419  				License:          "MIT",
   420  				ShortDescription: "foo bar zaz",
   421  				Repository: config.RepoRef{
   422  					Owner: "foo",
   423  					Name:  "bar",
   424  				},
   425  			},
   426  		},
   427  		{
   428  			name:             "bad-path-tmpl",
   429  			expectRunErrorIs: &template.Error{},
   430  			winget: config.Winget{
   431  				Name:             "foo",
   432  				Publisher:        "Beckersoft",
   433  				License:          "MIT",
   434  				Path:             "{{ .Nope }}",
   435  				ShortDescription: "foo bar zaz",
   436  				Repository: config.RepoRef{
   437  					Owner: "foo",
   438  					Name:  "bar",
   439  				},
   440  			},
   441  		},
   442  		{
   443  			name:                 "bad-commit-msg-tmpl",
   444  			expectPublishErrorIs: &template.Error{},
   445  			winget: config.Winget{
   446  				Name:                  "foo",
   447  				Publisher:             "Beckersoft",
   448  				License:               "MIT",
   449  				ShortDescription:      "foo bar zaz",
   450  				CommitMessageTemplate: "{{.Foo}}",
   451  				IDs:                   []string{"foo"},
   452  				Repository: config.RepoRef{
   453  					Owner: "foo",
   454  					Name:  "bar",
   455  				},
   456  			},
   457  		},
   458  		{
   459  			name:             "bad-publisher-support-url-tmpl",
   460  			expectRunErrorIs: &template.Error{},
   461  			winget: config.Winget{
   462  				Name:                "foo",
   463  				Publisher:           "Beckersoft",
   464  				PublisherSupportURL: "{{.Nope}}",
   465  				License:             "MIT",
   466  				ShortDescription:    "foo bar zaz",
   467  				Repository: config.RepoRef{
   468  					Owner: "foo",
   469  					Name:  "bar",
   470  				},
   471  			},
   472  		},
   473  		{
   474  			name:             "bad-copyright-tmpl",
   475  			expectRunErrorIs: &template.Error{},
   476  			winget: config.Winget{
   477  				Name:             "foo",
   478  				Publisher:        "Beckersoft",
   479  				License:          "MIT",
   480  				Copyright:        "{{ .Nope }}",
   481  				ShortDescription: "foo bar zaz",
   482  				Repository: config.RepoRef{
   483  					Owner: "foo",
   484  					Name:  "bar",
   485  				},
   486  			},
   487  		},
   488  		{
   489  			name:             "bad-copyright-url-tmpl",
   490  			expectRunErrorIs: &template.Error{},
   491  			winget: config.Winget{
   492  				Name:             "{{ .Nope }}",
   493  				Publisher:        "Beckersoft",
   494  				License:          "MIT",
   495  				CopyrightURL:     "{{ .Nope }}",
   496  				ShortDescription: "foo bar zaz",
   497  				Repository: config.RepoRef{
   498  					Owner: "foo",
   499  					Name:  "bar",
   500  				},
   501  			},
   502  		},
   503  		{
   504  			name:             "bad-license-tmpl",
   505  			expectRunErrorIs: &template.Error{},
   506  			winget: config.Winget{
   507  				Name:             "foo",
   508  				Publisher:        "Beckersoft",
   509  				License:          "{{ .Nope }}",
   510  				ShortDescription: "foo bar zaz",
   511  				Repository: config.RepoRef{
   512  					Owner: "foo",
   513  					Name:  "bar",
   514  				},
   515  			},
   516  		},
   517  		{
   518  			name:             "bad-license-url-tmpl",
   519  			expectRunErrorIs: &template.Error{},
   520  			winget: config.Winget{
   521  				Name:             "foo",
   522  				Publisher:        "Beckersoft",
   523  				License:          "MIT",
   524  				LicenseURL:       "{{ .Nope }}",
   525  				ShortDescription: "foo bar zaz",
   526  				Repository: config.RepoRef{
   527  					Owner: "foo",
   528  					Name:  "bar",
   529  				},
   530  			},
   531  		},
   532  		{
   533  			name:                 "skip-upload",
   534  			expectPublishErrorIs: errSkipUpload,
   535  			winget: config.Winget{
   536  				Name:             "doesnotmatter",
   537  				Publisher:        "Beckersoft",
   538  				SkipUpload:       "true",
   539  				License:          "MIT",
   540  				IDs:              []string{"foo"},
   541  				ShortDescription: "foo bar zaz",
   542  				Repository: config.RepoRef{
   543  					Owner: "foo",
   544  					Name:  "bar",
   545  				},
   546  			},
   547  		},
   548  		{
   549  			name:                 "skip-upload-auto",
   550  			expectPublishErrorIs: errSkipUploadAuto,
   551  			winget: config.Winget{
   552  				Name:             "doesnotmatter",
   553  				Publisher:        "Beckersoft",
   554  				License:          "MIT",
   555  				ShortDescription: "foo bar zaz",
   556  				IDs:              []string{"foo"},
   557  				SkipUpload:       "auto",
   558  				Repository: config.RepoRef{
   559  					Owner: "foo",
   560  					Name:  "bar",
   561  				},
   562  			},
   563  		},
   564  		{
   565  			name:       "with-deps",
   566  			expectPath: "manifests/f/Foo/deps/1.2.1/Foo.deps.",
   567  			winget: config.Winget{
   568  				Name:             "deps",
   569  				Publisher:        "Foo",
   570  				License:          "MIT",
   571  				ShortDescription: "foo bar zaz",
   572  				IDs:              []string{"foo"},
   573  				Repository: config.RepoRef{
   574  					Owner: "foo",
   575  					Name:  "bar",
   576  				},
   577  				Dependencies: []config.WingetDependency{
   578  					{
   579  						PackageIdentifier: "foo.bar",
   580  						MinimumVersion:    "1.2.3",
   581  					},
   582  					{
   583  						PackageIdentifier: "zaz.bar",
   584  					},
   585  				},
   586  			},
   587  		},
   588  		{
   589  			name:             "bad-dependency-template",
   590  			expectRunErrorIs: &template.Error{},
   591  			winget: config.Winget{
   592  				Name:             "foo",
   593  				Publisher:        "Beckersoft",
   594  				License:          "MIT",
   595  				LicenseURL:       "https://foo.bar",
   596  				ShortDescription: "foo bar zaz",
   597  				Repository: config.RepoRef{
   598  					Owner: "foo",
   599  					Name:  "bar",
   600  				},
   601  				Dependencies: []config.WingetDependency{
   602  					{PackageIdentifier: "{{.Nope}}"},
   603  				},
   604  			},
   605  		},
   606  	} {
   607  		t.Run(tt.name, func(t *testing.T) {
   608  			folder := t.TempDir()
   609  			ctx := testctx.NewWithCfg(
   610  				config.Project{
   611  					Dist:        folder,
   612  					ProjectName: "foo",
   613  					Winget:      []config.Winget{tt.winget},
   614  				},
   615  				testctx.WithVersion("1.2.1"),
   616  				testctx.WithCurrentTag("v1.2.1"),
   617  				testctx.WithSemver(1, 2, 1, "rc1"),
   618  				testctx.WithDate(time.Date(2023, 6, 12, 20, 32, 10, 12, time.Local)),
   619  			)
   620  			ctx.ReleaseNotes = "the changelog for this release..."
   621  			createFakeArtifact := func(id, goos, goarch, goamd64, goarm string, extra map[string]any) {
   622  				path := filepath.Join(folder, "dist/foo_"+goos+goarch+goamd64+goarm+".zip")
   623  				art := artifact.Artifact{
   624  					Name:    "foo_" + goos + "_" + goarch + goamd64 + goarm + ".zip",
   625  					Path:    path,
   626  					Goos:    goos,
   627  					Goarch:  goarch,
   628  					Goarm:   goarm,
   629  					Goamd64: goamd64,
   630  					Type:    artifact.UploadableArchive,
   631  					Extra: map[string]interface{}{
   632  						artifact.ExtraID:        id,
   633  						artifact.ExtraFormat:    "zip",
   634  						artifact.ExtraBinaries:  []string{"foo.exe"},
   635  						artifact.ExtraWrappedIn: "",
   636  					},
   637  				}
   638  				for k, v := range extra {
   639  					art.Extra[k] = v
   640  				}
   641  				ctx.Artifacts.Add(&art)
   642  
   643  				require.NoError(t, os.MkdirAll(filepath.Dir(path), 0o755))
   644  				f, err := os.Create(path)
   645  				require.NoError(t, err)
   646  				require.NoError(t, f.Close())
   647  			}
   648  
   649  			goos := "windows"
   650  			goarch := "amd64"
   651  			createFakeArtifact("partial", goos, goarch, "v1", "", nil)
   652  			createFakeArtifact("foo", goos, goarch, "v1", "", nil)
   653  			createFakeArtifact("wrapped-in-dir", goos, goarch, "v1", "", map[string]any{
   654  				artifact.ExtraWrappedIn: "foo",
   655  				artifact.ExtraBinaries:  []string{"bin/foo.exe"},
   656  			})
   657  
   658  			goarch = "386"
   659  			createFakeArtifact("foo", goos, goarch, "", "", nil)
   660  			createFakeArtifact("wrapped-in-dir", goos, goarch, "", "", map[string]any{
   661  				artifact.ExtraWrappedIn: "foo",
   662  				artifact.ExtraBinaries:  []string{"bin/foo.exe"},
   663  			})
   664  
   665  			goarch = "arm64"
   666  			createFakeArtifact("foo", goos, goarch, "", "", nil)
   667  			createFakeArtifact("wrapped-in-dir", goos, goarch, "", "", map[string]any{
   668  				artifact.ExtraWrappedIn: "foo",
   669  				artifact.ExtraBinaries:  []string{"bin/foo.exe"},
   670  			})
   671  
   672  			client := client.NewMock()
   673  			pipe := Pipe{}
   674  
   675  			// default
   676  			require.NoError(t, pipe.Default(ctx))
   677  
   678  			// run
   679  			if tt.expectRunErrorIs != nil {
   680  				err := pipe.runAll(ctx, client)
   681  				require.Error(t, err)
   682  				require.ErrorAs(t, err, &tt.expectPublishErrorIs)
   683  				return
   684  			}
   685  
   686  			require.NoError(t, pipe.runAll(ctx, client))
   687  			for _, winget := range ctx.Artifacts.Filter(artifact.Or(
   688  				artifact.ByType(artifact.WingetInstaller),
   689  				artifact.ByType(artifact.WingetVersion),
   690  				artifact.ByType(artifact.WingetDefaultLocale),
   691  			)).List() {
   692  				bts, err := os.ReadFile(winget.Path)
   693  				require.NoError(t, err)
   694  				golden.RequireEqualExtSubfolder(t, bts, extFor(winget.Type))
   695  			}
   696  
   697  			// publish
   698  			if tt.expectPublishErrorIs != nil {
   699  				err := pipe.publishAll(ctx, client)
   700  				require.Error(t, err)
   701  				require.ErrorAs(t, err, &tt.expectPublishErrorIs)
   702  				return
   703  			}
   704  			require.NoError(t, pipe.publishAll(ctx, client))
   705  			require.True(t, client.CreatedFile)
   706  
   707  			require.Len(t, client.Messages, 3)
   708  			expected := map[string]bool{
   709  				"locale":    false,
   710  				"version":   false,
   711  				"installer": false,
   712  			}
   713  			for _, msg := range client.Messages {
   714  				require.Regexp(t, "New version: \\w+\\.[\\w-]+ 1.2.1", msg)
   715  				for k, v := range expected {
   716  					if strings.Contains(msg, ": add "+k) {
   717  						require.False(t, v, "multiple commits for "+k)
   718  						expected[k] = true
   719  					}
   720  				}
   721  			}
   722  
   723  			require.NotEmpty(t, client.Path)
   724  			if tt.expectPath != "" {
   725  				require.Truef(t, strings.HasPrefix(client.Path, tt.expectPath), "expected %q to begin with %q", client.Path, tt.expectPath)
   726  			}
   727  
   728  			if tt.winget.Repository.PullRequest.Enabled {
   729  				require.True(t, client.OpenedPullRequest)
   730  			}
   731  		})
   732  	}
   733  }
   734  
   735  func TestErrNoArchivesFound(t *testing.T) {
   736  	require.EqualError(t, errNoArchivesFound{
   737  		goamd64: "v1",
   738  		ids:     []string{"foo", "bar"},
   739  	}, "no zip archives found matching goos=[windows] goarch=[amd64 386] goamd64=v1 ids=[foo bar]")
   740  }
   741  
   742  func TestDefault(t *testing.T) {
   743  	ctx := testctx.NewWithCfg(config.Project{
   744  		ProjectName: "foo",
   745  		Winget:      []config.Winget{{}},
   746  	})
   747  	require.NoError(t, Pipe{}.Default(ctx))
   748  	winget := ctx.Config.Winget[0]
   749  	require.Equal(t, "v1", winget.Goamd64)
   750  	require.NotEmpty(t, winget.CommitMessageTemplate)
   751  	require.Equal(t, "foo", winget.Name)
   752  }