github.com/goreleaser/goreleaser@v1.25.1/internal/pipe/archive/archive_test.go (about)

     1  package archive
     2  
     3  import (
     4  	"archive/tar"
     5  	"compress/gzip"
     6  	"fmt"
     7  	"io"
     8  	"io/fs"
     9  	"os"
    10  	"path/filepath"
    11  	"testing"
    12  
    13  	"github.com/goreleaser/goreleaser/internal/artifact"
    14  	"github.com/goreleaser/goreleaser/internal/testctx"
    15  	"github.com/goreleaser/goreleaser/internal/testlib"
    16  	"github.com/goreleaser/goreleaser/pkg/archive"
    17  	"github.com/goreleaser/goreleaser/pkg/config"
    18  	"github.com/stretchr/testify/require"
    19  )
    20  
    21  func TestDescription(t *testing.T) {
    22  	require.NotEmpty(t, Pipe{}.String())
    23  }
    24  
    25  func createFakeBinary(t *testing.T, dist, arch, bin string) {
    26  	t.Helper()
    27  	path := filepath.Join(dist, arch, bin)
    28  	require.NoError(t, os.MkdirAll(filepath.Dir(path), 0o755))
    29  	f, err := os.Create(path)
    30  	require.NoError(t, err)
    31  	require.NoError(t, f.Close())
    32  }
    33  
    34  func TestRunPipe(t *testing.T) {
    35  	folder := testlib.Mktmp(t)
    36  	for _, dets := range []struct {
    37  		Format string
    38  		Strip  bool
    39  	}{
    40  		{
    41  			Format: "tar.gz",
    42  			Strip:  true,
    43  		},
    44  		{
    45  			Format: "tar.gz",
    46  			Strip:  false,
    47  		},
    48  
    49  		{
    50  			Format: "zip",
    51  			Strip:  true,
    52  		},
    53  		{
    54  			Format: "zip",
    55  			Strip:  false,
    56  		},
    57  	} {
    58  		format := dets.Format
    59  		name := "archive." + format
    60  		if dets.Strip {
    61  			name = "strip_" + name
    62  		}
    63  		t.Run(name, func(t *testing.T) {
    64  			dist := filepath.Join(folder, name+"_dist")
    65  			require.NoError(t, os.Mkdir(dist, 0o755))
    66  			for _, arch := range []string{"darwinamd64v1", "darwinall", "linux386", "linuxarm7", "linuxmipssoftfloat", "linuxamd64v3"} {
    67  				createFakeBinary(t, dist, arch, "bin/mybin")
    68  			}
    69  			createFakeBinary(t, dist, "windowsamd64", "bin/mybin.exe")
    70  			for _, tt := range []string{"darwin", "linux", "windows"} {
    71  				f, err := os.Create(filepath.Join(folder, fmt.Sprintf("README.%s.md", tt)))
    72  				require.NoError(t, err)
    73  				require.NoError(t, f.Close())
    74  			}
    75  			require.NoError(t, os.MkdirAll(filepath.Join(folder, "foo", "bar", "foobar"), 0o755))
    76  			f, err := os.Create(filepath.Join(folder, "foo", "bar", "foobar", "blah.txt"))
    77  			require.NoError(t, err)
    78  			require.NoError(t, f.Close())
    79  			ctx := testctx.NewWithCfg(
    80  				config.Project{
    81  					Dist:        dist,
    82  					ProjectName: "foobar",
    83  					Archives: []config.Archive{
    84  						{
    85  							ID:     "myid",
    86  							Builds: []string{"default"},
    87  							BuildsInfo: config.FileInfo{
    88  								Owner: "root",
    89  								Group: "root",
    90  							},
    91  							NameTemplate:         defaultNameTemplate,
    92  							StripBinaryDirectory: dets.Strip,
    93  							Files: []config.File{
    94  								{Source: "README.{{.Os}}.*"},
    95  								{Source: "./foo/**/*"},
    96  							},
    97  							FormatOverrides: []config.FormatOverride{
    98  								{
    99  									Goos:   "windows",
   100  									Format: "zip",
   101  								},
   102  								{
   103  									Goos:   "freebsd",
   104  									Format: "none",
   105  								},
   106  							},
   107  						},
   108  					},
   109  				},
   110  			)
   111  			darwinUniversalBinary := &artifact.Artifact{
   112  				Goos:   "darwin",
   113  				Goarch: "all",
   114  				Name:   "bin/mybin",
   115  				Path:   filepath.Join(dist, "darwinall", "bin", "mybin"),
   116  				Type:   artifact.UniversalBinary,
   117  				Extra: map[string]interface{}{
   118  					artifact.ExtraBinary:   "bin/mybin",
   119  					artifact.ExtraID:       "default",
   120  					artifact.ExtraReplaces: true,
   121  				},
   122  			}
   123  			darwinBuild := &artifact.Artifact{
   124  				Goos:    "darwin",
   125  				Goarch:  "amd64",
   126  				Goamd64: "v1",
   127  				Name:    "bin/mybin",
   128  				Path:    filepath.Join(dist, "darwinamd64v1", "bin", "mybin"),
   129  				Type:    artifact.Binary,
   130  				Extra: map[string]interface{}{
   131  					artifact.ExtraBinary: "bin/mybin",
   132  					artifact.ExtraID:     "default",
   133  				},
   134  			}
   135  			linux386Build := &artifact.Artifact{
   136  				Goos:   "linux",
   137  				Goarch: "386",
   138  				Name:   "bin/mybin",
   139  				Path:   filepath.Join(dist, "linux386", "bin", "mybin"),
   140  				Type:   artifact.Binary,
   141  				Extra: map[string]interface{}{
   142  					artifact.ExtraBinary: "bin/mybin",
   143  					artifact.ExtraID:     "default",
   144  				},
   145  			}
   146  			linuxArmBuild := &artifact.Artifact{
   147  				Goos:   "linux",
   148  				Goarch: "arm",
   149  				Goarm:  "7",
   150  				Name:   "bin/mybin",
   151  				Path:   filepath.Join(dist, "linuxarm7", "bin", "mybin"),
   152  				Type:   artifact.Binary,
   153  				Extra: map[string]interface{}{
   154  					artifact.ExtraBinary: "bin/mybin",
   155  					artifact.ExtraID:     "default",
   156  				},
   157  			}
   158  			linuxMipsBuild := &artifact.Artifact{
   159  				Goos:   "linux",
   160  				Goarch: "mips",
   161  				Gomips: "softfloat",
   162  				Name:   "bin/mybin",
   163  				Path:   filepath.Join(dist, "linuxmipssoftfloat", "bin", "mybin"),
   164  				Type:   artifact.Binary,
   165  				Extra: map[string]interface{}{
   166  					artifact.ExtraBinary: "mybin",
   167  					artifact.ExtraID:     "default",
   168  				},
   169  			}
   170  			windowsBuild := &artifact.Artifact{
   171  				Goos:    "windows",
   172  				Goarch:  "amd64",
   173  				Goamd64: "v1",
   174  				Name:    "bin/mybin.exe",
   175  				Path:    filepath.Join(dist, "windowsamd64", "bin", "mybin.exe"),
   176  				Type:    artifact.Binary,
   177  				Extra: map[string]interface{}{
   178  					artifact.ExtraBinary: "mybin",
   179  					artifact.ExtraExt:    ".exe",
   180  					artifact.ExtraID:     "default",
   181  				},
   182  			}
   183  			linuxAmd64Build := &artifact.Artifact{
   184  				Goos:    "linux",
   185  				Goarch:  "amd64",
   186  				Goamd64: "v3",
   187  				Name:    "bin/mybin",
   188  				Path:    filepath.Join(dist, "linuxamd64v3", "bin", "mybin"),
   189  				Type:    artifact.Binary,
   190  				Extra: map[string]interface{}{
   191  					artifact.ExtraBinary: "mybin",
   192  					artifact.ExtraID:     "default",
   193  				},
   194  			}
   195  			freebsdAmd64Build := &artifact.Artifact{
   196  				Goos:    "freebsd",
   197  				Goarch:  "amd64",
   198  				Goamd64: "v3",
   199  				Name:    "bin/mybin",
   200  				Path:    "will be ignored",
   201  				Type:    artifact.Binary,
   202  				Extra: map[string]interface{}{
   203  					artifact.ExtraBinary: "mybin",
   204  					artifact.ExtraID:     "default",
   205  				},
   206  			}
   207  			ctx.Artifacts.Add(darwinBuild)
   208  			ctx.Artifacts.Add(darwinUniversalBinary)
   209  			ctx.Artifacts.Add(linux386Build)
   210  			ctx.Artifacts.Add(linuxArmBuild)
   211  			ctx.Artifacts.Add(linuxMipsBuild)
   212  			ctx.Artifacts.Add(windowsBuild)
   213  			ctx.Artifacts.Add(linuxAmd64Build)
   214  			ctx.Artifacts.Add(freebsdAmd64Build)
   215  			ctx.Version = "0.0.1"
   216  			ctx.Git.CurrentTag = "v0.0.1"
   217  			ctx.Config.Archives[0].Format = format
   218  			require.NoError(t, Pipe{}.Run(ctx))
   219  
   220  			require.Empty(t, ctx.Artifacts.Filter(
   221  				artifact.And(
   222  					artifact.ByGoos("freebsd"),
   223  					artifact.Or(
   224  						artifact.ByType(artifact.UploadableArchive),
   225  						artifact.ByType(artifact.UploadableBinary),
   226  					),
   227  				),
   228  			).List(), "shouldn't have archived freebsd in any way")
   229  
   230  			archives := ctx.Artifacts.Filter(artifact.ByType(artifact.UploadableArchive)).List()
   231  			for _, arch := range archives {
   232  				expectBin := "bin/mybin"
   233  				if arch.Goos == "windows" {
   234  					expectBin += ".exe"
   235  				}
   236  				require.Equal(t, "myid", arch.ID(), "all archives must have the archive ID set")
   237  				require.Equal(t, []string{expectBin}, artifact.ExtraOr(*arch, artifact.ExtraBinaries, []string{}))
   238  				require.Equal(t, "", artifact.ExtraOr(*arch, artifact.ExtraBinary, ""))
   239  			}
   240  			require.Len(t, archives, 7)
   241  			// TODO: should verify the artifact fields here too
   242  
   243  			expectBin := "bin/mybin"
   244  			if dets.Strip {
   245  				expectBin = "mybin"
   246  			}
   247  
   248  			if format == "tar.gz" {
   249  				// Check archive contents
   250  				for name, os := range map[string]string{
   251  					"foobar_0.0.1_darwin_amd64.tar.gz":         "darwin",
   252  					"foobar_0.0.1_darwin_all.tar.gz":           "darwin",
   253  					"foobar_0.0.1_linux_386.tar.gz":            "linux",
   254  					"foobar_0.0.1_linux_armv7.tar.gz":          "linux",
   255  					"foobar_0.0.1_linux_mips_softfloat.tar.gz": "linux",
   256  					"foobar_0.0.1_linux_amd64v3.tar.gz":        "linux",
   257  				} {
   258  					require.Equal(
   259  						t,
   260  						[]string{
   261  							fmt.Sprintf("README.%s.md", os),
   262  							"foo/bar/foobar/blah.txt",
   263  							expectBin,
   264  						},
   265  						testlib.LsArchive(t, filepath.Join(dist, name), "tar.gz"),
   266  					)
   267  
   268  					header := tarInfo(t, filepath.Join(dist, name), expectBin)
   269  					require.Equal(t, "root", header.Uname)
   270  					require.Equal(t, "root", header.Gname)
   271  
   272  				}
   273  			}
   274  			if format == "zip" {
   275  				require.Equal(
   276  					t,
   277  					[]string{
   278  						"README.windows.md",
   279  						"foo/bar/foobar/blah.txt",
   280  						expectBin + ".exe",
   281  					},
   282  					testlib.LsArchive(t, filepath.Join(dist, "foobar_0.0.1_windows_amd64.zip"), "zip"),
   283  				)
   284  			}
   285  		})
   286  	}
   287  }
   288  
   289  func TestRunPipeDifferentBinaryCount(t *testing.T) {
   290  	folder := testlib.Mktmp(t)
   291  	dist := filepath.Join(folder, "dist")
   292  	require.NoError(t, os.Mkdir(dist, 0o755))
   293  	for _, arch := range []string{"darwinamd64", "linuxamd64"} {
   294  		createFakeBinary(t, dist, arch, "bin/mybin")
   295  	}
   296  	createFakeBinary(t, dist, "darwinamd64", "bin/foobar")
   297  	ctx := testctx.NewWithCfg(config.Project{
   298  		Dist:        dist,
   299  		ProjectName: "foobar",
   300  		Archives: []config.Archive{
   301  			{
   302  				ID:           "myid",
   303  				Format:       "tar.gz",
   304  				Builds:       []string{"default", "foobar"},
   305  				NameTemplate: defaultNameTemplate,
   306  			},
   307  		},
   308  	})
   309  	darwinBuild := &artifact.Artifact{
   310  		Goos:   "darwin",
   311  		Goarch: "amd64",
   312  		Name:   "bin/mybin",
   313  		Path:   filepath.Join(dist, "darwinamd64", "bin", "mybin"),
   314  		Type:   artifact.Binary,
   315  		Extra: map[string]interface{}{
   316  			artifact.ExtraBinary: "bin/mybin",
   317  			artifact.ExtraID:     "default",
   318  		},
   319  	}
   320  	darwinBuild2 := &artifact.Artifact{
   321  		Goos:   "darwin",
   322  		Goarch: "amd64",
   323  		Name:   "bin/foobar",
   324  		Path:   filepath.Join(dist, "darwinamd64", "bin", "foobar"),
   325  		Type:   artifact.Binary,
   326  		Extra: map[string]interface{}{
   327  			artifact.ExtraBinary: "bin/foobar",
   328  			artifact.ExtraID:     "foobar",
   329  		},
   330  	}
   331  	linuxArmBuild := &artifact.Artifact{
   332  		Goos:   "linux",
   333  		Goarch: "amd64",
   334  		Name:   "bin/mybin",
   335  		Path:   filepath.Join(dist, "linuxamd64", "bin", "mybin"),
   336  		Type:   artifact.Binary,
   337  		Extra: map[string]interface{}{
   338  			artifact.ExtraBinary: "bin/mybin",
   339  			artifact.ExtraID:     "default",
   340  		},
   341  	}
   342  
   343  	ctx.Artifacts.Add(darwinBuild)
   344  	ctx.Artifacts.Add(darwinBuild2)
   345  	ctx.Artifacts.Add(linuxArmBuild)
   346  	ctx.Version = "0.0.1"
   347  	ctx.Git.CurrentTag = "v0.0.1"
   348  
   349  	t.Run("check enabled", func(t *testing.T) {
   350  		ctx.Config.Archives[0].AllowDifferentBinaryCount = false
   351  		require.EqualError(t, Pipe{}.Run(ctx), "invalid archive: 0: "+ErrArchiveDifferentBinaryCount.Error())
   352  	})
   353  
   354  	t.Run("check disabled", func(t *testing.T) {
   355  		ctx.Config.Archives[0].AllowDifferentBinaryCount = true
   356  		require.NoError(t, Pipe{}.Run(ctx))
   357  	})
   358  }
   359  
   360  func TestRunPipeNoBinaries(t *testing.T) {
   361  	folder := testlib.Mktmp(t)
   362  	dist := filepath.Join(folder, "dist")
   363  	require.NoError(t, os.Mkdir(dist, 0o755))
   364  	ctx := testctx.NewWithCfg(config.Project{
   365  		Dist:        dist,
   366  		ProjectName: "foobar",
   367  		Archives: []config.Archive{{
   368  			Builds: []string{"not-default"},
   369  		}},
   370  	}, testctx.WithVersion("0.0.1"), testctx.WithCurrentTag("v1.0.0"))
   371  	ctx.Artifacts.Add(&artifact.Artifact{
   372  		Goos:   "linux",
   373  		Goarch: "amd64",
   374  		Name:   "bin/mybin",
   375  		Path:   filepath.Join(dist, "linuxamd64", "bin", "mybin"),
   376  		Type:   artifact.Binary,
   377  		Extra: map[string]interface{}{
   378  			artifact.ExtraBinary: "bin/mybin",
   379  			artifact.ExtraID:     "default",
   380  		},
   381  	})
   382  	require.NoError(t, Pipe{}.Run(ctx))
   383  }
   384  
   385  func tarInfo(t *testing.T, path, name string) *tar.Header {
   386  	t.Helper()
   387  	f, err := os.Open(path)
   388  	require.NoError(t, err)
   389  	defer f.Close()
   390  	gr, err := gzip.NewReader(f)
   391  	require.NoError(t, err)
   392  	defer gr.Close()
   393  	r := tar.NewReader(gr)
   394  	for {
   395  		next, err := r.Next()
   396  		if err == io.EOF {
   397  			break
   398  		}
   399  		if next.Name == name {
   400  			return next
   401  		}
   402  	}
   403  	return nil
   404  }
   405  
   406  func TestRunPipeBinary(t *testing.T) {
   407  	folder := testlib.Mktmp(t)
   408  	dist := filepath.Join(folder, "dist")
   409  	require.NoError(t, os.Mkdir(dist, 0o755))
   410  	require.NoError(t, os.Mkdir(filepath.Join(dist, "darwinamd64"), 0o755))
   411  	require.NoError(t, os.Mkdir(filepath.Join(dist, "windowsamd64"), 0o755))
   412  	f, err := os.Create(filepath.Join(dist, "darwinamd64", "mybin"))
   413  	require.NoError(t, err)
   414  	require.NoError(t, f.Close())
   415  	f, err = os.Create(filepath.Join(dist, "windowsamd64", "mybin.exe"))
   416  	require.NoError(t, err)
   417  	require.NoError(t, f.Close())
   418  	f, err = os.Create(filepath.Join(dist, "windowsamd64", "myotherbin"))
   419  	require.NoError(t, err)
   420  	require.NoError(t, f.Close())
   421  	f, err = os.Create(filepath.Join(folder, "README.md"))
   422  	require.NoError(t, err)
   423  	require.NoError(t, f.Close())
   424  	ctx := testctx.NewWithCfg(
   425  		config.Project{
   426  			Dist: dist,
   427  			Archives: []config.Archive{
   428  				{
   429  					Format:       "binary",
   430  					NameTemplate: defaultBinaryNameTemplate,
   431  					Builds:       []string{"default", "default2"},
   432  				},
   433  			},
   434  		},
   435  		testctx.WithVersion("0.0.1"),
   436  		testctx.WithCurrentTag("v0.0.1"),
   437  	)
   438  	ctx.Artifacts.Add(&artifact.Artifact{
   439  		Goos:   "darwin",
   440  		Goarch: "amd64",
   441  		Name:   "mybin",
   442  		Path:   filepath.Join(dist, "darwinamd64", "mybin"),
   443  		Type:   artifact.Binary,
   444  		Extra: map[string]interface{}{
   445  			artifact.ExtraBinary: "mybin",
   446  			artifact.ExtraID:     "default",
   447  		},
   448  	})
   449  	ctx.Artifacts.Add(&artifact.Artifact{
   450  		Goos:   "darwin",
   451  		Goarch: "all",
   452  		Name:   "myunibin",
   453  		Path:   filepath.Join(dist, "darwinamd64", "mybin"),
   454  		Type:   artifact.UniversalBinary,
   455  		Extra: map[string]interface{}{
   456  			artifact.ExtraBinary:   "myunibin",
   457  			artifact.ExtraID:       "default",
   458  			artifact.ExtraReplaces: true,
   459  		},
   460  	})
   461  	ctx.Artifacts.Add(&artifact.Artifact{
   462  		Goos:   "windows",
   463  		Goarch: "amd64",
   464  		Name:   "mybin.exe",
   465  		Path:   filepath.Join(dist, "windowsamd64", "mybin.exe"),
   466  		Type:   artifact.Binary,
   467  		Extra: map[string]interface{}{
   468  			artifact.ExtraBinary: "mybin",
   469  			artifact.ExtraExt:    ".exe",
   470  			artifact.ExtraID:     "default",
   471  		},
   472  	})
   473  	ctx.Artifacts.Add(&artifact.Artifact{
   474  		Goos:   "windows",
   475  		Goarch: "amd64",
   476  		Name:   "myotherbin.exe",
   477  		Path:   filepath.Join(dist, "windowsamd64", "myotherbin.exe"),
   478  		Type:   artifact.Binary,
   479  		Extra: map[string]interface{}{
   480  			artifact.ExtraBinary: "myotherbin",
   481  			artifact.ExtraExt:    ".exe",
   482  			artifact.ExtraID:     "default2",
   483  		},
   484  	})
   485  
   486  	require.NoError(t, Pipe{}.Run(ctx))
   487  	binaries := ctx.Artifacts.Filter(artifact.ByType(artifact.UploadableBinary))
   488  	require.Len(t, binaries.List(), 4)
   489  	darwinThin := binaries.Filter(artifact.And(
   490  		artifact.ByGoos("darwin"),
   491  		artifact.ByGoarch("amd64"),
   492  	)).List()[0]
   493  	darwinUniversal := binaries.Filter(artifact.And(
   494  		artifact.ByGoos("darwin"),
   495  		artifact.ByGoarch("all"),
   496  	)).List()[0]
   497  	require.True(t, artifact.ExtraOr(*darwinUniversal, artifact.ExtraReplaces, false))
   498  	windows := binaries.Filter(artifact.ByGoos("windows")).List()[0]
   499  	windows2 := binaries.Filter(artifact.ByGoos("windows")).List()[1]
   500  	require.Equal(t, "mybin_0.0.1_darwin_amd64", darwinThin.Name)
   501  	require.Equal(t, "mybin", artifact.ExtraOr(*darwinThin, artifact.ExtraBinary, ""))
   502  	require.Equal(t, "myunibin_0.0.1_darwin_all", darwinUniversal.Name)
   503  	require.Equal(t, "myunibin", artifact.ExtraOr(*darwinUniversal, artifact.ExtraBinary, ""))
   504  	require.Equal(t, "mybin_0.0.1_windows_amd64.exe", windows.Name)
   505  	require.Equal(t, "mybin.exe", artifact.ExtraOr(*windows, artifact.ExtraBinary, ""))
   506  	require.Equal(t, "myotherbin_0.0.1_windows_amd64.exe", windows2.Name)
   507  	require.Equal(t, "myotherbin.exe", artifact.ExtraOr(*windows2, artifact.ExtraBinary, ""))
   508  }
   509  
   510  func TestRunPipeDistRemoved(t *testing.T) {
   511  	ctx := testctx.NewWithCfg(
   512  		config.Project{
   513  			Dist: "/tmp/path/to/nope",
   514  			Archives: []config.Archive{
   515  				{
   516  					NameTemplate: "nope",
   517  					Format:       "zip",
   518  					Builds:       []string{"default"},
   519  				},
   520  			},
   521  		},
   522  		testctx.WithCurrentTag("v0.0.1"),
   523  	)
   524  	ctx.Artifacts.Add(&artifact.Artifact{
   525  		Goos:   "windows",
   526  		Goarch: "amd64",
   527  		Name:   "mybin.exe",
   528  		Path:   filepath.Join("/tmp/path/to/nope", "windowsamd64", "mybin.exe"),
   529  		Type:   artifact.Binary,
   530  		Extra: map[string]interface{}{
   531  			artifact.ExtraBinary: "mybin",
   532  			artifact.ExtraExt:    ".exe",
   533  			artifact.ExtraID:     "default",
   534  		},
   535  	})
   536  	// not checking on error msg because it may change depending on OS/version
   537  	require.Error(t, Pipe{}.Run(ctx))
   538  }
   539  
   540  func TestRunPipeInvalidGlob(t *testing.T) {
   541  	folder := testlib.Mktmp(t)
   542  	dist := filepath.Join(folder, "dist")
   543  	require.NoError(t, os.Mkdir(dist, 0o755))
   544  	require.NoError(t, os.Mkdir(filepath.Join(dist, "darwinamd64"), 0o755))
   545  	f, err := os.Create(filepath.Join(dist, "darwinamd64", "mybin"))
   546  	require.NoError(t, err)
   547  	require.NoError(t, f.Close())
   548  	ctx := testctx.NewWithCfg(
   549  		config.Project{
   550  			Dist: dist,
   551  			Archives: []config.Archive{
   552  				{
   553  					Builds:       []string{"default"},
   554  					NameTemplate: "foo",
   555  					Format:       "zip",
   556  					Files: []config.File{
   557  						{Source: "[x-]"},
   558  					},
   559  				},
   560  			},
   561  		},
   562  		testctx.WithCurrentTag("v0.0.1"),
   563  	)
   564  	ctx.Git.CurrentTag = "v0.0.1"
   565  	ctx.Artifacts.Add(&artifact.Artifact{
   566  		Goos:   "darwin",
   567  		Goarch: "amd64",
   568  		Name:   "mybin",
   569  		Path:   filepath.Join("dist", "darwinamd64", "mybin"),
   570  		Type:   artifact.Binary,
   571  		Extra: map[string]interface{}{
   572  			artifact.ExtraBinary: "mybin",
   573  			artifact.ExtraID:     "default",
   574  		},
   575  	})
   576  	require.EqualError(t, Pipe{}.Run(ctx), `failed to find files to archive: globbing failed for pattern [x-]: compile glob pattern: unexpected end of input`)
   577  }
   578  
   579  func TestRunPipeNameTemplateWithSpace(t *testing.T) {
   580  	folder := testlib.Mktmp(t)
   581  	dist := filepath.Join(folder, "dist")
   582  	require.NoError(t, os.Mkdir(dist, 0o755))
   583  	require.NoError(t, os.Mkdir(filepath.Join(dist, "darwinamd64"), 0o755))
   584  	f, err := os.Create(filepath.Join(dist, "darwinamd64", "mybin"))
   585  	require.NoError(t, err)
   586  	require.NoError(t, f.Close())
   587  	ctx := testctx.NewWithCfg(
   588  		config.Project{
   589  			Dist: dist,
   590  			Archives: []config.Archive{
   591  				{
   592  					Builds:       []string{"default"},
   593  					NameTemplate: " foo_{{.Os}}_{{.Arch}} ",
   594  					Format:       "zip",
   595  				},
   596  				{
   597  					Builds:       []string{"default"},
   598  					NameTemplate: " foo_{{.Os}}_{{.Arch}} ",
   599  					Format:       "binary",
   600  				},
   601  			},
   602  		},
   603  		testctx.WithCurrentTag("v0.0.1"),
   604  	)
   605  	ctx.Artifacts.Add(&artifact.Artifact{
   606  		Goos:   "darwin",
   607  		Goarch: "amd64",
   608  		Name:   "mybin",
   609  		Path:   filepath.Join("dist", "darwinamd64", "mybin"),
   610  		Type:   artifact.Binary,
   611  		Extra: map[string]interface{}{
   612  			artifact.ExtraBinary: "mybin",
   613  			artifact.ExtraID:     "default",
   614  		},
   615  	})
   616  	require.NoError(t, Pipe{}.Run(ctx))
   617  	list := ctx.Artifacts.Filter(artifact.ByType(artifact.UploadableBinary)).List()
   618  	require.Len(t, list, 1)
   619  	require.Equal(t, "foo_darwin_amd64", list[0].Name)
   620  	list = ctx.Artifacts.Filter(artifact.ByType(artifact.UploadableArchive)).List()
   621  	require.Len(t, list, 1)
   622  	require.Equal(t, "foo_darwin_amd64.zip", list[0].Name)
   623  }
   624  
   625  func TestRunPipeInvalidNameTemplate(t *testing.T) {
   626  	folder := testlib.Mktmp(t)
   627  	dist := filepath.Join(folder, "dist")
   628  	require.NoError(t, os.Mkdir(dist, 0o755))
   629  	require.NoError(t, os.Mkdir(filepath.Join(dist, "darwinamd64"), 0o755))
   630  	f, err := os.Create(filepath.Join(dist, "darwinamd64", "mybin"))
   631  	require.NoError(t, err)
   632  	require.NoError(t, f.Close())
   633  	ctx := testctx.NewWithCfg(
   634  		config.Project{
   635  			Dist: dist,
   636  			Archives: []config.Archive{
   637  				{
   638  					Builds:       []string{"default"},
   639  					NameTemplate: "foo{{ .fff }",
   640  					Format:       "zip",
   641  				},
   642  			},
   643  		},
   644  		testctx.WithCurrentTag("v0.0.1"),
   645  	)
   646  	ctx.Artifacts.Add(&artifact.Artifact{
   647  		Goos:   "darwin",
   648  		Goarch: "amd64",
   649  		Name:   "mybin",
   650  		Path:   filepath.Join("dist", "darwinamd64", "mybin"),
   651  		Type:   artifact.Binary,
   652  		Extra: map[string]interface{}{
   653  			artifact.ExtraBinary: "mybin",
   654  			artifact.ExtraID:     "default",
   655  		},
   656  	})
   657  	testlib.RequireTemplateError(t, Pipe{}.Run(ctx))
   658  }
   659  
   660  func TestRunPipeInvalidFilesNameTemplate(t *testing.T) {
   661  	folder := testlib.Mktmp(t)
   662  	dist := filepath.Join(folder, "dist")
   663  	require.NoError(t, os.Mkdir(dist, 0o755))
   664  	require.NoError(t, os.Mkdir(filepath.Join(dist, "darwinamd64"), 0o755))
   665  	f, err := os.Create(filepath.Join(dist, "darwinamd64", "mybin"))
   666  	require.NoError(t, err)
   667  	require.NoError(t, f.Close())
   668  	ctx := testctx.NewWithCfg(
   669  		config.Project{
   670  			Dist: dist,
   671  			Archives: []config.Archive{
   672  				{
   673  					Builds:       []string{"default"},
   674  					NameTemplate: "foo",
   675  					Format:       "zip",
   676  					Files: []config.File{
   677  						{Source: "{{.asdsd}"},
   678  					},
   679  				},
   680  			},
   681  		},
   682  		testctx.WithCurrentTag("v0.0.1"),
   683  	)
   684  	ctx.Artifacts.Add(&artifact.Artifact{
   685  		Goos:   "darwin",
   686  		Goarch: "amd64",
   687  		Name:   "mybin",
   688  		Path:   filepath.Join("dist", "darwinamd64", "mybin"),
   689  		Type:   artifact.Binary,
   690  		Extra: map[string]interface{}{
   691  			artifact.ExtraBinary: "mybin",
   692  			artifact.ExtraID:     "default",
   693  		},
   694  	})
   695  	testlib.RequireTemplateError(t, Pipe{}.Run(ctx))
   696  }
   697  
   698  func TestRunPipeInvalidWrapInDirectoryTemplate(t *testing.T) {
   699  	folder := testlib.Mktmp(t)
   700  	dist := filepath.Join(folder, "dist")
   701  	require.NoError(t, os.Mkdir(dist, 0o755))
   702  	require.NoError(t, os.Mkdir(filepath.Join(dist, "darwinamd64"), 0o755))
   703  	f, err := os.Create(filepath.Join(dist, "darwinamd64", "mybin"))
   704  	require.NoError(t, err)
   705  	require.NoError(t, f.Close())
   706  	ctx := testctx.NewWithCfg(
   707  		config.Project{
   708  			Dist: dist,
   709  			Archives: []config.Archive{
   710  				{
   711  					Builds:          []string{"default"},
   712  					NameTemplate:    "foo",
   713  					WrapInDirectory: "foo{{ .fff }",
   714  					Format:          "zip",
   715  				},
   716  			},
   717  		},
   718  		testctx.WithCurrentTag("v0.0.1"),
   719  	)
   720  	ctx.Artifacts.Add(&artifact.Artifact{
   721  		Goos:   "darwin",
   722  		Goarch: "amd64",
   723  		Name:   "mybin",
   724  		Path:   filepath.Join("dist", "darwinamd64", "mybin"),
   725  		Type:   artifact.Binary,
   726  		Extra: map[string]interface{}{
   727  			artifact.ExtraBinary: "mybin",
   728  			artifact.ExtraID:     "default",
   729  		},
   730  	})
   731  	testlib.RequireTemplateError(t, Pipe{}.Run(ctx))
   732  }
   733  
   734  func TestRunPipeWrap(t *testing.T) {
   735  	folder := testlib.Mktmp(t)
   736  	dist := filepath.Join(folder, "dist")
   737  	require.NoError(t, os.Mkdir(dist, 0o755))
   738  	require.NoError(t, os.Mkdir(filepath.Join(dist, "darwinamd64"), 0o755))
   739  	f, err := os.Create(filepath.Join(dist, "darwinamd64", "mybin"))
   740  	require.NoError(t, err)
   741  	require.NoError(t, f.Close())
   742  	f, err = os.Create(filepath.Join(folder, "README.md"))
   743  	require.NoError(t, err)
   744  	require.NoError(t, f.Close())
   745  	ctx := testctx.NewWithCfg(
   746  		config.Project{
   747  			Dist: dist,
   748  			Archives: []config.Archive{
   749  				{
   750  					Builds:          []string{"default"},
   751  					NameTemplate:    "foo",
   752  					WrapInDirectory: "foo_{{ .Os }}",
   753  					Format:          "tar.gz",
   754  					Files: []config.File{
   755  						{Source: "README.*"},
   756  					},
   757  				},
   758  			},
   759  		},
   760  		testctx.WithCurrentTag("v0.0.1"),
   761  	)
   762  	ctx.Artifacts.Add(&artifact.Artifact{
   763  		Goos:   "darwin",
   764  		Goarch: "amd64",
   765  		Name:   "mybin",
   766  		Path:   filepath.Join("dist", "darwinamd64", "mybin"),
   767  		Type:   artifact.Binary,
   768  		Extra: map[string]interface{}{
   769  			artifact.ExtraBinary: "mybin",
   770  			artifact.ExtraID:     "default",
   771  		},
   772  	})
   773  	require.NoError(t, Pipe{}.Run(ctx))
   774  
   775  	archives := ctx.Artifacts.Filter(artifact.ByType(artifact.UploadableArchive)).List()
   776  	require.Len(t, archives, 1)
   777  	require.Equal(t, "foo_darwin", artifact.ExtraOr(*archives[0], artifact.ExtraWrappedIn, ""))
   778  
   779  	require.ElementsMatch(
   780  		t,
   781  		[]string{"foo_darwin/README.md", "foo_darwin/mybin"},
   782  		testlib.LsArchive(t, filepath.Join(dist, "foo.tar.gz"), "tar.gz"),
   783  	)
   784  }
   785  
   786  func TestDefault(t *testing.T) {
   787  	ctx := testctx.NewWithCfg(config.Project{
   788  		Archives: []config.Archive{},
   789  	})
   790  	require.NoError(t, Pipe{}.Default(ctx))
   791  	require.NotEmpty(t, ctx.Config.Archives[0].NameTemplate)
   792  	require.Equal(t, "tar.gz", ctx.Config.Archives[0].Format)
   793  	require.NotEmpty(t, ctx.Config.Archives[0].Files)
   794  }
   795  
   796  func TestDefaultSet(t *testing.T) {
   797  	ctx := testctx.NewWithCfg(config.Project{
   798  		Archives: []config.Archive{
   799  			{
   800  				Builds:       []string{"default"},
   801  				NameTemplate: "foo",
   802  				Format:       "zip",
   803  				Files: []config.File{
   804  					{Source: "foo"},
   805  				},
   806  			},
   807  		},
   808  	})
   809  	require.NoError(t, Pipe{}.Default(ctx))
   810  	require.Equal(t, "foo", ctx.Config.Archives[0].NameTemplate)
   811  	require.Equal(t, "zip", ctx.Config.Archives[0].Format)
   812  	require.Equal(t, config.File{Source: "foo"}, ctx.Config.Archives[0].Files[0])
   813  }
   814  
   815  func TestDefaultNoFiles(t *testing.T) {
   816  	ctx := testctx.NewWithCfg(config.Project{
   817  		Archives: []config.Archive{
   818  			{
   819  				Format: "tar.gz",
   820  			},
   821  		},
   822  	})
   823  	require.NoError(t, Pipe{}.Default(ctx))
   824  	require.Equal(t, defaultNameTemplate, ctx.Config.Archives[0].NameTemplate)
   825  }
   826  
   827  func TestDefaultFormatBinary(t *testing.T) {
   828  	ctx := testctx.NewWithCfg(config.Project{
   829  		Archives: []config.Archive{
   830  			{
   831  				Format: "binary",
   832  			},
   833  		},
   834  	})
   835  	require.NoError(t, Pipe{}.Default(ctx))
   836  	require.Equal(t, defaultBinaryNameTemplate, ctx.Config.Archives[0].NameTemplate)
   837  }
   838  
   839  func TestFormatFor(t *testing.T) {
   840  	ctx := testctx.NewWithCfg(config.Project{
   841  		Archives: []config.Archive{
   842  			{
   843  				Builds: []string{"default"},
   844  				Format: "tar.gz",
   845  				FormatOverrides: []config.FormatOverride{
   846  					{
   847  						Goos:   "windows",
   848  						Format: "zip",
   849  					},
   850  					{
   851  						Goos:   "darwin",
   852  						Format: "none",
   853  					},
   854  				},
   855  			},
   856  		},
   857  	})
   858  	require.Equal(t, "zip", packageFormat(ctx.Config.Archives[0], "windows"))
   859  	require.Equal(t, "tar.gz", packageFormat(ctx.Config.Archives[0], "linux"))
   860  	require.Equal(t, "none", packageFormat(ctx.Config.Archives[0], "darwin"))
   861  }
   862  
   863  func TestBinaryOverride(t *testing.T) {
   864  	folder := testlib.Mktmp(t)
   865  	dist := filepath.Join(folder, "dist")
   866  	require.NoError(t, os.Mkdir(dist, 0o755))
   867  	require.NoError(t, os.Mkdir(filepath.Join(dist, "darwinamd64"), 0o755))
   868  	require.NoError(t, os.Mkdir(filepath.Join(dist, "windowsamd64"), 0o755))
   869  	f, err := os.Create(filepath.Join(dist, "darwinamd64", "mybin"))
   870  	require.NoError(t, err)
   871  	require.NoError(t, f.Close())
   872  	f, err = os.Create(filepath.Join(dist, "windowsamd64", "mybin.exe"))
   873  	require.NoError(t, err)
   874  	require.NoError(t, f.Close())
   875  	f, err = os.Create(filepath.Join(folder, "README.md"))
   876  	require.NoError(t, err)
   877  	require.NoError(t, f.Close())
   878  	for _, format := range []string{"tar.gz", "zip"} {
   879  		t.Run("Archive format "+format, func(t *testing.T) {
   880  			ctx := testctx.NewWithCfg(
   881  				config.Project{
   882  					Dist:        dist,
   883  					ProjectName: "foobar",
   884  					Archives: []config.Archive{
   885  						{
   886  							Builds:       []string{"default"},
   887  							NameTemplate: defaultNameTemplate,
   888  							Files: []config.File{
   889  								{Source: "README.*"},
   890  							},
   891  							FormatOverrides: []config.FormatOverride{
   892  								{
   893  									Goos:   "windows",
   894  									Format: "binary",
   895  								},
   896  							},
   897  						},
   898  					},
   899  				},
   900  				testctx.WithCurrentTag("v0.0.1"),
   901  			)
   902  			ctx.Artifacts.Add(&artifact.Artifact{
   903  				Goos:   "darwin",
   904  				Goarch: "amd64",
   905  				Name:   "mybin",
   906  				Path:   filepath.Join(dist, "darwinamd64", "mybin"),
   907  				Type:   artifact.Binary,
   908  				Extra: map[string]interface{}{
   909  					artifact.ExtraBinary: "mybin",
   910  					artifact.ExtraID:     "default",
   911  				},
   912  			})
   913  			ctx.Artifacts.Add(&artifact.Artifact{
   914  				Goos:   "windows",
   915  				Goarch: "amd64",
   916  				Name:   "mybin.exe",
   917  				Path:   filepath.Join(dist, "windowsamd64", "mybin.exe"),
   918  				Type:   artifact.Binary,
   919  				Extra: map[string]interface{}{
   920  					artifact.ExtraBinary: "mybin",
   921  					artifact.ExtraExt:    ".exe",
   922  					artifact.ExtraID:     "default",
   923  				},
   924  			})
   925  			ctx.Version = "0.0.1"
   926  			ctx.Config.Archives[0].Format = format
   927  
   928  			require.NoError(t, Pipe{}.Run(ctx))
   929  			archives := ctx.Artifacts.Filter(artifact.ByType(artifact.UploadableArchive))
   930  			darwin := archives.Filter(artifact.ByGoos("darwin")).List()[0]
   931  			require.Equal(t, "foobar_0.0.1_darwin_amd64."+format, darwin.Name)
   932  			require.Equal(t, format, darwin.Format())
   933  			require.Empty(t, artifact.ExtraOr(*darwin, artifact.ExtraWrappedIn, ""))
   934  
   935  			archives = ctx.Artifacts.Filter(artifact.ByType(artifact.UploadableBinary))
   936  			windows := archives.Filter(artifact.ByGoos("windows")).List()[0]
   937  			require.Equal(t, "foobar_0.0.1_windows_amd64.exe", windows.Name)
   938  			require.Empty(t, artifact.ExtraOr(*windows, artifact.ExtraWrappedIn, ""))
   939  			require.Equal(t, "mybin.exe", artifact.ExtraOr(*windows, artifact.ExtraBinary, ""))
   940  		})
   941  	}
   942  }
   943  
   944  func TestRunPipeSameArchiveFilename(t *testing.T) {
   945  	folder := testlib.Mktmp(t)
   946  	dist := filepath.Join(folder, "dist")
   947  	require.NoError(t, os.Mkdir(dist, 0o755))
   948  	require.NoError(t, os.Mkdir(filepath.Join(dist, "darwinamd64"), 0o755))
   949  	require.NoError(t, os.Mkdir(filepath.Join(dist, "windowsamd64"), 0o755))
   950  	f, err := os.Create(filepath.Join(dist, "darwinamd64", "mybin"))
   951  	require.NoError(t, err)
   952  	require.NoError(t, f.Close())
   953  	f, err = os.Create(filepath.Join(dist, "windowsamd64", "mybin.exe"))
   954  	require.NoError(t, err)
   955  	require.NoError(t, f.Close())
   956  	ctx := testctx.NewWithCfg(
   957  		config.Project{
   958  			Dist:        dist,
   959  			ProjectName: "foobar",
   960  			Archives: []config.Archive{
   961  				{
   962  					Builds:       []string{"default"},
   963  					NameTemplate: "same-filename",
   964  					Files: []config.File{
   965  						{Source: "README.*"},
   966  						{Source: "./foo/**/*"},
   967  					},
   968  					Format: "tar.gz",
   969  				},
   970  			},
   971  		},
   972  	)
   973  	ctx.Artifacts.Add(&artifact.Artifact{
   974  		Goos:   "darwin",
   975  		Goarch: "amd64",
   976  		Name:   "mybin",
   977  		Path:   filepath.Join(dist, "darwinamd64", "mybin"),
   978  		Type:   artifact.Binary,
   979  		Extra: map[string]interface{}{
   980  			artifact.ExtraBinary: "mybin",
   981  			artifact.ExtraID:     "default",
   982  		},
   983  	})
   984  	ctx.Artifacts.Add(&artifact.Artifact{
   985  		Goos:   "windows",
   986  		Goarch: "amd64",
   987  		Name:   "mybin.exe",
   988  		Path:   filepath.Join(dist, "windowsamd64", "mybin.exe"),
   989  		Type:   artifact.Binary,
   990  		Extra: map[string]interface{}{
   991  			artifact.ExtraBinary: "mybin",
   992  			artifact.ExtraExt:    ".exe",
   993  			artifact.ExtraID:     "default",
   994  		},
   995  	})
   996  	ctx.Version = "0.0.1"
   997  	ctx.Git.CurrentTag = "v0.0.1"
   998  	err = Pipe{}.Run(ctx)
   999  	require.ErrorContains(t, err, "same-filename.tar.gz already exists. Check your archive name template")
  1000  }
  1001  
  1002  func TestDuplicateFilesInsideArchive(t *testing.T) {
  1003  	folder := t.TempDir()
  1004  
  1005  	f, err := os.CreateTemp(folder, "")
  1006  	require.NoError(t, err)
  1007  	t.Cleanup(func() {
  1008  		require.NoError(t, f.Close())
  1009  	})
  1010  
  1011  	ff, err := os.CreateTemp(folder, "")
  1012  	require.NoError(t, err)
  1013  	require.NoError(t, ff.Close())
  1014  	a, err := archive.New(f, "tar.gz")
  1015  	require.NoError(t, err)
  1016  	a = NewEnhancedArchive(a, "")
  1017  	t.Cleanup(func() {
  1018  		require.NoError(t, a.Close())
  1019  	})
  1020  
  1021  	require.NoError(t, a.Add(config.File{
  1022  		Source:      ff.Name(),
  1023  		Destination: "foo",
  1024  	}))
  1025  	require.ErrorIs(t, a.Add(config.File{
  1026  		Source:      ff.Name(),
  1027  		Destination: "foo",
  1028  	}), fs.ErrExist)
  1029  }
  1030  
  1031  func TestWrapInDirectory(t *testing.T) {
  1032  	t.Run("false", func(t *testing.T) {
  1033  		require.Equal(t, "", wrapFolder(config.Archive{
  1034  			WrapInDirectory: "false",
  1035  		}))
  1036  	})
  1037  	t.Run("true", func(t *testing.T) {
  1038  		require.Equal(t, "foo", wrapFolder(config.Archive{
  1039  			WrapInDirectory: "true",
  1040  			NameTemplate:    "foo",
  1041  		}))
  1042  	})
  1043  	t.Run("custom", func(t *testing.T) {
  1044  		require.Equal(t, "foobar", wrapFolder(config.Archive{
  1045  			WrapInDirectory: "foobar",
  1046  		}))
  1047  	})
  1048  }
  1049  
  1050  func TestSeveralArchivesWithTheSameID(t *testing.T) {
  1051  	ctx := testctx.NewWithCfg(config.Project{
  1052  		Archives: []config.Archive{
  1053  			{
  1054  				ID: "a",
  1055  			},
  1056  			{
  1057  				ID: "a",
  1058  			},
  1059  		},
  1060  	})
  1061  	require.EqualError(t, Pipe{}.Default(ctx), "found 2 archives with the ID 'a', please fix your config")
  1062  }
  1063  
  1064  func TestArchive_globbing(t *testing.T) {
  1065  	assertGlob := func(t *testing.T, files []config.File, expected []string) {
  1066  		t.Helper()
  1067  		bin, err := os.CreateTemp(t.TempDir(), "binary")
  1068  		require.NoError(t, err)
  1069  		dist := t.TempDir()
  1070  		ctx := testctx.NewWithCfg(config.Project{
  1071  			Dist: dist,
  1072  			Archives: []config.Archive{
  1073  				{
  1074  					Builds:       []string{"default"},
  1075  					Format:       "tar.gz",
  1076  					NameTemplate: "foo",
  1077  					Files:        files,
  1078  				},
  1079  			},
  1080  		})
  1081  
  1082  		ctx.Artifacts.Add(&artifact.Artifact{
  1083  			Goos:   "darwin",
  1084  			Goarch: "amd64",
  1085  			Name:   "foobin",
  1086  			Path:   bin.Name(),
  1087  			Type:   artifact.Binary,
  1088  			Extra: map[string]interface{}{
  1089  				artifact.ExtraID: "default",
  1090  			},
  1091  		})
  1092  
  1093  		require.NoError(t, Pipe{}.Run(ctx))
  1094  		require.Equal(t, append(expected, "foobin"), testlib.LsArchive(t, filepath.Join(dist, "foo.tar.gz"), "tar.gz"))
  1095  	}
  1096  
  1097  	t.Run("exact src file", func(t *testing.T) {
  1098  		assertGlob(t, []config.File{{Source: "testdata/a/a.txt"}}, []string{"testdata/a/a.txt"})
  1099  	})
  1100  
  1101  	t.Run("exact src file with dst", func(t *testing.T) {
  1102  		assertGlob(t, []config.File{
  1103  			{
  1104  				Source:      "testdata/a/a.txt",
  1105  				Destination: "foo/",
  1106  			},
  1107  		}, []string{"foo"})
  1108  	})
  1109  
  1110  	t.Run("glob src", func(t *testing.T) {
  1111  		assertGlob(t, []config.File{
  1112  			{Source: "testdata/**/*.txt"},
  1113  		}, []string{
  1114  			"testdata/a/a.txt",
  1115  			"testdata/a/b/a.txt",
  1116  			"testdata/a/b/c/d.txt",
  1117  		})
  1118  	})
  1119  
  1120  	t.Run("glob src with dst", func(t *testing.T) {
  1121  		assertGlob(t, []config.File{
  1122  			{
  1123  				Source:      "testdata/**/*.txt",
  1124  				Destination: "var/yada",
  1125  			},
  1126  		}, []string{
  1127  			"var/yada/a.txt",
  1128  			"var/yada/b/a.txt",
  1129  			"var/yada/b/c/d.txt",
  1130  		})
  1131  	})
  1132  
  1133  	t.Run("glob src with dst stripping parent", func(t *testing.T) {
  1134  		assertGlob(t, []config.File{
  1135  			{
  1136  				Source:      "testdata/**/*.txt",
  1137  				Destination: "var/yada",
  1138  				StripParent: true,
  1139  			},
  1140  		}, []string{
  1141  			"var/yada/a.txt",
  1142  			"var/yada/d.txt",
  1143  		})
  1144  	})
  1145  }
  1146  
  1147  func TestInvalidFormat(t *testing.T) {
  1148  	ctx := testctx.NewWithCfg(config.Project{
  1149  		Dist: t.TempDir(),
  1150  		Archives: []config.Archive{
  1151  			{
  1152  				ID:           "foo",
  1153  				NameTemplate: "foo",
  1154  				Meta:         true,
  1155  				Format:       "7z",
  1156  			},
  1157  		},
  1158  	})
  1159  	require.EqualError(t, Pipe{}.Run(ctx), "invalid archive format: 7z")
  1160  }
  1161  
  1162  func TestIssue3803(t *testing.T) {
  1163  	ctx := testctx.NewWithCfg(config.Project{
  1164  		Dist: t.TempDir(),
  1165  		Archives: []config.Archive{
  1166  			{
  1167  				ID:           "foo",
  1168  				NameTemplate: "foo",
  1169  				Meta:         true,
  1170  				Format:       "zip",
  1171  				Files: []config.File{
  1172  					{Source: "./testdata/a/a.txt"},
  1173  				},
  1174  			},
  1175  			{
  1176  				ID:           "foobar",
  1177  				NameTemplate: "foobar",
  1178  				Meta:         true,
  1179  				Format:       "zip",
  1180  				Files: []config.File{
  1181  					{Source: "./testdata/a/b/a.txt"},
  1182  				},
  1183  			},
  1184  		},
  1185  	})
  1186  	require.NoError(t, Pipe{}.Run(ctx))
  1187  	archives := ctx.Artifacts.List()
  1188  	require.Len(t, archives, 2)
  1189  }
  1190  
  1191  func TestExtraFormatWhenOverride(t *testing.T) {
  1192  	ctx := testctx.NewWithCfg(config.Project{
  1193  		Dist: t.TempDir(),
  1194  		Archives: []config.Archive{
  1195  			{
  1196  				ID:           "foo",
  1197  				NameTemplate: "foo",
  1198  				Format:       "tar.gz",
  1199  				FormatOverrides: []config.FormatOverride{{
  1200  					Goos:   "windows",
  1201  					Format: "zip",
  1202  				}},
  1203  				Files: []config.File{
  1204  					{Source: "./testdata/a/a.txt"},
  1205  				},
  1206  			},
  1207  		},
  1208  	})
  1209  	windowsBuild := &artifact.Artifact{
  1210  		Goos:    "windows",
  1211  		Goarch:  "amd64",
  1212  		Goamd64: "v1",
  1213  		Name:    "bin/mybin.exe",
  1214  		Path:    filepath.Join(ctx.Config.Dist, "windowsamd64", "bin", "mybin.exe"),
  1215  		Type:    artifact.Binary,
  1216  		Extra: map[string]interface{}{
  1217  			artifact.ExtraBinary: "mybin",
  1218  			artifact.ExtraExt:    ".exe",
  1219  			artifact.ExtraID:     "default",
  1220  		},
  1221  	}
  1222  	require.NoError(t, os.MkdirAll(filepath.Dir(windowsBuild.Path), 0o755))
  1223  	f, err := os.Create(windowsBuild.Path)
  1224  	require.NoError(t, err)
  1225  	require.NoError(t, f.Close())
  1226  	ctx.Artifacts.Add(windowsBuild)
  1227  	require.NoError(t, Pipe{}.Run(ctx))
  1228  	archives := ctx.Artifacts.Filter(artifact.ByFormats("zip")).List()
  1229  	require.Len(t, archives, 1)
  1230  }