github.com/goreleaser/goreleaser@v1.25.1/internal/pipe/nfpm/nfpm_test.go (about)

     1  package nfpm
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  	"testing"
     7  
     8  	"github.com/goreleaser/goreleaser/internal/artifact"
     9  	"github.com/goreleaser/goreleaser/internal/skips"
    10  	"github.com/goreleaser/goreleaser/internal/testctx"
    11  	"github.com/goreleaser/goreleaser/internal/testlib"
    12  	"github.com/goreleaser/goreleaser/pkg/config"
    13  	"github.com/goreleaser/goreleaser/pkg/context"
    14  	"github.com/goreleaser/nfpm/v2"
    15  	"github.com/goreleaser/nfpm/v2/files"
    16  	"github.com/stretchr/testify/require"
    17  )
    18  
    19  func TestDescription(t *testing.T) {
    20  	require.NotEmpty(t, Pipe{}.String())
    21  }
    22  
    23  func TestRunPipeNoFormats(t *testing.T) {
    24  	ctx := testctx.NewWithCfg(
    25  		config.Project{
    26  			NFPMs: []config.NFPM{
    27  				{},
    28  			},
    29  		},
    30  		testctx.WithCurrentTag("v1.0.1"),
    31  		testctx.WithVersion("1.0.1"),
    32  	)
    33  	require.NoError(t, Pipe{}.Default(ctx))
    34  	testlib.AssertSkipped(t, Pipe{}.Run(ctx))
    35  }
    36  
    37  func TestRunPipeError(t *testing.T) {
    38  	ctx := testctx.NewWithCfg(config.Project{
    39  		Dist: t.TempDir(),
    40  		NFPMs: []config.NFPM{
    41  			{
    42  				Formats: []string{"deb"},
    43  				NFPMOverridables: config.NFPMOverridables{
    44  					FileNameTemplate: "{{.ConventionalFileName}}",
    45  				},
    46  			},
    47  		},
    48  	})
    49  	ctx.Artifacts.Add(&artifact.Artifact{
    50  		Name:   "mybin",
    51  		Path:   "testdata/testfile.txt",
    52  		Goarch: "amd64",
    53  		Goos:   "linux",
    54  		Type:   artifact.Binary,
    55  		Extra: map[string]interface{}{
    56  			artifact.ExtraID: "foo",
    57  		},
    58  	})
    59  	require.NoError(t, Pipe{}.Default(ctx))
    60  	require.EqualError(t, Pipe{}.Run(ctx), "nfpm failed for _0.0.0~rc0_amd64.deb: package name must be provided")
    61  }
    62  
    63  func TestRunPipeInvalidFormat(t *testing.T) {
    64  	ctx := testctx.NewWithCfg(config.Project{
    65  		ProjectName: "nope",
    66  		NFPMs: []config.NFPM{
    67  			{
    68  				Bindir:  "/usr/bin",
    69  				Formats: []string{"nope"},
    70  				Builds:  []string{"foo"},
    71  				NFPMOverridables: config.NFPMOverridables{
    72  					PackageName:      "foo",
    73  					FileNameTemplate: defaultNameTemplate,
    74  				},
    75  			},
    76  		},
    77  	}, testctx.WithVersion("1.2.3"), testctx.WithCurrentTag("v1.2.3"))
    78  	for _, goos := range []string{"linux", "darwin"} {
    79  		for _, goarch := range []string{"amd64", "386"} {
    80  			ctx.Artifacts.Add(&artifact.Artifact{
    81  				Name:   "mybin",
    82  				Path:   "testdata/testfile.txt",
    83  				Goarch: goarch,
    84  				Goos:   goos,
    85  				Type:   artifact.Binary,
    86  				Extra: map[string]interface{}{
    87  					artifact.ExtraID: "foo",
    88  				},
    89  			})
    90  		}
    91  	}
    92  	require.Contains(t, Pipe{}.Run(ctx).Error(), `no packager registered for the format nope`)
    93  }
    94  
    95  func TestRunPipe(t *testing.T) {
    96  	folder := t.TempDir()
    97  	dist := filepath.Join(folder, "dist")
    98  	require.NoError(t, os.Mkdir(dist, 0o755))
    99  	require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755))
   100  	binPath := filepath.Join(dist, "mybin", "mybin")
   101  	foohPath := filepath.Join(dist, "foo.h")
   102  	foosoPath := filepath.Join(dist, "foo.so")
   103  	fooaPath := filepath.Join(dist, "foo.a")
   104  	for _, name := range []string{binPath, foosoPath, foohPath, fooaPath} {
   105  		f, err := os.Create(name)
   106  		require.NoError(t, err)
   107  		require.NoError(t, f.Close())
   108  
   109  	}
   110  	libPrefix := `/usr/lib
   111        {{- if eq .Arch "amd64" }}{{if eq .Format "rpm"}}_rpm{{end}}64{{- end -}}
   112  	`
   113  	ctx := testctx.NewWithCfg(config.Project{
   114  		ProjectName: "mybin",
   115  		Dist:        dist,
   116  		Env: []string{
   117  			"PRO=pro",
   118  			"DESC=templates",
   119  			"EXT=.sh",
   120  		},
   121  		NFPMs: []config.NFPM{
   122  			{
   123  				ID:          "someid",
   124  				Bindir:      "/usr/bin",
   125  				Builds:      []string{"default", "lib1", "lib2", "lib3"},
   126  				Formats:     []string{"deb", "rpm", "apk", "termux.deb", "archlinux"},
   127  				Section:     "somesection",
   128  				Priority:    "standard",
   129  				Description: "Some description with {{ .Env.DESC }}",
   130  				License:     "MIT",
   131  				Maintainer:  "me@me",
   132  				Vendor:      "asdf",
   133  				Homepage:    "https://goreleaser.com/{{ .Env.PRO }}",
   134  				Changelog:   "./testdata/changelog.yaml",
   135  				Libdirs: config.Libdirs{
   136  					Header:   libPrefix + "/headers",
   137  					CArchive: libPrefix + "/c-archives",
   138  					CShared:  libPrefix + "/c-shareds",
   139  				},
   140  				NFPMOverridables: config.NFPMOverridables{
   141  					FileNameTemplate: defaultNameTemplate + "-{{ .Release }}-{{ .Epoch }}",
   142  					PackageName:      "foo",
   143  					Dependencies:     []string{"make"},
   144  					Recommends:       []string{"svn"},
   145  					Suggests:         []string{"bzr"},
   146  					Replaces:         []string{"fish"},
   147  					Conflicts:        []string{"git"},
   148  					Provides:         []string{"ash"},
   149  					Release:          "10",
   150  					Epoch:            "20",
   151  					Scripts: config.NFPMScripts{
   152  						PreInstall:  "./testdata/pre_install{{.Env.EXT}}",
   153  						PostInstall: "./testdata/post_install{{.Env.EXT}}",
   154  						PreRemove:   "./testdata/pre_remove{{.Env.EXT}}",
   155  						PostRemove:  "./testdata/post_remove{{.Env.EXT}}",
   156  					},
   157  					Contents: []*files.Content{
   158  						{
   159  							Destination: "/var/log/foobar",
   160  							Type:        "dir",
   161  						},
   162  						{
   163  							Source:      "./testdata/testfile.txt",
   164  							Destination: "/usr/share/testfile.txt",
   165  						},
   166  						{
   167  							Source:      "./testdata/testfile.txt",
   168  							Destination: "/etc/nope.conf",
   169  							Type:        "config",
   170  						},
   171  						{
   172  							Destination: "/etc/mydir",
   173  							Type:        "dir",
   174  						},
   175  						{
   176  							Source:      "./testdata/testfile.txt",
   177  							Destination: "/etc/nope-rpm.conf",
   178  							Type:        "config",
   179  							Packager:    "rpm",
   180  						},
   181  						{
   182  							Source:      "/etc/nope.conf",
   183  							Destination: "/etc/nope2.conf",
   184  							Type:        "symlink",
   185  						},
   186  						{
   187  							Source:      "./testdata/testfile-{{ .Arch }}{{.Amd64}}{{.Arm}}{{.Mips}}.txt",
   188  							Destination: "/etc/nope3_{{ .ProjectName }}.conf",
   189  						},
   190  						{
   191  							Source:      "./testdata/folder",
   192  							Destination: "/etc/folder",
   193  						},
   194  					},
   195  				},
   196  			},
   197  		},
   198  	}, testctx.WithVersion("1.0.0"), testctx.WithCurrentTag("v1.0.0"))
   199  	for _, goos := range []string{"linux", "darwin", "ios"} {
   200  		for _, goarch := range []string{"amd64", "386", "arm64", "arm", "mips"} {
   201  			if goos == "ios" && goarch != "arm64" {
   202  				continue
   203  			}
   204  			switch goarch {
   205  			case "arm":
   206  				for _, goarm := range []string{"6", "7"} {
   207  					ctx.Artifacts.Add(&artifact.Artifact{
   208  						Name:   "subdir/mybin",
   209  						Path:   binPath,
   210  						Goarch: goarch,
   211  						Goos:   goos,
   212  						Goarm:  goarm,
   213  						Type:   artifact.Binary,
   214  						Extra: map[string]interface{}{
   215  							artifact.ExtraID: "default",
   216  						},
   217  					})
   218  					ctx.Artifacts.Add(&artifact.Artifact{
   219  						Name:   "foo.h",
   220  						Path:   foohPath,
   221  						Goarch: goarch,
   222  						Goos:   goos,
   223  						Goarm:  goarm,
   224  						Type:   artifact.Header,
   225  						Extra: map[string]interface{}{
   226  							artifact.ExtraID: "lib1",
   227  						},
   228  					})
   229  					ctx.Artifacts.Add(&artifact.Artifact{
   230  						Name:   "foo.so",
   231  						Path:   foosoPath,
   232  						Goarch: goarch,
   233  						Goos:   goos,
   234  						Goarm:  goarm,
   235  						Type:   artifact.CShared,
   236  						Extra: map[string]interface{}{
   237  							artifact.ExtraID: "lib2",
   238  						},
   239  					})
   240  					ctx.Artifacts.Add(&artifact.Artifact{
   241  						Name:   "foo.a",
   242  						Path:   fooaPath,
   243  						Goarch: goarch,
   244  						Goos:   goos,
   245  						Goarm:  goarm,
   246  						Type:   artifact.CArchive,
   247  						Extra: map[string]interface{}{
   248  							artifact.ExtraID: "lib3",
   249  						},
   250  					})
   251  				}
   252  			case "amd64":
   253  				for _, goamd64 := range []string{"v1", "v2", "v3", "v4"} {
   254  					ctx.Artifacts.Add(&artifact.Artifact{
   255  						Name:    "subdir/mybin",
   256  						Path:    binPath,
   257  						Goarch:  goarch,
   258  						Goos:    goos,
   259  						Goamd64: goamd64,
   260  						Type:    artifact.Binary,
   261  						Extra: map[string]interface{}{
   262  							artifact.ExtraID: "default",
   263  						},
   264  					})
   265  					ctx.Artifacts.Add(&artifact.Artifact{
   266  						Name:    "foo.h",
   267  						Path:    foohPath,
   268  						Goarch:  goarch,
   269  						Goos:    goos,
   270  						Goamd64: goamd64,
   271  						Type:    artifact.Header,
   272  						Extra: map[string]interface{}{
   273  							artifact.ExtraID: "lib1",
   274  						},
   275  					})
   276  					ctx.Artifacts.Add(&artifact.Artifact{
   277  						Name:    "foo.so",
   278  						Path:    foosoPath,
   279  						Goarch:  goarch,
   280  						Goos:    goos,
   281  						Goamd64: goamd64,
   282  						Type:    artifact.CShared,
   283  						Extra: map[string]interface{}{
   284  							artifact.ExtraID: "lib2",
   285  						},
   286  					})
   287  					ctx.Artifacts.Add(&artifact.Artifact{
   288  						Name:    "foo.a",
   289  						Path:    fooaPath,
   290  						Goarch:  goarch,
   291  						Goos:    goos,
   292  						Goamd64: goamd64,
   293  						Type:    artifact.CArchive,
   294  						Extra: map[string]interface{}{
   295  							artifact.ExtraID: "lib3",
   296  						},
   297  					})
   298  				}
   299  			case "mips":
   300  				for _, gomips := range []string{"softfloat", "hardfloat"} {
   301  					ctx.Artifacts.Add(&artifact.Artifact{
   302  						Name:   "subdir/mybin",
   303  						Path:   binPath,
   304  						Goarch: goarch,
   305  						Goos:   goos,
   306  						Gomips: gomips,
   307  						Type:   artifact.Binary,
   308  						Extra: map[string]interface{}{
   309  							artifact.ExtraID: "default",
   310  						},
   311  					})
   312  					ctx.Artifacts.Add(&artifact.Artifact{
   313  						Name:   "foo.h",
   314  						Path:   foohPath,
   315  						Goarch: goarch,
   316  						Goos:   goos,
   317  						Gomips: gomips,
   318  						Type:   artifact.Header,
   319  						Extra: map[string]interface{}{
   320  							artifact.ExtraID: "lib1",
   321  						},
   322  					})
   323  					ctx.Artifacts.Add(&artifact.Artifact{
   324  						Name:   "foo.so",
   325  						Path:   foosoPath,
   326  						Goarch: goarch,
   327  						Goos:   goos,
   328  						Gomips: gomips,
   329  						Type:   artifact.CShared,
   330  						Extra: map[string]interface{}{
   331  							artifact.ExtraID: "lib2",
   332  						},
   333  					})
   334  					ctx.Artifacts.Add(&artifact.Artifact{
   335  						Name:   "foo.a",
   336  						Path:   fooaPath,
   337  						Goarch: goarch,
   338  						Goos:   goos,
   339  						Gomips: gomips,
   340  						Type:   artifact.CArchive,
   341  						Extra: map[string]interface{}{
   342  							artifact.ExtraID: "lib3",
   343  						},
   344  					})
   345  				}
   346  			default:
   347  				ctx.Artifacts.Add(&artifact.Artifact{
   348  					Name:   "subdir/mybin",
   349  					Path:   binPath,
   350  					Goarch: goarch,
   351  					Goos:   goos,
   352  					Type:   artifact.Binary,
   353  					Extra: map[string]interface{}{
   354  						artifact.ExtraID: "default",
   355  					},
   356  				})
   357  				ctx.Artifacts.Add(&artifact.Artifact{
   358  					Name:   "foo.h",
   359  					Path:   foohPath,
   360  					Goarch: goarch,
   361  					Goos:   goos,
   362  					Type:   artifact.Header,
   363  					Extra: map[string]interface{}{
   364  						artifact.ExtraID: "lib1",
   365  					},
   366  				})
   367  				ctx.Artifacts.Add(&artifact.Artifact{
   368  					Name:   "foo.so",
   369  					Path:   foosoPath,
   370  					Goarch: goarch,
   371  					Goos:   goos,
   372  					Type:   artifact.CShared,
   373  					Extra: map[string]interface{}{
   374  						artifact.ExtraID: "lib2",
   375  					},
   376  				})
   377  				ctx.Artifacts.Add(&artifact.Artifact{
   378  					Name:   "foo.a",
   379  					Path:   fooaPath,
   380  					Goarch: goarch,
   381  					Goos:   goos,
   382  					Type:   artifact.CArchive,
   383  					Extra: map[string]interface{}{
   384  						artifact.ExtraID: "lib3",
   385  					},
   386  				})
   387  			}
   388  		}
   389  	}
   390  	require.NoError(t, Pipe{}.Run(ctx))
   391  	packages := ctx.Artifacts.Filter(artifact.ByType(artifact.LinuxPackage)).List()
   392  	require.Len(t, packages, 44)
   393  	for _, pkg := range packages {
   394  		format := pkg.Format()
   395  		require.NotEmpty(t, format)
   396  		require.Equal(t, pkg.Format(), artifact.ExtraOr(*pkg, artifact.ExtraExt, ""))
   397  		arch := pkg.Goarch
   398  		if pkg.Goarm != "" {
   399  			arch += "v" + pkg.Goarm
   400  		}
   401  		if pkg.Goamd64 != "v1" {
   402  			arch += pkg.Goamd64
   403  		}
   404  		if pkg.Gomips != "" {
   405  			arch += "_" + pkg.Gomips
   406  		}
   407  
   408  		ext := "." + format
   409  		if format != termuxFormat {
   410  			packager, err := nfpm.Get(format)
   411  			require.NoError(t, err)
   412  
   413  			if packager, ok := packager.(nfpm.PackagerWithExtension); ok {
   414  				ext = packager.ConventionalExtension()
   415  			}
   416  		}
   417  
   418  		if pkg.Goos == "linux" {
   419  			require.Equal(t, "foo_1.0.0_linux_"+arch+"-10-20"+ext, pkg.Name)
   420  		} else {
   421  			require.Equal(t, "foo_1.0.0_ios_arm64-10-20"+ext, pkg.Name)
   422  		}
   423  		require.Equal(t, "someid", pkg.ID())
   424  		require.ElementsMatch(t, []string{
   425  			"./testdata/testfile.txt",
   426  			"./testdata/testfile.txt",
   427  			"./testdata/testfile.txt",
   428  			"/etc/nope.conf",
   429  			"./testdata/folder",
   430  			"./testdata/testfile-" + pkg.Goarch + pkg.Goamd64 + pkg.Goarm + pkg.Gomips + ".txt",
   431  			binPath,
   432  			foohPath,
   433  			fooaPath,
   434  			foosoPath,
   435  		}, sources(artifact.ExtraOr(*pkg, extraFiles, files.Contents{})))
   436  
   437  		bin := "/usr/bin/subdir/"
   438  		header := "/usr/lib/headers"
   439  		carchive := "/usr/lib/c-archives"
   440  		cshared := "/usr/lib/c-shareds"
   441  		if pkg.Goarch == "amd64" {
   442  			if pkg.Format() == "rpm" {
   443  				header = "/usr/lib_rpm64/headers"
   444  				carchive = "/usr/lib_rpm64/c-archives"
   445  				cshared = "/usr/lib_rpm64/c-shareds"
   446  			} else {
   447  				header = "/usr/lib64/headers"
   448  				carchive = "/usr/lib64/c-archives"
   449  				cshared = "/usr/lib64/c-shareds"
   450  			}
   451  		}
   452  		if format == termuxFormat {
   453  			bin = filepath.Join("/data/data/com.termux/files", bin)
   454  			header = filepath.Join("/data/data/com.termux/files", header)
   455  			cshared = filepath.Join("/data/data/com.termux/files", cshared)
   456  			carchive = filepath.Join("/data/data/com.termux/files", carchive)
   457  		}
   458  		bin = filepath.Join(bin, "mybin")
   459  		header = filepath.Join(header, "foo.h")
   460  		cshared = filepath.Join(cshared, "foo.so")
   461  		carchive = filepath.Join(carchive, "foo.a")
   462  		require.ElementsMatch(t, []string{
   463  			"/var/log/foobar",
   464  			"/usr/share/testfile.txt",
   465  			"/etc/mydir",
   466  			"/etc/nope.conf",
   467  			"/etc/nope-rpm.conf",
   468  			"/etc/nope2.conf",
   469  			"/etc/nope3_mybin.conf",
   470  			"/etc/folder",
   471  			bin,
   472  			header,
   473  			carchive,
   474  			cshared,
   475  		}, destinations(artifact.ExtraOr(*pkg, extraFiles, files.Contents{})))
   476  	}
   477  	require.Len(t, ctx.Config.NFPMs[0].Contents, 8, "should not modify the config file list")
   478  }
   479  
   480  func TestRunPipeConventionalNameTemplate(t *testing.T) {
   481  	t.Run("regular", func(t *testing.T) { doTestRunPipeConventionalNameTemplate(t, false) })
   482  	t.Run("snapshot", func(t *testing.T) { doTestRunPipeConventionalNameTemplate(t, true) })
   483  }
   484  
   485  func doTestRunPipeConventionalNameTemplate(t *testing.T, snapshot bool) {
   486  	t.Helper()
   487  	folder := t.TempDir()
   488  	dist := filepath.Join(folder, "dist")
   489  	require.NoError(t, os.Mkdir(dist, 0o755))
   490  	require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755))
   491  	binPath := filepath.Join(dist, "mybin", "mybin")
   492  	f, err := os.Create(binPath)
   493  	require.NoError(t, err)
   494  	require.NoError(t, f.Close())
   495  	ctx := testctx.NewWithCfg(config.Project{
   496  		ProjectName: "mybin",
   497  		Dist:        dist,
   498  		NFPMs: []config.NFPM{
   499  			{
   500  				ID:          "someid",
   501  				Builds:      []string{"default"},
   502  				Formats:     []string{"deb", "rpm", "apk", "archlinux"},
   503  				Section:     "somesection",
   504  				Priority:    "standard",
   505  				Description: "Some description ",
   506  				License:     "MIT",
   507  				Maintainer:  "me@me",
   508  				Vendor:      "asdf",
   509  				Homepage:    "https://goreleaser.com/",
   510  				Bindir:      "/usr/bin",
   511  				NFPMOverridables: config.NFPMOverridables{
   512  					FileNameTemplate: `
   513  						{{- trimsuffix .ConventionalFileName .ConventionalExtension -}}
   514  						{{- if and (eq .Arm "6") (eq .ConventionalExtension ".deb") }}6{{ end -}}
   515  						{{- if not (eq .Amd64 "v1")}}{{ .Amd64 }}{{ end -}}
   516  						{{- .ConventionalExtension -}}
   517  					`,
   518  					PackageName: "foo{{ if .IsSnapshot }}-snapshot{{ end }}",
   519  				},
   520  			},
   521  		},
   522  	}, testctx.WithVersion("1.0.0"), testctx.WithCurrentTag("v1.0.0"))
   523  	if snapshot {
   524  		ctx.Snapshot = true
   525  	}
   526  	for _, goos := range []string{"linux", "darwin"} {
   527  		for _, goarch := range []string{"amd64", "386", "arm64", "arm", "mips"} {
   528  			switch goarch {
   529  			case "arm":
   530  				for _, goarm := range []string{"6", "7"} {
   531  					ctx.Artifacts.Add(&artifact.Artifact{
   532  						Name:   "subdir/mybin",
   533  						Path:   binPath,
   534  						Goarch: goarch,
   535  						Goos:   goos,
   536  						Goarm:  goarm,
   537  						Type:   artifact.Binary,
   538  						Extra: map[string]interface{}{
   539  							artifact.ExtraID: "default",
   540  						},
   541  					})
   542  				}
   543  			case "amd64":
   544  				for _, goamd64 := range []string{"v1", "v2", "v3", "v4"} {
   545  					ctx.Artifacts.Add(&artifact.Artifact{
   546  						Name:    "subdir/mybin",
   547  						Path:    binPath,
   548  						Goarch:  goarch,
   549  						Goos:    goos,
   550  						Goamd64: goamd64,
   551  						Type:    artifact.Binary,
   552  						Extra: map[string]interface{}{
   553  							artifact.ExtraID: "default",
   554  						},
   555  					})
   556  				}
   557  			case "mips":
   558  				for _, gomips := range []string{"softfloat", "hardfloat"} {
   559  					ctx.Artifacts.Add(&artifact.Artifact{
   560  						Name:   "subdir/mybin",
   561  						Path:   binPath,
   562  						Goarch: goarch,
   563  						Goos:   goos,
   564  						Gomips: gomips,
   565  						Type:   artifact.Binary,
   566  						Extra: map[string]interface{}{
   567  							artifact.ExtraID: "default",
   568  						},
   569  					})
   570  				}
   571  			default:
   572  				ctx.Artifacts.Add(&artifact.Artifact{
   573  					Name:   "subdir/mybin",
   574  					Path:   binPath,
   575  					Goarch: goarch,
   576  					Goos:   goos,
   577  					Type:   artifact.Binary,
   578  					Extra: map[string]interface{}{
   579  						artifact.ExtraID: "default",
   580  					},
   581  				})
   582  			}
   583  		}
   584  	}
   585  	require.NoError(t, Pipe{}.Run(ctx))
   586  	packages := ctx.Artifacts.Filter(artifact.ByType(artifact.LinuxPackage)).List()
   587  	require.Len(t, packages, 37)
   588  	prefix := "foo"
   589  	if snapshot {
   590  		prefix += "-snapshot"
   591  	}
   592  	for _, pkg := range packages {
   593  		format := pkg.Format()
   594  		require.NotEmpty(t, format)
   595  		require.Contains(t, []string{
   596  			prefix + "-1.0.0-1.aarch64.rpm",
   597  			prefix + "-1.0.0-1.armv6hl.rpm",
   598  			prefix + "-1.0.0-1.armv7hl.rpm",
   599  			prefix + "-1.0.0-1.i386.rpm",
   600  			prefix + "-1.0.0-1.mips.rpm",
   601  			prefix + "-1.0.0-1.mips.rpm",
   602  			prefix + "-1.0.0-1.x86_64.rpm",
   603  			prefix + "-1.0.0-1.x86_64v2.rpm",
   604  			prefix + "-1.0.0-1.x86_64v3.rpm",
   605  			prefix + "-1.0.0-1.x86_64v4.rpm",
   606  			prefix + "_1.0.0_aarch64.apk",
   607  			prefix + "_1.0.0_amd64.deb",
   608  			prefix + "_1.0.0_amd64v2.deb",
   609  			prefix + "_1.0.0_amd64v3.deb",
   610  			prefix + "_1.0.0_amd64v4.deb",
   611  			prefix + "_1.0.0_arm64.deb",
   612  			prefix + "_1.0.0_armhf.apk",
   613  			prefix + "_1.0.0_armhf.deb",
   614  			prefix + "_1.0.0_armhf6.deb",
   615  			prefix + "_1.0.0_armv7.apk",
   616  			prefix + "_1.0.0_i386.deb",
   617  			prefix + "_1.0.0_mips.apk",
   618  			prefix + "_1.0.0_mips.deb",
   619  			prefix + "_1.0.0_mips.apk",
   620  			prefix + "_1.0.0_mips.deb",
   621  			prefix + "_1.0.0_x86.apk",
   622  			prefix + "_1.0.0_x86_64.apk",
   623  			prefix + "_1.0.0_x86_64v2.apk",
   624  			prefix + "_1.0.0_x86_64v3.apk",
   625  			prefix + "_1.0.0_x86_64v4.apk",
   626  			prefix + "-1.0.0-1-aarch64.pkg.tar.zst",
   627  			prefix + "-1.0.0-1-armv6h.pkg.tar.zst",
   628  			prefix + "-1.0.0-1-armv7h.pkg.tar.zst",
   629  			prefix + "-1.0.0-1-i686.pkg.tar.zst",
   630  			prefix + "-1.0.0-1-x86_64.pkg.tar.zst",
   631  			prefix + "-1.0.0-1-x86_64v2.pkg.tar.zst",
   632  			prefix + "-1.0.0-1-x86_64v3.pkg.tar.zst",
   633  			prefix + "-1.0.0-1-x86_64v4.pkg.tar.zst",
   634  			prefix + "-1.0.0-1-mips.pkg.tar.zst",
   635  			prefix + "-1.0.0-1-mips.pkg.tar.zst",
   636  		}, pkg.Name, "package name is not expected")
   637  		require.Equal(t, "someid", pkg.ID())
   638  		require.ElementsMatch(t, []string{binPath}, sources(artifact.ExtraOr(*pkg, extraFiles, files.Contents{})))
   639  		require.ElementsMatch(t, []string{"/usr/bin/subdir/mybin"}, destinations(artifact.ExtraOr(*pkg, extraFiles, files.Contents{})))
   640  	}
   641  }
   642  
   643  func TestInvalidTemplate(t *testing.T) {
   644  	makeCtx := func() *context.Context {
   645  		ctx := testctx.NewWithCfg(
   646  			config.Project{
   647  				ProjectName: "test",
   648  				NFPMs: []config.NFPM{
   649  					{
   650  						Formats: []string{"deb"},
   651  						Builds:  []string{"default"},
   652  					},
   653  				},
   654  			},
   655  			testctx.WithVersion("1.2.3"),
   656  		)
   657  		ctx.Artifacts.Add(&artifact.Artifact{
   658  			Name:   "mybin",
   659  			Goos:   "linux",
   660  			Goarch: "amd64",
   661  			Type:   artifact.Binary,
   662  			Extra: map[string]interface{}{
   663  				artifact.ExtraID: "default",
   664  			},
   665  		})
   666  		return ctx
   667  	}
   668  
   669  	t.Run("filename_template", func(t *testing.T) {
   670  		ctx := makeCtx()
   671  		ctx.Config.NFPMs[0].Meta = true
   672  		ctx.Config.NFPMs[0].NFPMOverridables = config.NFPMOverridables{
   673  			FileNameTemplate: "{{.Foo}",
   674  		}
   675  		require.NoError(t, Pipe{}.Default(ctx))
   676  		testlib.RequireTemplateError(t, Pipe{}.Run(ctx))
   677  	})
   678  
   679  	t.Run("source", func(t *testing.T) {
   680  		ctx := makeCtx()
   681  		ctx.Config.NFPMs[0].NFPMOverridables = config.NFPMOverridables{
   682  			Contents: files.Contents{
   683  				{
   684  					Source:      "{{ .NOPE_SOURCE }}",
   685  					Destination: "/foo",
   686  				},
   687  			},
   688  		}
   689  		testlib.RequireTemplateError(t, Pipe{}.Run(ctx))
   690  	})
   691  
   692  	t.Run("target", func(t *testing.T) {
   693  		ctx := makeCtx()
   694  		ctx.Config.NFPMs[0].NFPMOverridables = config.NFPMOverridables{
   695  			Contents: files.Contents{
   696  				{
   697  					Source:      "./testdata/testfile.txt",
   698  					Destination: "{{ .NOPE_TARGET }}",
   699  				},
   700  			},
   701  		}
   702  		testlib.RequireTemplateError(t, Pipe{}.Run(ctx))
   703  	})
   704  
   705  	t.Run("description", func(t *testing.T) {
   706  		ctx := makeCtx()
   707  		ctx.Config.NFPMs[0].Description = "{{ .NOPE_DESC }}"
   708  		testlib.RequireTemplateError(t, Pipe{}.Run(ctx))
   709  	})
   710  
   711  	t.Run("maintainer", func(t *testing.T) {
   712  		ctx := makeCtx()
   713  		ctx.Config.NFPMs[0].Maintainer = "{{ .NOPE_DESC }}"
   714  		testlib.RequireTemplateError(t, Pipe{}.Run(ctx))
   715  	})
   716  
   717  	t.Run("homepage", func(t *testing.T) {
   718  		ctx := makeCtx()
   719  		ctx.Config.NFPMs[0].Homepage = "{{ .NOPE_HOMEPAGE }}"
   720  		testlib.RequireTemplateError(t, Pipe{}.Run(ctx))
   721  	})
   722  
   723  	t.Run("deb key file", func(t *testing.T) {
   724  		ctx := makeCtx()
   725  		ctx.Config.NFPMs[0].Deb.Signature.KeyFile = "{{ .NOPE_KEY_FILE }}"
   726  		testlib.RequireTemplateError(t, Pipe{}.Run(ctx))
   727  	})
   728  
   729  	t.Run("rpm key file", func(t *testing.T) {
   730  		ctx := makeCtx()
   731  		ctx.Config.NFPMs[0].RPM.Signature.KeyFile = "{{ .NOPE_KEY_FILE }}"
   732  		testlib.RequireTemplateError(t, Pipe{}.Run(ctx))
   733  	})
   734  
   735  	t.Run("apk key file", func(t *testing.T) {
   736  		ctx := makeCtx()
   737  		ctx.Config.NFPMs[0].APK.Signature.KeyFile = "{{ .NOPE_KEY_FILE }}"
   738  		testlib.RequireTemplateError(t, Pipe{}.Run(ctx))
   739  	})
   740  
   741  	t.Run("apk key name", func(t *testing.T) {
   742  		ctx := makeCtx()
   743  		ctx.Config.NFPMs[0].APK.Signature.KeyName = "{{ .NOPE_KEY_FILE }}"
   744  		testlib.RequireTemplateError(t, Pipe{}.Run(ctx))
   745  	})
   746  
   747  	t.Run("bindir", func(t *testing.T) {
   748  		ctx := makeCtx()
   749  		ctx.Config.NFPMs[0].Bindir = "/usr/{{ .NOPE }}"
   750  		testlib.RequireTemplateError(t, Pipe{}.Run(ctx))
   751  	})
   752  }
   753  
   754  func TestRunPipeInvalidContentsSourceTemplate(t *testing.T) {
   755  	ctx := testctx.NewWithCfg(config.Project{
   756  		NFPMs: []config.NFPM{
   757  			{
   758  				NFPMOverridables: config.NFPMOverridables{
   759  					PackageName: "foo",
   760  					Contents: []*files.Content{
   761  						{
   762  							Source:      "{{.asdsd}",
   763  							Destination: "testfile",
   764  						},
   765  					},
   766  				},
   767  				Formats: []string{"deb"},
   768  				Builds:  []string{"default"},
   769  			},
   770  		},
   771  	})
   772  	ctx.Artifacts.Add(&artifact.Artifact{
   773  		Name:   "mybin",
   774  		Goos:   "linux",
   775  		Goarch: "amd64",
   776  		Type:   artifact.Binary,
   777  		Extra: map[string]interface{}{
   778  			artifact.ExtraID: "default",
   779  		},
   780  	})
   781  	testlib.RequireTemplateError(t, Pipe{}.Run(ctx))
   782  }
   783  
   784  func TestNoBuildsFound(t *testing.T) {
   785  	ctx := testctx.NewWithCfg(config.Project{
   786  		NFPMs: []config.NFPM{
   787  			{
   788  				Formats: []string{"deb"},
   789  				Builds:  []string{"nope"},
   790  			},
   791  		},
   792  	})
   793  	ctx.Artifacts.Add(&artifact.Artifact{
   794  		Name:   "mybin",
   795  		Goos:   "linux",
   796  		Goarch: "amd64",
   797  		Type:   artifact.Binary,
   798  		Extra: map[string]interface{}{
   799  			artifact.ExtraID: "default",
   800  		},
   801  	})
   802  	require.EqualError(t, Pipe{}.Run(ctx), `no linux binaries found for builds [nope]`)
   803  }
   804  
   805  func TestCreateFileDoesntExist(t *testing.T) {
   806  	folder := t.TempDir()
   807  	dist := filepath.Join(folder, "dist")
   808  	require.NoError(t, os.Mkdir(dist, 0o755))
   809  	require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755))
   810  	ctx := testctx.NewWithCfg(config.Project{
   811  		Dist:        dist,
   812  		ProjectName: "asd",
   813  		NFPMs: []config.NFPM{
   814  			{
   815  				Formats: []string{"deb", "rpm"},
   816  				Builds:  []string{"default"},
   817  				NFPMOverridables: config.NFPMOverridables{
   818  					PackageName: "foo",
   819  					Contents: []*files.Content{
   820  						{
   821  							Source:      "testdata/testfile.txt",
   822  							Destination: "/var/lib/test/testfile.txt",
   823  						},
   824  					},
   825  				},
   826  			},
   827  		},
   828  	}, testctx.WithVersion("1.2.3"), testctx.WithCurrentTag("v1.2.3"))
   829  	ctx.Artifacts.Add(&artifact.Artifact{
   830  		Name:   "mybin",
   831  		Path:   filepath.Join(dist, "mybin", "mybin"),
   832  		Goos:   "linux",
   833  		Goarch: "amd64",
   834  		Type:   artifact.Binary,
   835  		Extra: map[string]interface{}{
   836  			artifact.ExtraID: "default",
   837  		},
   838  	})
   839  	require.Contains(t, Pipe{}.Run(ctx).Error(), `dist/mybin/mybin": file does not exist`)
   840  }
   841  
   842  func TestInvalidConfig(t *testing.T) {
   843  	folder := t.TempDir()
   844  	dist := filepath.Join(folder, "dist")
   845  	require.NoError(t, os.Mkdir(dist, 0o755))
   846  	require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755))
   847  	ctx := testctx.NewWithCfg(config.Project{
   848  		Dist: dist,
   849  		NFPMs: []config.NFPM{
   850  			{
   851  				Formats: []string{"deb"},
   852  				Builds:  []string{"default"},
   853  			},
   854  		},
   855  	}, testctx.WithCurrentTag("v1.2.3"), testctx.WithVersion("1.2.3"))
   856  	ctx.Artifacts.Add(&artifact.Artifact{
   857  		Name:   "mybin",
   858  		Path:   filepath.Join(dist, "mybin", "mybin"),
   859  		Goos:   "linux",
   860  		Goarch: "amd64",
   861  		Type:   artifact.Binary,
   862  		Extra: map[string]interface{}{
   863  			artifact.ExtraID: "default",
   864  		},
   865  	})
   866  	require.Contains(t, Pipe{}.Run(ctx).Error(), `package name must be provided`)
   867  }
   868  
   869  func TestDefault(t *testing.T) {
   870  	ctx := testctx.NewWithCfg(config.Project{
   871  		ProjectName: "foobar",
   872  		NFPMs: []config.NFPM{
   873  			{},
   874  		},
   875  	})
   876  	require.NoError(t, Pipe{}.Default(ctx))
   877  	require.Equal(t, "/usr/bin", ctx.Config.NFPMs[0].Bindir)
   878  	require.Empty(t, ctx.Config.NFPMs[0].Builds)
   879  	require.Equal(t, defaultNameTemplate, ctx.Config.NFPMs[0].FileNameTemplate)
   880  	require.Equal(t, ctx.Config.ProjectName, ctx.Config.NFPMs[0].PackageName)
   881  }
   882  
   883  func TestDefaultSet(t *testing.T) {
   884  	ctx := testctx.NewWithCfg(config.Project{
   885  		NFPMs: []config.NFPM{
   886  			{
   887  				Builds: []string{"foo"},
   888  				Bindir: "/bin",
   889  				NFPMOverridables: config.NFPMOverridables{
   890  					FileNameTemplate: "foo",
   891  				},
   892  			},
   893  		},
   894  	})
   895  	require.NoError(t, Pipe{}.Default(ctx))
   896  	require.Equal(t, "/bin", ctx.Config.NFPMs[0].Bindir)
   897  	require.Equal(t, "foo", ctx.Config.NFPMs[0].FileNameTemplate)
   898  	require.Equal(t, []string{"foo"}, ctx.Config.NFPMs[0].Builds)
   899  	require.Equal(t, config.NFPMRPMScripts{}, ctx.Config.NFPMs[0].RPM.Scripts)
   900  }
   901  
   902  func TestOverrides(t *testing.T) {
   903  	ctx := testctx.NewWithCfg(config.Project{
   904  		NFPMs: []config.NFPM{
   905  			{
   906  				Bindir: "/bin",
   907  				NFPMOverridables: config.NFPMOverridables{
   908  					FileNameTemplate: "foo",
   909  				},
   910  				Overrides: map[string]config.NFPMOverridables{
   911  					"deb": {
   912  						FileNameTemplate: "bar",
   913  					},
   914  				},
   915  			},
   916  		},
   917  	})
   918  	require.NoError(t, Pipe{}.Default(ctx))
   919  	merged, err := mergeOverrides(ctx.Config.NFPMs[0], "deb")
   920  	require.NoError(t, err)
   921  	require.Equal(t, "/bin", ctx.Config.NFPMs[0].Bindir)
   922  	require.Equal(t, "foo", ctx.Config.NFPMs[0].FileNameTemplate)
   923  	require.Equal(t, "bar", ctx.Config.NFPMs[0].Overrides["deb"].FileNameTemplate)
   924  	require.Equal(t, "bar", merged.FileNameTemplate)
   925  }
   926  
   927  func TestDebSpecificConfig(t *testing.T) {
   928  	setupContext := func(tb testing.TB) *context.Context {
   929  		tb.Helper()
   930  		folder := t.TempDir()
   931  		dist := filepath.Join(folder, "dist")
   932  		require.NoError(t, os.Mkdir(dist, 0o755))
   933  		require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755))
   934  		binPath := filepath.Join(dist, "mybin", "mybin")
   935  		f, err := os.Create(binPath)
   936  		require.NoError(t, err)
   937  		require.NoError(t, f.Close())
   938  		ctx := testctx.NewWithCfg(config.Project{
   939  			ProjectName: "mybin",
   940  			Dist:        dist,
   941  			NFPMs: []config.NFPM{
   942  				{
   943  					ID:         "someid",
   944  					Builds:     []string{"default"},
   945  					Formats:    []string{"deb"},
   946  					Maintainer: "foo",
   947  					NFPMOverridables: config.NFPMOverridables{
   948  						PackageName: "foo",
   949  						Contents: []*files.Content{
   950  							{
   951  								Source:      "testdata/testfile.txt",
   952  								Destination: "/usr/share/testfile.txt",
   953  							},
   954  						},
   955  						Deb: config.NFPMDeb{
   956  							Signature: config.NFPMDebSignature{
   957  								KeyFile: "./testdata/privkey.gpg",
   958  							},
   959  						},
   960  					},
   961  				},
   962  			},
   963  		}, testctx.WithVersion("1.0.0"), testctx.WithCurrentTag("v1.0.0"))
   964  		for _, goos := range []string{"linux", "darwin"} {
   965  			for _, goarch := range []string{"amd64", "386"} {
   966  				ctx.Artifacts.Add(&artifact.Artifact{
   967  					Name:   "mybin",
   968  					Path:   binPath,
   969  					Goarch: goarch,
   970  					Goos:   goos,
   971  					Type:   artifact.Binary,
   972  					Extra: map[string]interface{}{
   973  						artifact.ExtraID: "default",
   974  					},
   975  				})
   976  			}
   977  		}
   978  		return ctx
   979  	}
   980  
   981  	t.Run("no passphrase set", func(t *testing.T) {
   982  		require.Contains(
   983  			t,
   984  			Pipe{}.Run(setupContext(t)).Error(),
   985  			`key is encrypted but no passphrase was provided`,
   986  		)
   987  	})
   988  
   989  	t.Run("global passphrase set", func(t *testing.T) {
   990  		ctx := setupContext(t)
   991  		ctx.Env = map[string]string{
   992  			"NFPM_PASSPHRASE": "hunter2",
   993  		}
   994  		require.NoError(t, Pipe{}.Run(ctx))
   995  	})
   996  
   997  	t.Run("general passphrase set", func(t *testing.T) {
   998  		ctx := setupContext(t)
   999  		ctx.Env = map[string]string{
  1000  			"NFPM_SOMEID_PASSPHRASE": "hunter2",
  1001  		}
  1002  		require.NoError(t, Pipe{}.Run(ctx))
  1003  	})
  1004  
  1005  	t.Run("packager specific passphrase set", func(t *testing.T) {
  1006  		ctx := setupContext(t)
  1007  		ctx.Env = map[string]string{
  1008  			"NFPM_SOMEID_DEB_PASSPHRASE": "hunter2",
  1009  		}
  1010  		require.NoError(t, Pipe{}.Run(ctx))
  1011  	})
  1012  
  1013  	t.Run("lintian", func(t *testing.T) {
  1014  		ctx := setupContext(t)
  1015  		ctx.Parallelism = 100
  1016  		ctx.Env = map[string]string{
  1017  			"NFPM_SOMEID_DEB_PASSPHRASE": "hunter2",
  1018  		}
  1019  		ctx.Config.NFPMs[0].Deb.Lintian = []string{
  1020  			"statically-linked-binary",
  1021  			"changelog-file-missing-in-native-package",
  1022  		}
  1023  		ctx.Config.NFPMs[0].Formats = []string{"apk", "rpm", "deb", "termux.deb"}
  1024  
  1025  		require.NoError(t, Pipe{}.Run(ctx))
  1026  		for _, format := range []string{"apk", "rpm"} {
  1027  			require.NoDirExists(t, filepath.Join(ctx.Config.Dist, format))
  1028  		}
  1029  		require.DirExists(t, filepath.Join(ctx.Config.Dist, "deb"))
  1030  		for _, goarch := range []string{"amd64", "386"} {
  1031  			bts, err := os.ReadFile(filepath.Join(ctx.Config.Dist, "deb", "foo_"+goarch, "lintian"))
  1032  			require.NoError(t, err)
  1033  			require.Equal(t, "foo: statically-linked-binary\nfoo: changelog-file-missing-in-native-package", string(bts))
  1034  		}
  1035  		require.DirExists(t, filepath.Join(ctx.Config.Dist, "termux.deb"))
  1036  		for _, goarch := range []string{"x86_64", "i686"} {
  1037  			bts, err := os.ReadFile(filepath.Join(ctx.Config.Dist, "termux.deb", "foo_"+goarch, "lintian"))
  1038  			require.NoError(t, err)
  1039  			require.Equal(t, "foo: statically-linked-binary\nfoo: changelog-file-missing-in-native-package", string(bts))
  1040  		}
  1041  	})
  1042  
  1043  	t.Run("lintian no debs", func(t *testing.T) {
  1044  		ctx := setupContext(t)
  1045  		ctx.Parallelism = 100
  1046  		ctx.Env = map[string]string{
  1047  			"NFPM_SOMEID_DEB_PASSPHRASE": "hunter2",
  1048  		}
  1049  		ctx.Config.NFPMs[0].Deb.Lintian = []string{
  1050  			"statically-linked-binary",
  1051  			"changelog-file-missing-in-native-package",
  1052  		}
  1053  		ctx.Config.NFPMs[0].Formats = []string{"apk", "rpm"}
  1054  
  1055  		require.NoError(t, Pipe{}.Run(ctx))
  1056  		for _, format := range []string{"deb", "termux.deb"} {
  1057  			require.NoDirExists(t, filepath.Join(ctx.Config.Dist, format))
  1058  		}
  1059  	})
  1060  }
  1061  
  1062  func TestRPMSpecificConfig(t *testing.T) {
  1063  	folder := t.TempDir()
  1064  	dist := filepath.Join(folder, "dist")
  1065  	require.NoError(t, os.Mkdir(dist, 0o755))
  1066  	require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755))
  1067  	binPath := filepath.Join(dist, "mybin", "mybin")
  1068  	f, err := os.Create(binPath)
  1069  	require.NoError(t, err)
  1070  	require.NoError(t, f.Close())
  1071  	ctx := testctx.NewWithCfg(config.Project{
  1072  		ProjectName: "mybin",
  1073  		Dist:        dist,
  1074  		NFPMs: []config.NFPM{
  1075  			{
  1076  				ID:      "someid",
  1077  				Builds:  []string{"default"},
  1078  				Formats: []string{"rpm"},
  1079  				NFPMOverridables: config.NFPMOverridables{
  1080  					PackageName: "foo",
  1081  					Contents: []*files.Content{
  1082  						{
  1083  							Source:      "testdata/testfile.txt",
  1084  							Destination: "/usr/share/testfile.txt",
  1085  						},
  1086  					},
  1087  					RPM: config.NFPMRPM{
  1088  						Signature: config.NFPMRPMSignature{
  1089  							KeyFile: "./testdata/privkey.gpg",
  1090  						},
  1091  					},
  1092  				},
  1093  			},
  1094  		},
  1095  	}, testctx.WithVersion("1.0.0"), testctx.WithCurrentTag("v1.0.0"))
  1096  	for _, goos := range []string{"linux", "darwin"} {
  1097  		for _, goarch := range []string{"amd64", "386"} {
  1098  			ctx.Artifacts.Add(&artifact.Artifact{
  1099  				Name:   "mybin",
  1100  				Path:   binPath,
  1101  				Goarch: goarch,
  1102  				Goos:   goos,
  1103  				Type:   artifact.Binary,
  1104  				Extra: map[string]interface{}{
  1105  					artifact.ExtraID: "default",
  1106  				},
  1107  			})
  1108  		}
  1109  	}
  1110  
  1111  	t.Run("no passphrase set", func(t *testing.T) {
  1112  		require.Contains(
  1113  			t,
  1114  			Pipe{}.Run(ctx).Error(),
  1115  			`key is encrypted but no passphrase was provided`,
  1116  		)
  1117  	})
  1118  
  1119  	t.Run("general passphrase set", func(t *testing.T) {
  1120  		ctx.Env = map[string]string{
  1121  			"NFPM_SOMEID_PASSPHRASE": "hunter2",
  1122  		}
  1123  		require.NoError(t, Pipe{}.Run(ctx))
  1124  	})
  1125  
  1126  	t.Run("packager specific passphrase set", func(t *testing.T) {
  1127  		ctx.Env = map[string]string{
  1128  			"NFPM_SOMEID_RPM_PASSPHRASE": "hunter2",
  1129  		}
  1130  		require.NoError(t, Pipe{}.Run(ctx))
  1131  	})
  1132  }
  1133  
  1134  func TestRPMSpecificScriptsConfig(t *testing.T) {
  1135  	folder := t.TempDir()
  1136  	dist := filepath.Join(folder, "dist")
  1137  	require.NoError(t, os.Mkdir(dist, 0o755))
  1138  	require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755))
  1139  	binPath := filepath.Join(dist, "mybin", "mybin")
  1140  	f, err := os.Create(binPath)
  1141  	require.NoError(t, err)
  1142  	require.NoError(t, f.Close())
  1143  	ctx := testctx.NewWithCfg(config.Project{
  1144  		ProjectName: "mybin",
  1145  		Dist:        dist,
  1146  		NFPMs: []config.NFPM{
  1147  			{
  1148  				ID:      "someid",
  1149  				Builds:  []string{"default"},
  1150  				Formats: []string{"rpm"},
  1151  				NFPMOverridables: config.NFPMOverridables{
  1152  					PackageName: "foo",
  1153  					RPM: config.NFPMRPM{
  1154  						Scripts: config.NFPMRPMScripts{
  1155  							PreTrans:  "/does/not/exist_pretrans.sh",
  1156  							PostTrans: "/does/not/exist_posttrans.sh",
  1157  						},
  1158  					},
  1159  				},
  1160  			},
  1161  		},
  1162  	}, testctx.WithVersion("1.0.0"), testctx.WithCurrentTag("v1.0.0"))
  1163  	for _, goos := range []string{"linux", "darwin"} {
  1164  		for _, goarch := range []string{"amd64", "386"} {
  1165  			ctx.Artifacts.Add(&artifact.Artifact{
  1166  				Name:   "mybin",
  1167  				Path:   binPath,
  1168  				Goarch: goarch,
  1169  				Goos:   goos,
  1170  				Type:   artifact.Binary,
  1171  				Extra: map[string]interface{}{
  1172  					artifact.ExtraID: "default",
  1173  				},
  1174  			})
  1175  		}
  1176  	}
  1177  
  1178  	t.Run("PreTrans script file does not exist", func(t *testing.T) {
  1179  		require.ErrorIs(t, Pipe{}.Run(ctx), os.ErrNotExist)
  1180  	})
  1181  
  1182  	t.Run("PostTrans script file does not exist", func(t *testing.T) {
  1183  		ctx.Config.NFPMs[0].RPM.Scripts.PreTrans = "testdata/testfile.txt"
  1184  		require.ErrorIs(t, Pipe{}.Run(ctx), os.ErrNotExist)
  1185  	})
  1186  
  1187  	t.Run("pretrans and posttrans scriptlets set", func(t *testing.T) {
  1188  		ctx.Config.NFPMs[0].RPM.Scripts.PreTrans = "testdata/testfile.txt"
  1189  		ctx.Config.NFPMs[0].RPM.Scripts.PostTrans = "testdata/testfile.txt"
  1190  
  1191  		require.NoError(t, Pipe{}.Run(ctx))
  1192  	})
  1193  }
  1194  
  1195  func TestAPKSpecificConfig(t *testing.T) {
  1196  	folder := t.TempDir()
  1197  	dist := filepath.Join(folder, "dist")
  1198  	require.NoError(t, os.Mkdir(dist, 0o755))
  1199  	require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755))
  1200  	binPath := filepath.Join(dist, "mybin", "mybin")
  1201  	f, err := os.Create(binPath)
  1202  	require.NoError(t, err)
  1203  	require.NoError(t, f.Close())
  1204  	ctx := testctx.NewWithCfg(config.Project{
  1205  		ProjectName: "mybin",
  1206  		Dist:        dist,
  1207  		NFPMs: []config.NFPM{
  1208  			{
  1209  				ID:         "someid",
  1210  				Maintainer: "me@me",
  1211  				Builds:     []string{"default"},
  1212  				Formats:    []string{"apk"},
  1213  				NFPMOverridables: config.NFPMOverridables{
  1214  					PackageName: "foo",
  1215  					Contents: []*files.Content{
  1216  						{
  1217  							Source:      "testdata/testfile.txt",
  1218  							Destination: "/usr/share/testfile.txt",
  1219  						},
  1220  					},
  1221  					APK: config.NFPMAPK{
  1222  						Signature: config.NFPMAPKSignature{
  1223  							KeyFile: "./testdata/rsa.priv",
  1224  						},
  1225  					},
  1226  				},
  1227  			},
  1228  		},
  1229  	}, testctx.WithVersion("1.0.0"), testctx.WithCurrentTag("v1.0.0"))
  1230  	for _, goos := range []string{"linux", "darwin"} {
  1231  		for _, goarch := range []string{"amd64", "386"} {
  1232  			ctx.Artifacts.Add(&artifact.Artifact{
  1233  				Name:   "mybin",
  1234  				Path:   binPath,
  1235  				Goarch: goarch,
  1236  				Goos:   goos,
  1237  				Type:   artifact.Binary,
  1238  				Extra: map[string]interface{}{
  1239  					artifact.ExtraID: "default",
  1240  				},
  1241  			})
  1242  		}
  1243  	}
  1244  
  1245  	t.Run("no passphrase set", func(t *testing.T) {
  1246  		require.Contains(
  1247  			t,
  1248  			Pipe{}.Run(ctx).Error(),
  1249  			`key is encrypted but no passphrase was provided`,
  1250  		)
  1251  	})
  1252  
  1253  	t.Run("general passphrase set", func(t *testing.T) {
  1254  		ctx.Env = map[string]string{
  1255  			"NFPM_SOMEID_PASSPHRASE": "hunter2",
  1256  		}
  1257  		require.NoError(t, Pipe{}.Run(ctx))
  1258  	})
  1259  
  1260  	t.Run("packager specific passphrase set", func(t *testing.T) {
  1261  		ctx.Env = map[string]string{
  1262  			"NFPM_SOMEID_APK_PASSPHRASE": "hunter2",
  1263  		}
  1264  		require.NoError(t, Pipe{}.Run(ctx))
  1265  	})
  1266  }
  1267  
  1268  func TestAPKSpecificScriptsConfig(t *testing.T) {
  1269  	folder := t.TempDir()
  1270  	dist := filepath.Join(folder, "dist")
  1271  	require.NoError(t, os.Mkdir(dist, 0o755))
  1272  	require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755))
  1273  	binPath := filepath.Join(dist, "mybin", "mybin")
  1274  	f, err := os.Create(binPath)
  1275  	require.NoError(t, err)
  1276  	require.NoError(t, f.Close())
  1277  	scripts := config.NFPMAPKScripts{
  1278  		PreUpgrade:  "/does/not/exist_preupgrade.sh",
  1279  		PostUpgrade: "/does/not/exist_postupgrade.sh",
  1280  	}
  1281  	ctx := testctx.NewWithCfg(config.Project{
  1282  		ProjectName: "mybin",
  1283  		Dist:        dist,
  1284  		NFPMs: []config.NFPM{
  1285  			{
  1286  				ID:         "someid",
  1287  				Maintainer: "me@me",
  1288  				Builds:     []string{"default"},
  1289  				Formats:    []string{"apk"},
  1290  				NFPMOverridables: config.NFPMOverridables{
  1291  					PackageName: "foo",
  1292  					Contents: []*files.Content{
  1293  						{
  1294  							Source:      "testdata/testfile.txt",
  1295  							Destination: "/usr/share/testfile.txt",
  1296  						},
  1297  					},
  1298  					APK: config.NFPMAPK{
  1299  						Scripts: scripts,
  1300  					},
  1301  				},
  1302  			},
  1303  		},
  1304  	}, testctx.WithVersion("1.0.0"), testctx.WithCurrentTag("v1.0.0"))
  1305  	for _, goos := range []string{"linux", "darwin"} {
  1306  		for _, goarch := range []string{"amd64", "386"} {
  1307  			ctx.Artifacts.Add(&artifact.Artifact{
  1308  				Name:   "mybin",
  1309  				Path:   binPath,
  1310  				Goarch: goarch,
  1311  				Goos:   goos,
  1312  				Type:   artifact.Binary,
  1313  				Extra: map[string]interface{}{
  1314  					artifact.ExtraID: "default",
  1315  				},
  1316  			})
  1317  		}
  1318  	}
  1319  
  1320  	t.Run("PreUpgrade script file does not exist", func(t *testing.T) {
  1321  		ctx.Config.NFPMs[0].APK.Scripts = scripts
  1322  		ctx.Config.NFPMs[0].APK.Scripts.PostUpgrade = "testdata/testfile.txt"
  1323  		require.ErrorIs(t, Pipe{}.Run(ctx), os.ErrNotExist)
  1324  	})
  1325  
  1326  	t.Run("PostUpgrade script file does not exist", func(t *testing.T) {
  1327  		ctx.Config.NFPMs[0].APK.Scripts = scripts
  1328  		ctx.Config.NFPMs[0].APK.Scripts.PreUpgrade = "testdata/testfile.txt"
  1329  		require.ErrorIs(t, Pipe{}.Run(ctx), os.ErrNotExist)
  1330  	})
  1331  
  1332  	t.Run("preupgrade and postupgrade scriptlets set", func(t *testing.T) {
  1333  		ctx.Config.NFPMs[0].APK.Scripts.PreUpgrade = "testdata/testfile.txt"
  1334  		ctx.Config.NFPMs[0].APK.Scripts.PostUpgrade = "testdata/testfile.txt"
  1335  
  1336  		require.NoError(t, Pipe{}.Run(ctx))
  1337  	})
  1338  }
  1339  
  1340  func TestSeveralNFPMsWithTheSameID(t *testing.T) {
  1341  	ctx := testctx.NewWithCfg(config.Project{
  1342  		NFPMs: []config.NFPM{
  1343  			{
  1344  				ID: "a",
  1345  			},
  1346  			{
  1347  				ID: "a",
  1348  			},
  1349  		},
  1350  	})
  1351  	require.EqualError(t, Pipe{}.Default(ctx), "found 2 nfpms with the ID 'a', please fix your config")
  1352  }
  1353  
  1354  func TestMeta(t *testing.T) {
  1355  	folder := t.TempDir()
  1356  	dist := filepath.Join(folder, "dist")
  1357  	require.NoError(t, os.Mkdir(dist, 0o755))
  1358  	require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755))
  1359  	binPath := filepath.Join(dist, "mybin", "mybin")
  1360  	f, err := os.Create(binPath)
  1361  	require.NoError(t, err)
  1362  	require.NoError(t, f.Close())
  1363  	ctx := testctx.NewWithCfg(config.Project{
  1364  		ProjectName: "mybin",
  1365  		Dist:        dist,
  1366  		NFPMs: []config.NFPM{
  1367  			{
  1368  				ID:          "someid",
  1369  				Bindir:      "/usr/bin",
  1370  				Builds:      []string{"default"},
  1371  				Formats:     []string{"deb", "rpm"},
  1372  				Section:     "somesection",
  1373  				Priority:    "standard",
  1374  				Description: "Some description",
  1375  				License:     "MIT",
  1376  				Maintainer:  "me@me",
  1377  				Vendor:      "asdf",
  1378  				Homepage:    "https://goreleaser.github.io",
  1379  				Meta:        true,
  1380  				NFPMOverridables: config.NFPMOverridables{
  1381  					FileNameTemplate: defaultNameTemplate + "-{{ .Release }}-{{ .Epoch }}",
  1382  					PackageName:      "foo",
  1383  					Dependencies:     []string{"make"},
  1384  					Recommends:       []string{"svn"},
  1385  					Suggests:         []string{"bzr"},
  1386  					Replaces:         []string{"fish"},
  1387  					Conflicts:        []string{"git"},
  1388  					Release:          "10",
  1389  					Epoch:            "20",
  1390  					Contents: []*files.Content{
  1391  						{
  1392  							Source:      "testdata/testfile.txt",
  1393  							Destination: "/usr/share/testfile.txt",
  1394  						},
  1395  						{
  1396  							Source:      "./testdata/testfile.txt",
  1397  							Destination: "/etc/nope.conf",
  1398  							Type:        "config",
  1399  						},
  1400  						{
  1401  							Source:      "./testdata/testfile.txt",
  1402  							Destination: "/etc/nope-rpm.conf",
  1403  							Type:        "config",
  1404  							Packager:    "rpm",
  1405  						},
  1406  						{
  1407  							Destination: "/var/log/foobar",
  1408  							Type:        "dir",
  1409  						},
  1410  					},
  1411  				},
  1412  			},
  1413  		},
  1414  	}, testctx.WithVersion("1.0.0"), testctx.WithCurrentTag("v1.0.0"))
  1415  	for _, goos := range []string{"linux", "darwin"} {
  1416  		for _, goarch := range []string{"amd64", "386"} {
  1417  			ctx.Artifacts.Add(&artifact.Artifact{
  1418  				Name:   "mybin",
  1419  				Path:   binPath,
  1420  				Goarch: goarch,
  1421  				Goos:   goos,
  1422  				Type:   artifact.Binary,
  1423  				Extra: map[string]interface{}{
  1424  					artifact.ExtraID: "default",
  1425  				},
  1426  			})
  1427  		}
  1428  	}
  1429  	require.NoError(t, Pipe{}.Run(ctx))
  1430  	packages := ctx.Artifacts.Filter(artifact.ByType(artifact.LinuxPackage)).List()
  1431  	require.Len(t, packages, 4)
  1432  	for _, pkg := range packages {
  1433  		format := pkg.Format()
  1434  		require.NotEmpty(t, format)
  1435  		require.Equal(t, pkg.Name, "foo_1.0.0_linux_"+pkg.Goarch+"-10-20."+format)
  1436  		require.Equal(t, "someid", pkg.ID())
  1437  		require.ElementsMatch(t, []string{
  1438  			"/var/log/foobar",
  1439  			"/usr/share/testfile.txt",
  1440  			"/etc/nope.conf",
  1441  			"/etc/nope-rpm.conf",
  1442  		}, destinations(artifact.ExtraOr(*pkg, extraFiles, files.Contents{})))
  1443  	}
  1444  
  1445  	require.Len(t, ctx.Config.NFPMs[0].Contents, 4, "should not modify the config file list")
  1446  }
  1447  
  1448  func TestSkipSign(t *testing.T) {
  1449  	folder := t.TempDir()
  1450  	dist := filepath.Join(folder, "dist")
  1451  	require.NoError(t, os.Mkdir(dist, 0o755))
  1452  	require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755))
  1453  	binPath := filepath.Join(dist, "mybin", "mybin")
  1454  	_, err := os.Create(binPath)
  1455  	require.NoError(t, err)
  1456  	ctx := testctx.NewWithCfg(config.Project{
  1457  		ProjectName: "mybin",
  1458  		Dist:        dist,
  1459  		NFPMs: []config.NFPM{
  1460  			{
  1461  				ID:      "someid",
  1462  				Builds:  []string{"default"},
  1463  				Formats: []string{"deb", "rpm", "apk"},
  1464  				NFPMOverridables: config.NFPMOverridables{
  1465  					PackageName:      "foo",
  1466  					FileNameTemplate: defaultNameTemplate,
  1467  					Contents: []*files.Content{
  1468  						{
  1469  							Source:      "testdata/testfile.txt",
  1470  							Destination: "/usr/share/testfile.txt",
  1471  						},
  1472  					},
  1473  					Deb: config.NFPMDeb{
  1474  						Signature: config.NFPMDebSignature{
  1475  							KeyFile: "/does/not/exist.gpg",
  1476  						},
  1477  					},
  1478  					RPM: config.NFPMRPM{
  1479  						Signature: config.NFPMRPMSignature{
  1480  							KeyFile: "/does/not/exist.gpg",
  1481  						},
  1482  					},
  1483  					APK: config.NFPMAPK{
  1484  						Signature: config.NFPMAPKSignature{
  1485  							KeyFile: "/does/not/exist.gpg",
  1486  						},
  1487  					},
  1488  				},
  1489  			},
  1490  		},
  1491  	}, testctx.WithVersion("1.0.0"), testctx.WithCurrentTag("v1.0.0"))
  1492  	for _, goos := range []string{"linux", "darwin"} {
  1493  		for _, goarch := range []string{"amd64", "386"} {
  1494  			ctx.Artifacts.Add(&artifact.Artifact{
  1495  				Name:   "mybin",
  1496  				Path:   binPath,
  1497  				Goarch: goarch,
  1498  				Goos:   goos,
  1499  				Type:   artifact.Binary,
  1500  				Extra: map[string]interface{}{
  1501  					artifact.ExtraID: "default",
  1502  				},
  1503  			})
  1504  		}
  1505  	}
  1506  
  1507  	t.Run("skip sign not set", func(t *testing.T) {
  1508  		// TODO: once https://github.com/goreleaser/nfpm/pull/630 is released,
  1509  		// use require.ErrorIs() here.
  1510  		require.Error(t, Pipe{}.Run(ctx))
  1511  	})
  1512  
  1513  	t.Run("skip sign set", func(t *testing.T) {
  1514  		skips.Set(ctx, skips.Sign)
  1515  		require.NoError(t, Pipe{}.Run(ctx))
  1516  	})
  1517  }
  1518  
  1519  func TestBinDirTemplating(t *testing.T) {
  1520  	folder := t.TempDir()
  1521  	dist := filepath.Join(folder, "dist")
  1522  	require.NoError(t, os.Mkdir(dist, 0o755))
  1523  	require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755))
  1524  	binPath := filepath.Join(dist, "mybin", "mybin")
  1525  	f, err := os.Create(binPath)
  1526  	require.NoError(t, err)
  1527  	require.NoError(t, f.Close())
  1528  	ctx := testctx.NewWithCfg(config.Project{
  1529  		ProjectName: "mybin",
  1530  		Dist:        dist,
  1531  		Env: []string{
  1532  			"PRO=pro",
  1533  			"DESC=templates",
  1534  			"MAINTAINER=me@me",
  1535  		},
  1536  		NFPMs: []config.NFPM{
  1537  			{
  1538  				ID: "someid",
  1539  				// Bindir should pass through the template engine
  1540  				Bindir:      "/usr/lib/{{ .Env.PRO }}/nagios/plugins",
  1541  				Builds:      []string{"default"},
  1542  				Formats:     []string{"rpm"},
  1543  				Section:     "somesection",
  1544  				Priority:    "standard",
  1545  				Description: "Some description with {{ .Env.DESC }}",
  1546  				License:     "MIT",
  1547  				Maintainer:  "{{ .Env.MAINTAINER }}",
  1548  				Vendor:      "asdf",
  1549  				Homepage:    "https://goreleaser.com/{{ .Env.PRO }}",
  1550  				NFPMOverridables: config.NFPMOverridables{
  1551  					PackageName: "foo",
  1552  				},
  1553  			},
  1554  		},
  1555  	}, testctx.WithVersion("1.0.0"), testctx.WithCurrentTag("v1.0.0"))
  1556  	for _, goos := range []string{"linux"} {
  1557  		for _, goarch := range []string{"amd64", "386"} {
  1558  			ctx.Artifacts.Add(&artifact.Artifact{
  1559  				Name:   "subdir/mybin",
  1560  				Path:   binPath,
  1561  				Goarch: goarch,
  1562  				Goos:   goos,
  1563  				Type:   artifact.Binary,
  1564  				Extra: map[string]interface{}{
  1565  					artifact.ExtraID: "default",
  1566  				},
  1567  			})
  1568  		}
  1569  	}
  1570  	require.NoError(t, Pipe{}.Run(ctx))
  1571  	packages := ctx.Artifacts.Filter(artifact.ByType(artifact.LinuxPackage)).List()
  1572  
  1573  	for _, pkg := range packages {
  1574  		format := pkg.Format()
  1575  		require.NotEmpty(t, format)
  1576  		// the final binary should contain the evaluated bindir (after template eval)
  1577  		require.ElementsMatch(t, []string{
  1578  			"/usr/lib/pro/nagios/plugins/subdir/mybin",
  1579  		}, destinations(artifact.ExtraOr(*pkg, extraFiles, files.Contents{})))
  1580  	}
  1581  }
  1582  
  1583  func TestSkip(t *testing.T) {
  1584  	t.Run("skip", func(t *testing.T) {
  1585  		require.True(t, Pipe{}.Skip(testctx.New()))
  1586  	})
  1587  	t.Run("skip flag", func(t *testing.T) {
  1588  		ctx := testctx.NewWithCfg(config.Project{
  1589  			NFPMs: []config.NFPM{
  1590  				{},
  1591  			},
  1592  		}, testctx.Skip(skips.NFPM))
  1593  		require.True(t, Pipe{}.Skip(ctx))
  1594  	})
  1595  
  1596  	t.Run("dont skip", func(t *testing.T) {
  1597  		ctx := testctx.NewWithCfg(config.Project{
  1598  			NFPMs: []config.NFPM{
  1599  				{},
  1600  			},
  1601  		})
  1602  		require.False(t, Pipe{}.Skip(ctx))
  1603  	})
  1604  }
  1605  
  1606  func TestTemplateExt(t *testing.T) {
  1607  	ctx := testctx.NewWithCfg(config.Project{
  1608  		Dist: t.TempDir(),
  1609  		NFPMs: []config.NFPM{
  1610  			{
  1611  				NFPMOverridables: config.NFPMOverridables{
  1612  					FileNameTemplate: "a_{{ .ConventionalExtension }}_b",
  1613  					PackageName:      "foo",
  1614  				},
  1615  				Meta:       true,
  1616  				Maintainer: "foo@bar",
  1617  				Formats:    []string{"deb", "rpm", "termux.deb", "apk", "archlinux"},
  1618  				Builds:     []string{"default"},
  1619  			},
  1620  		},
  1621  	})
  1622  	ctx.Artifacts.Add(&artifact.Artifact{
  1623  		Name:   "mybin",
  1624  		Goos:   "linux",
  1625  		Goarch: "amd64",
  1626  		Type:   artifact.Binary,
  1627  		Extra: map[string]interface{}{
  1628  			artifact.ExtraID: "default",
  1629  		},
  1630  	})
  1631  	require.NoError(t, Pipe{}.Run(ctx))
  1632  
  1633  	packages := ctx.Artifacts.Filter(artifact.ByType(artifact.LinuxPackage)).List()
  1634  	require.Len(t, packages, 5)
  1635  	names := make([]string, 0, 5)
  1636  	for _, p := range packages {
  1637  		names = append(names, p.Name)
  1638  	}
  1639  
  1640  	require.ElementsMatch(t, []string{
  1641  		"a_.apk_b.apk",
  1642  		"a_.deb_b.deb",
  1643  		"a_.rpm_b.rpm",
  1644  		"a_.termux.deb_b.termux.deb",
  1645  		"a_.pkg.tar.zst_b.pkg.tar.zst",
  1646  	}, names)
  1647  }
  1648  
  1649  func sources(contents files.Contents) []string {
  1650  	result := make([]string, 0, len(contents))
  1651  	for _, f := range contents {
  1652  		if f.Source == "" {
  1653  			continue
  1654  		}
  1655  		result = append(result, f.Source)
  1656  	}
  1657  	return result
  1658  }