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 }