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