github.com/ahmet2mir/goreleaser@v0.180.3-0.20210927151101-8e5ee5a9b8c5/internal/pipe/nfpm/nfpm_test.go (about) 1 package nfpm 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path/filepath" 7 "runtime" 8 "testing" 9 10 "github.com/goreleaser/goreleaser/internal/artifact" 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/files" 15 "github.com/stretchr/testify/require" 16 ) 17 18 func TestDescription(t *testing.T) { 19 require.NotEmpty(t, Pipe{}.String()) 20 } 21 22 func TestRunPipeNoFormats(t *testing.T) { 23 ctx := &context.Context{ 24 Version: "1.0.0", 25 Git: context.GitInfo{ 26 CurrentTag: "v1.0.0", 27 }, 28 Config: config.Project{ 29 NFPMs: []config.NFPM{ 30 {}, 31 }, 32 }, 33 Parallelism: runtime.NumCPU(), 34 } 35 require.NoError(t, Pipe{}.Default(ctx)) 36 testlib.AssertSkipped(t, Pipe{}.Run(ctx)) 37 } 38 39 func TestRunPipeInvalidFormat(t *testing.T) { 40 ctx := context.New(config.Project{ 41 ProjectName: "nope", 42 NFPMs: []config.NFPM{ 43 { 44 Bindir: "/usr/bin", 45 Formats: []string{"nope"}, 46 Builds: []string{"foo"}, 47 NFPMOverridables: config.NFPMOverridables{ 48 PackageName: "foo", 49 FileNameTemplate: defaultNameTemplate, 50 }, 51 }, 52 }, 53 }) 54 ctx.Version = "1.2.3" 55 ctx.Git = context.GitInfo{ 56 CurrentTag: "v1.2.3", 57 } 58 for _, goos := range []string{"linux", "darwin"} { 59 for _, goarch := range []string{"amd64", "386"} { 60 ctx.Artifacts.Add(&artifact.Artifact{ 61 Name: "mybin", 62 Path: "testdata/testfile.txt", 63 Goarch: goarch, 64 Goos: goos, 65 Type: artifact.Binary, 66 Extra: map[string]interface{}{ 67 "ID": "foo", 68 }, 69 }) 70 } 71 } 72 require.Contains(t, Pipe{}.Run(ctx).Error(), `no packager registered for the format nope`) 73 } 74 75 func TestRunPipe(t *testing.T) { 76 folder := t.TempDir() 77 dist := filepath.Join(folder, "dist") 78 require.NoError(t, os.Mkdir(dist, 0o755)) 79 require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755)) 80 binPath := filepath.Join(dist, "mybin", "mybin") 81 f, err := os.Create(binPath) 82 require.NoError(t, err) 83 require.NoError(t, f.Close()) 84 ctx := context.New(config.Project{ 85 ProjectName: "mybin", 86 Dist: dist, 87 Env: []string{ 88 "PRO=pro", 89 "DESC=templates", 90 }, 91 NFPMs: []config.NFPM{ 92 { 93 ID: "someid", 94 Bindir: "/usr/bin", 95 Builds: []string{"default"}, 96 Formats: []string{"deb", "rpm", "apk"}, 97 Section: "somesection", 98 Priority: "standard", 99 Description: "Some description with {{ .Env.DESC }}", 100 License: "MIT", 101 Maintainer: "me@me", 102 Vendor: "asdf", 103 Homepage: "https://goreleaser.com/{{ .Env.PRO }}", 104 NFPMOverridables: config.NFPMOverridables{ 105 FileNameTemplate: defaultNameTemplate + "-{{ .Release }}-{{ .Epoch }}", 106 PackageName: "foo", 107 Dependencies: []string{"make"}, 108 Recommends: []string{"svn"}, 109 Suggests: []string{"bzr"}, 110 Replaces: []string{"fish"}, 111 Conflicts: []string{"git"}, 112 EmptyFolders: []string{"/var/log/foobar"}, 113 Release: "10", 114 Epoch: "20", 115 Contents: []*files.Content{ 116 { 117 Source: "./testdata/testfile.txt", 118 Destination: "/usr/share/testfile.txt", 119 }, 120 { 121 Source: "./testdata/testfile.txt", 122 Destination: "/etc/nope.conf", 123 Type: "config", 124 }, 125 { 126 Source: "./testdata/testfile.txt", 127 Destination: "/etc/nope-rpm.conf", 128 Type: "config", 129 Packager: "rpm", 130 }, 131 { 132 Source: "/etc/nope.conf", 133 Destination: "/etc/nope2.conf", 134 Type: "symlink", 135 }, 136 { 137 Source: "./testdata/testfile-{{ .Arch }}.txt", 138 Destination: "/etc/nope3_{{ .ProjectName }}.conf", 139 }, 140 }, 141 Replacements: map[string]string{ 142 "linux": "Tux", 143 }, 144 }, 145 }, 146 }, 147 }) 148 ctx.Version = "1.0.0" 149 ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"} 150 for _, goos := range []string{"linux", "darwin"} { 151 for _, goarch := range []string{"amd64", "386"} { 152 ctx.Artifacts.Add(&artifact.Artifact{ 153 Name: "subdir/mybin", 154 Path: binPath, 155 Goarch: goarch, 156 Goos: goos, 157 Type: artifact.Binary, 158 Extra: map[string]interface{}{ 159 "ID": "default", 160 }, 161 }) 162 } 163 } 164 require.NoError(t, Pipe{}.Run(ctx)) 165 packages := ctx.Artifacts.Filter(artifact.ByType(artifact.LinuxPackage)).List() 166 require.Len(t, packages, 6) 167 for _, pkg := range packages { 168 format := pkg.ExtraOr("Format", "").(string) 169 require.NotEmpty(t, format) 170 require.Equal(t, pkg.Name, "foo_1.0.0_Tux_"+pkg.Goarch+"-10-20."+format) 171 require.Equal(t, pkg.ExtraOr("ID", ""), "someid") 172 require.ElementsMatch(t, []string{ 173 "./testdata/testfile.txt", 174 "./testdata/testfile.txt", 175 "./testdata/testfile.txt", 176 "/etc/nope.conf", 177 "./testdata/testfile-" + pkg.Goarch + ".txt", 178 binPath, 179 }, sources(pkg.ExtraOr("Files", files.Contents{}).(files.Contents))) 180 require.ElementsMatch(t, []string{ 181 "/usr/share/testfile.txt", 182 "/etc/nope.conf", 183 "/etc/nope-rpm.conf", 184 "/etc/nope2.conf", 185 "/etc/nope3_mybin.conf", 186 "/usr/bin/subdir/mybin", 187 }, destinations(pkg.ExtraOr("Files", files.Contents{}).(files.Contents))) 188 } 189 require.Len(t, ctx.Config.NFPMs[0].Contents, 5, "should not modify the config file list") 190 } 191 192 func TestInvalidTemplate(t *testing.T) { 193 makeCtx := func() *context.Context { 194 ctx := &context.Context{ 195 Version: "1.2.3", 196 Parallelism: runtime.NumCPU(), 197 Artifacts: artifact.New(), 198 Config: config.Project{ 199 NFPMs: []config.NFPM{ 200 { 201 Formats: []string{"deb"}, 202 Builds: []string{"default"}, 203 }, 204 }, 205 }, 206 } 207 ctx.Artifacts.Add(&artifact.Artifact{ 208 Name: "mybin", 209 Goos: "linux", 210 Goarch: "amd64", 211 Type: artifact.Binary, 212 Extra: map[string]interface{}{ 213 "ID": "default", 214 }, 215 }) 216 return ctx 217 } 218 219 t.Run("filename_template", func(t *testing.T) { 220 ctx := makeCtx() 221 ctx.Config.NFPMs[0].NFPMOverridables = config.NFPMOverridables{ 222 FileNameTemplate: "{{.Foo}", 223 } 224 require.Contains(t, Pipe{}.Run(ctx).Error(), `template: tmpl:1: unexpected "}" in operand`) 225 }) 226 227 t.Run("source", func(t *testing.T) { 228 ctx := makeCtx() 229 ctx.Config.NFPMs[0].NFPMOverridables = config.NFPMOverridables{ 230 Contents: files.Contents{ 231 { 232 Source: "{{ .NOPE_SOURCE }}", 233 Destination: "/foo", 234 }, 235 }, 236 } 237 require.Contains(t, Pipe{}.Run(ctx).Error(), `template: tmpl:1:3: executing "tmpl" at <.NOPE_SOURCE>: map has no entry for key "NOPE_SOURCE"`) 238 }) 239 240 t.Run("target", func(t *testing.T) { 241 ctx := makeCtx() 242 ctx.Config.NFPMs[0].NFPMOverridables = config.NFPMOverridables{ 243 Contents: files.Contents{ 244 { 245 Source: "./testdata/testfile.txt", 246 Destination: "{{ .NOPE_TARGET }}", 247 }, 248 }, 249 } 250 require.Contains(t, Pipe{}.Run(ctx).Error(), `template: tmpl:1:3: executing "tmpl" at <.NOPE_TARGET>: map has no entry for key "NOPE_TARGET"`) 251 }) 252 253 t.Run("description", func(t *testing.T) { 254 ctx := makeCtx() 255 ctx.Config.NFPMs[0].Description = "{{ .NOPE_DESC }}" 256 require.Contains(t, Pipe{}.Run(ctx).Error(), `template: tmpl:1:3: executing "tmpl" at <.NOPE_DESC>: map has no entry for key "NOPE_DESC"`) 257 }) 258 259 t.Run("homepage", func(t *testing.T) { 260 ctx := makeCtx() 261 ctx.Config.NFPMs[0].Homepage = "{{ .NOPE_HOMEPAGE }}" 262 require.Contains(t, Pipe{}.Run(ctx).Error(), `template: tmpl:1:3: executing "tmpl" at <.NOPE_HOMEPAGE>: map has no entry for key "NOPE_HOMEPAGE"`) 263 }) 264 265 t.Run("deb key file", func(t *testing.T) { 266 ctx := makeCtx() 267 ctx.Config.NFPMs[0].Deb.Signature.KeyFile = "{{ .NOPE_KEY_FILE }}" 268 require.Contains(t, Pipe{}.Run(ctx).Error(), `template: tmpl:1:3: executing "tmpl" at <.NOPE_KEY_FILE>: map has no entry for key "NOPE_KEY_FILE"`) 269 }) 270 271 t.Run("rpm key file", func(t *testing.T) { 272 ctx := makeCtx() 273 ctx.Config.NFPMs[0].RPM.Signature.KeyFile = "{{ .NOPE_KEY_FILE }}" 274 require.Contains(t, Pipe{}.Run(ctx).Error(), `template: tmpl:1:3: executing "tmpl" at <.NOPE_KEY_FILE>: map has no entry for key "NOPE_KEY_FILE"`) 275 }) 276 277 t.Run("apk key file", func(t *testing.T) { 278 ctx := makeCtx() 279 ctx.Config.NFPMs[0].APK.Signature.KeyFile = "{{ .NOPE_KEY_FILE }}" 280 require.Contains(t, Pipe{}.Run(ctx).Error(), `template: tmpl:1:3: executing "tmpl" at <.NOPE_KEY_FILE>: map has no entry for key "NOPE_KEY_FILE"`) 281 }) 282 283 t.Run("bindir", func(t *testing.T) { 284 ctx := makeCtx() 285 ctx.Config.NFPMs[0].Bindir = "/usr/local/{{ .NOPE }}" 286 require.Contains(t, Pipe{}.Run(ctx).Error(), `template: tmpl:1:14: executing "tmpl" at <.NOPE>: map has no entry for key "NOPE"`) 287 }) 288 } 289 290 func TestRunPipeInvalidContentsSourceTemplate(t *testing.T) { 291 ctx := &context.Context{ 292 Parallelism: runtime.NumCPU(), 293 Artifacts: artifact.New(), 294 Config: config.Project{ 295 NFPMs: []config.NFPM{ 296 { 297 NFPMOverridables: config.NFPMOverridables{ 298 PackageName: "foo", 299 Contents: []*files.Content{ 300 { 301 Source: "{{.asdsd}", 302 Destination: "testfile", 303 }, 304 }, 305 }, 306 Formats: []string{"deb"}, 307 Builds: []string{"default"}, 308 }, 309 }, 310 }, 311 } 312 ctx.Artifacts.Add(&artifact.Artifact{ 313 Name: "mybin", 314 Goos: "linux", 315 Goarch: "amd64", 316 Type: artifact.Binary, 317 Extra: map[string]interface{}{ 318 "ID": "default", 319 }, 320 }) 321 require.EqualError(t, Pipe{}.Run(ctx), `template: tmpl:1: unexpected "}" in operand`) 322 } 323 324 func TestNoBuildsFound(t *testing.T) { 325 ctx := &context.Context{ 326 Parallelism: runtime.NumCPU(), 327 Artifacts: artifact.New(), 328 Config: config.Project{ 329 NFPMs: []config.NFPM{ 330 { 331 Formats: []string{"deb"}, 332 Builds: []string{"nope"}, 333 }, 334 }, 335 }, 336 } 337 ctx.Artifacts.Add(&artifact.Artifact{ 338 Name: "mybin", 339 Goos: "linux", 340 Goarch: "amd64", 341 Type: artifact.Binary, 342 Extra: map[string]interface{}{ 343 "ID": "default", 344 }, 345 }) 346 require.EqualError(t, Pipe{}.Run(ctx), `no linux binaries found for builds [nope]`) 347 } 348 349 func TestCreateFileDoesntExist(t *testing.T) { 350 folder := t.TempDir() 351 dist := filepath.Join(folder, "dist") 352 require.NoError(t, os.Mkdir(dist, 0o755)) 353 require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755)) 354 ctx := context.New(config.Project{ 355 Dist: dist, 356 ProjectName: "asd", 357 NFPMs: []config.NFPM{ 358 { 359 Formats: []string{"deb", "rpm"}, 360 Builds: []string{"default"}, 361 NFPMOverridables: config.NFPMOverridables{ 362 PackageName: "foo", 363 Contents: []*files.Content{ 364 { 365 Source: "testdata/testfile.txt", 366 Destination: "/var/lib/test/testfile.txt", 367 }, 368 }, 369 }, 370 }, 371 }, 372 }) 373 ctx.Version = "1.2.3" 374 ctx.Git = context.GitInfo{ 375 CurrentTag: "v1.2.3", 376 } 377 ctx.Artifacts.Add(&artifact.Artifact{ 378 Name: "mybin", 379 Path: filepath.Join(dist, "mybin", "mybin"), 380 Goos: "linux", 381 Goarch: "amd64", 382 Type: artifact.Binary, 383 Extra: map[string]interface{}{ 384 "ID": "default", 385 }, 386 }) 387 require.Contains(t, Pipe{}.Run(ctx).Error(), `dist/mybin/mybin": file does not exist`) 388 } 389 390 func TestInvalidConfig(t *testing.T) { 391 folder := t.TempDir() 392 dist := filepath.Join(folder, "dist") 393 require.NoError(t, os.Mkdir(dist, 0o755)) 394 require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755)) 395 ctx := context.New(config.Project{ 396 Dist: dist, 397 NFPMs: []config.NFPM{ 398 { 399 Formats: []string{"deb"}, 400 Builds: []string{"default"}, 401 }, 402 }, 403 }) 404 ctx.Git.CurrentTag = "v1.2.3" 405 ctx.Version = "v1.2.3" 406 ctx.Artifacts.Add(&artifact.Artifact{ 407 Name: "mybin", 408 Path: filepath.Join(dist, "mybin", "mybin"), 409 Goos: "linux", 410 Goarch: "amd64", 411 Type: artifact.Binary, 412 Extra: map[string]interface{}{ 413 "ID": "default", 414 }, 415 }) 416 require.Contains(t, Pipe{}.Run(ctx).Error(), `invalid nfpm config: package name must be provided`) 417 } 418 419 func TestDefault(t *testing.T) { 420 ctx := &context.Context{ 421 Config: config.Project{ 422 ProjectName: "foobar", 423 NFPMs: []config.NFPM{ 424 {}, 425 }, 426 Builds: []config.Build{ 427 {ID: "foo"}, 428 {ID: "bar"}, 429 }, 430 }, 431 } 432 require.NoError(t, Pipe{}.Default(ctx)) 433 require.Equal(t, "/usr/local/bin", ctx.Config.NFPMs[0].Bindir) 434 require.Equal(t, []string{"foo", "bar"}, ctx.Config.NFPMs[0].Builds) 435 require.Equal(t, defaultNameTemplate, ctx.Config.NFPMs[0].FileNameTemplate) 436 require.Equal(t, ctx.Config.ProjectName, ctx.Config.NFPMs[0].PackageName) 437 } 438 439 func TestDefaultSet(t *testing.T) { 440 ctx := &context.Context{ 441 Config: config.Project{ 442 Builds: []config.Build{ 443 {ID: "foo"}, 444 {ID: "bar"}, 445 }, 446 NFPMs: []config.NFPM{ 447 { 448 Builds: []string{"foo"}, 449 Bindir: "/bin", 450 NFPMOverridables: config.NFPMOverridables{ 451 FileNameTemplate: "foo", 452 }, 453 }, 454 }, 455 }, 456 } 457 require.NoError(t, Pipe{}.Default(ctx)) 458 require.Equal(t, "/bin", ctx.Config.NFPMs[0].Bindir) 459 require.Equal(t, "foo", ctx.Config.NFPMs[0].FileNameTemplate) 460 require.Equal(t, []string{"foo"}, ctx.Config.NFPMs[0].Builds) 461 require.Equal(t, config.NFPMRPMScripts{}, ctx.Config.NFPMs[0].RPM.Scripts) 462 } 463 464 func TestOverrides(t *testing.T) { 465 ctx := &context.Context{ 466 Config: config.Project{ 467 NFPMs: []config.NFPM{ 468 { 469 Bindir: "/bin", 470 NFPMOverridables: config.NFPMOverridables{ 471 FileNameTemplate: "foo", 472 }, 473 Overrides: map[string]config.NFPMOverridables{ 474 "deb": { 475 FileNameTemplate: "bar", 476 }, 477 }, 478 }, 479 }, 480 }, 481 } 482 require.NoError(t, Pipe{}.Default(ctx)) 483 merged, err := mergeOverrides(ctx.Config.NFPMs[0], "deb") 484 require.NoError(t, err) 485 require.Equal(t, "/bin", ctx.Config.NFPMs[0].Bindir) 486 require.Equal(t, "foo", ctx.Config.NFPMs[0].FileNameTemplate) 487 require.Equal(t, "bar", ctx.Config.NFPMs[0].Overrides["deb"].FileNameTemplate) 488 require.Equal(t, "bar", merged.FileNameTemplate) 489 } 490 491 func TestDebSpecificConfig(t *testing.T) { 492 folder := t.TempDir() 493 dist := filepath.Join(folder, "dist") 494 require.NoError(t, os.Mkdir(dist, 0o755)) 495 require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755)) 496 binPath := filepath.Join(dist, "mybin", "mybin") 497 f, err := os.Create(binPath) 498 require.NoError(t, err) 499 require.NoError(t, f.Close()) 500 ctx := context.New(config.Project{ 501 ProjectName: "mybin", 502 Dist: dist, 503 NFPMs: []config.NFPM{ 504 { 505 ID: "someid", 506 Builds: []string{"default"}, 507 Formats: []string{"deb"}, 508 NFPMOverridables: config.NFPMOverridables{ 509 PackageName: "foo", 510 Contents: []*files.Content{ 511 { 512 Source: "testdata/testfile.txt", 513 Destination: "/usr/share/testfile.txt", 514 }, 515 }, 516 Deb: config.NFPMDeb{ 517 Signature: config.NFPMDebSignature{ 518 KeyFile: "./testdata/privkey.gpg", 519 }, 520 }, 521 }, 522 }, 523 }, 524 }) 525 ctx.Version = "1.0.0" 526 ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"} 527 for _, goos := range []string{"linux", "darwin"} { 528 for _, goarch := range []string{"amd64", "386"} { 529 ctx.Artifacts.Add(&artifact.Artifact{ 530 Name: "mybin", 531 Path: binPath, 532 Goarch: goarch, 533 Goos: goos, 534 Type: artifact.Binary, 535 Extra: map[string]interface{}{ 536 "ID": "default", 537 }, 538 }) 539 } 540 } 541 542 t.Run("no passphrase set", func(t *testing.T) { 543 require.Contains( 544 t, 545 Pipe{}.Run(ctx).Error(), 546 `key is encrypted but no passphrase was provided`, 547 ) 548 }) 549 550 t.Run("general passphrase set", func(t *testing.T) { 551 ctx.Env = map[string]string{ 552 "NFPM_SOMEID_PASSPHRASE": "hunter2", 553 } 554 require.NoError(t, Pipe{}.Run(ctx)) 555 }) 556 557 t.Run("packager specific passphrase set", func(t *testing.T) { 558 ctx.Env = map[string]string{ 559 "NFPM_SOMEID_DEB_PASSPHRASE": "hunter2", 560 } 561 require.NoError(t, Pipe{}.Run(ctx)) 562 }) 563 } 564 565 func TestRPMSpecificConfig(t *testing.T) { 566 folder := t.TempDir() 567 dist := filepath.Join(folder, "dist") 568 require.NoError(t, os.Mkdir(dist, 0o755)) 569 require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755)) 570 binPath := filepath.Join(dist, "mybin", "mybin") 571 f, err := os.Create(binPath) 572 require.NoError(t, err) 573 require.NoError(t, f.Close()) 574 ctx := context.New(config.Project{ 575 ProjectName: "mybin", 576 Dist: dist, 577 NFPMs: []config.NFPM{ 578 { 579 ID: "someid", 580 Builds: []string{"default"}, 581 Formats: []string{"rpm"}, 582 NFPMOverridables: config.NFPMOverridables{ 583 PackageName: "foo", 584 Contents: []*files.Content{ 585 { 586 Source: "testdata/testfile.txt", 587 Destination: "/usr/share/testfile.txt", 588 }, 589 }, 590 RPM: config.NFPMRPM{ 591 Signature: config.NFPMRPMSignature{ 592 KeyFile: "./testdata/privkey.gpg", 593 }, 594 }, 595 }, 596 }, 597 }, 598 }) 599 ctx.Version = "1.0.0" 600 ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"} 601 for _, goos := range []string{"linux", "darwin"} { 602 for _, goarch := range []string{"amd64", "386"} { 603 ctx.Artifacts.Add(&artifact.Artifact{ 604 Name: "mybin", 605 Path: binPath, 606 Goarch: goarch, 607 Goos: goos, 608 Type: artifact.Binary, 609 Extra: map[string]interface{}{ 610 "ID": "default", 611 }, 612 }) 613 } 614 } 615 616 t.Run("no passphrase set", func(t *testing.T) { 617 require.Contains( 618 t, 619 Pipe{}.Run(ctx).Error(), 620 `key is encrypted but no passphrase was provided`, 621 ) 622 }) 623 624 t.Run("general passphrase set", func(t *testing.T) { 625 ctx.Env = map[string]string{ 626 "NFPM_SOMEID_PASSPHRASE": "hunter2", 627 } 628 require.NoError(t, Pipe{}.Run(ctx)) 629 }) 630 631 t.Run("packager specific passphrase set", func(t *testing.T) { 632 ctx.Env = map[string]string{ 633 "NFPM_SOMEID_RPM_PASSPHRASE": "hunter2", 634 } 635 require.NoError(t, Pipe{}.Run(ctx)) 636 }) 637 } 638 639 func TestRPMSpecificScriptsConfig(t *testing.T) { 640 folder := t.TempDir() 641 dist := filepath.Join(folder, "dist") 642 require.NoError(t, os.Mkdir(dist, 0o755)) 643 require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755)) 644 binPath := filepath.Join(dist, "mybin", "mybin") 645 f, err := os.Create(binPath) 646 require.NoError(t, err) 647 require.NoError(t, f.Close()) 648 ctx := context.New(config.Project{ 649 ProjectName: "mybin", 650 Dist: dist, 651 NFPMs: []config.NFPM{ 652 { 653 ID: "someid", 654 Builds: []string{"default"}, 655 Formats: []string{"rpm"}, 656 NFPMOverridables: config.NFPMOverridables{ 657 PackageName: "foo", 658 RPM: config.NFPMRPM{ 659 Scripts: config.NFPMRPMScripts{ 660 PreTrans: "/does/not/exist_pretrans.sh", 661 PostTrans: "/does/not/exist_posttrans.sh", 662 }, 663 }, 664 }, 665 }, 666 }, 667 }) 668 ctx.Version = "1.0.0" 669 ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"} 670 for _, goos := range []string{"linux", "darwin"} { 671 for _, goarch := range []string{"amd64", "386"} { 672 ctx.Artifacts.Add(&artifact.Artifact{ 673 Name: "mybin", 674 Path: binPath, 675 Goarch: goarch, 676 Goos: goos, 677 Type: artifact.Binary, 678 Extra: map[string]interface{}{ 679 "ID": "default", 680 }, 681 }) 682 } 683 } 684 685 t.Run("PreTrans script file does not exist", func(t *testing.T) { 686 require.Contains( 687 t, 688 Pipe{}.Run(ctx).Error(), 689 `nfpm failed: open /does/not/exist_pretrans.sh: no such file or directory`, 690 ) 691 }) 692 693 t.Run("PostTrans script file does not exist", func(t *testing.T) { 694 ctx.Config.NFPMs[0].RPM.Scripts.PreTrans = "testdata/testfile.txt" 695 696 require.Contains( 697 t, 698 Pipe{}.Run(ctx).Error(), 699 `nfpm failed: open /does/not/exist_posttrans.sh: no such file or directory`, 700 ) 701 }) 702 703 t.Run("pretrans and posttrans scriptlets set", func(t *testing.T) { 704 ctx.Config.NFPMs[0].RPM.Scripts.PreTrans = "testdata/testfile.txt" 705 ctx.Config.NFPMs[0].RPM.Scripts.PostTrans = "testdata/testfile.txt" 706 707 require.NoError(t, Pipe{}.Run(ctx)) 708 }) 709 } 710 711 func TestAPKSpecificConfig(t *testing.T) { 712 folder := t.TempDir() 713 dist := filepath.Join(folder, "dist") 714 require.NoError(t, os.Mkdir(dist, 0o755)) 715 require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755)) 716 binPath := filepath.Join(dist, "mybin", "mybin") 717 f, err := os.Create(binPath) 718 require.NoError(t, err) 719 require.NoError(t, f.Close()) 720 ctx := context.New(config.Project{ 721 ProjectName: "mybin", 722 Dist: dist, 723 NFPMs: []config.NFPM{ 724 { 725 ID: "someid", 726 Maintainer: "me@me", 727 Builds: []string{"default"}, 728 Formats: []string{"apk"}, 729 NFPMOverridables: config.NFPMOverridables{ 730 PackageName: "foo", 731 Contents: []*files.Content{ 732 { 733 Source: "testdata/testfile.txt", 734 Destination: "/usr/share/testfile.txt", 735 }, 736 }, 737 APK: config.NFPMAPK{ 738 Signature: config.NFPMAPKSignature{ 739 KeyFile: "./testdata/rsa.priv", 740 }, 741 }, 742 }, 743 }, 744 }, 745 }) 746 ctx.Version = "1.0.0" 747 ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"} 748 for _, goos := range []string{"linux", "darwin"} { 749 for _, goarch := range []string{"amd64", "386"} { 750 ctx.Artifacts.Add(&artifact.Artifact{ 751 Name: "mybin", 752 Path: binPath, 753 Goarch: goarch, 754 Goos: goos, 755 Type: artifact.Binary, 756 Extra: map[string]interface{}{ 757 "ID": "default", 758 }, 759 }) 760 } 761 } 762 763 t.Run("no passphrase set", func(t *testing.T) { 764 require.Contains( 765 t, 766 Pipe{}.Run(ctx).Error(), 767 `key is encrypted but no passphrase was provided`, 768 ) 769 }) 770 771 t.Run("general passphrase set", func(t *testing.T) { 772 ctx.Env = map[string]string{ 773 "NFPM_SOMEID_PASSPHRASE": "hunter2", 774 } 775 require.NoError(t, Pipe{}.Run(ctx)) 776 }) 777 778 t.Run("packager specific passphrase set", func(t *testing.T) { 779 ctx.Env = map[string]string{ 780 "NFPM_SOMEID_APK_PASSPHRASE": "hunter2", 781 } 782 require.NoError(t, Pipe{}.Run(ctx)) 783 }) 784 } 785 786 func TestAPKSpecificScriptsConfig(t *testing.T) { 787 folder := t.TempDir() 788 dist := filepath.Join(folder, "dist") 789 require.NoError(t, os.Mkdir(dist, 0o755)) 790 require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755)) 791 binPath := filepath.Join(dist, "mybin", "mybin") 792 f, err := os.Create(binPath) 793 require.NoError(t, err) 794 require.NoError(t, f.Close()) 795 scripts := config.NFPMAPKScripts{ 796 PreUpgrade: "/does/not/exist_preupgrade.sh", 797 PostUpgrade: "/does/not/exist_postupgrade.sh", 798 } 799 ctx := context.New(config.Project{ 800 ProjectName: "mybin", 801 Dist: dist, 802 NFPMs: []config.NFPM{ 803 { 804 ID: "someid", 805 Maintainer: "me@me", 806 Builds: []string{"default"}, 807 Formats: []string{"apk"}, 808 NFPMOverridables: config.NFPMOverridables{ 809 PackageName: "foo", 810 Contents: []*files.Content{ 811 { 812 Source: "testdata/testfile.txt", 813 Destination: "/usr/share/testfile.txt", 814 }, 815 }, 816 APK: config.NFPMAPK{ 817 Scripts: scripts, 818 }, 819 }, 820 }, 821 }, 822 }) 823 ctx.Version = "1.0.0" 824 ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"} 825 for _, goos := range []string{"linux", "darwin"} { 826 for _, goarch := range []string{"amd64", "386"} { 827 ctx.Artifacts.Add(&artifact.Artifact{ 828 Name: "mybin", 829 Path: binPath, 830 Goarch: goarch, 831 Goos: goos, 832 Type: artifact.Binary, 833 Extra: map[string]interface{}{ 834 "ID": "default", 835 }, 836 }) 837 } 838 } 839 840 t.Run("PreUpgrade script file does not exist", func(t *testing.T) { 841 ctx.Config.NFPMs[0].APK.Scripts = scripts 842 ctx.Config.NFPMs[0].APK.Scripts.PostUpgrade = "testdata/testfile.txt" 843 844 require.Contains( 845 t, 846 Pipe{}.Run(ctx).Error(), 847 `nfpm failed: stat /does/not/exist_preupgrade.sh: no such file or directory`, 848 ) 849 }) 850 851 t.Run("PostUpgrade script file does not exist", func(t *testing.T) { 852 ctx.Config.NFPMs[0].APK.Scripts = scripts 853 ctx.Config.NFPMs[0].APK.Scripts.PreUpgrade = "testdata/testfile.txt" 854 855 require.Contains( 856 t, 857 Pipe{}.Run(ctx).Error(), 858 `nfpm failed: stat /does/not/exist_postupgrade.sh: no such file or directory`, 859 ) 860 }) 861 862 t.Run("preupgrade and postupgrade scriptlets set", func(t *testing.T) { 863 ctx.Config.NFPMs[0].APK.Scripts.PreUpgrade = "testdata/testfile.txt" 864 ctx.Config.NFPMs[0].APK.Scripts.PostUpgrade = "testdata/testfile.txt" 865 866 require.NoError(t, Pipe{}.Run(ctx)) 867 }) 868 } 869 870 func TestSeveralNFPMsWithTheSameID(t *testing.T) { 871 ctx := &context.Context{ 872 Config: config.Project{ 873 NFPMs: []config.NFPM{ 874 { 875 ID: "a", 876 }, 877 { 878 ID: "a", 879 }, 880 }, 881 }, 882 } 883 require.EqualError(t, Pipe{}.Default(ctx), "found 2 nfpms with the ID 'a', please fix your config") 884 } 885 886 func TestMeta(t *testing.T) { 887 folder := t.TempDir() 888 dist := filepath.Join(folder, "dist") 889 require.NoError(t, os.Mkdir(dist, 0o755)) 890 require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755)) 891 binPath := filepath.Join(dist, "mybin", "mybin") 892 f, err := os.Create(binPath) 893 require.NoError(t, err) 894 require.NoError(t, f.Close()) 895 ctx := context.New(config.Project{ 896 ProjectName: "mybin", 897 Dist: dist, 898 NFPMs: []config.NFPM{ 899 { 900 ID: "someid", 901 Bindir: "/usr/bin", 902 Builds: []string{"default"}, 903 Formats: []string{"deb", "rpm"}, 904 Section: "somesection", 905 Priority: "standard", 906 Description: "Some description", 907 License: "MIT", 908 Maintainer: "me@me", 909 Vendor: "asdf", 910 Homepage: "https://goreleaser.github.io", 911 Meta: true, 912 NFPMOverridables: config.NFPMOverridables{ 913 FileNameTemplate: defaultNameTemplate + "-{{ .Release }}-{{ .Epoch }}", 914 PackageName: "foo", 915 Dependencies: []string{"make"}, 916 Recommends: []string{"svn"}, 917 Suggests: []string{"bzr"}, 918 Replaces: []string{"fish"}, 919 Conflicts: []string{"git"}, 920 EmptyFolders: []string{"/var/log/foobar"}, 921 Release: "10", 922 Epoch: "20", 923 Contents: []*files.Content{ 924 { 925 Source: "testdata/testfile.txt", 926 Destination: "/usr/share/testfile.txt", 927 }, 928 { 929 Source: "./testdata/testfile.txt", 930 Destination: "/etc/nope.conf", 931 Type: "config", 932 }, 933 { 934 Source: "./testdata/testfile.txt", 935 Destination: "/etc/nope-rpm.conf", 936 Type: "config", 937 Packager: "rpm", 938 }, 939 }, 940 Replacements: map[string]string{ 941 "linux": "Tux", 942 }, 943 }, 944 }, 945 }, 946 }) 947 ctx.Version = "1.0.0" 948 ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"} 949 for _, goos := range []string{"linux", "darwin"} { 950 for _, goarch := range []string{"amd64", "386"} { 951 ctx.Artifacts.Add(&artifact.Artifact{ 952 Name: "mybin", 953 Path: binPath, 954 Goarch: goarch, 955 Goos: goos, 956 Type: artifact.Binary, 957 Extra: map[string]interface{}{ 958 "ID": "default", 959 }, 960 }) 961 } 962 } 963 require.NoError(t, Pipe{}.Run(ctx)) 964 packages := ctx.Artifacts.Filter(artifact.ByType(artifact.LinuxPackage)).List() 965 require.Len(t, packages, 4) 966 for _, pkg := range packages { 967 format := pkg.ExtraOr("Format", "").(string) 968 require.NotEmpty(t, format) 969 require.Equal(t, pkg.Name, "foo_1.0.0_Tux_"+pkg.Goarch+"-10-20."+format) 970 require.Equal(t, pkg.ExtraOr("ID", ""), "someid") 971 require.ElementsMatch(t, []string{ 972 "/usr/share/testfile.txt", 973 "/etc/nope.conf", 974 "/etc/nope-rpm.conf", 975 }, destinations(pkg.ExtraOr("Files", files.Contents{}).(files.Contents))) 976 } 977 978 require.Len(t, ctx.Config.NFPMs[0].Contents, 3, "should not modify the config file list") 979 } 980 981 func TestSkipSign(t *testing.T) { 982 folder, err := ioutil.TempDir("", "archivetest") 983 require.NoError(t, err) 984 dist := filepath.Join(folder, "dist") 985 require.NoError(t, os.Mkdir(dist, 0o755)) 986 require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755)) 987 binPath := filepath.Join(dist, "mybin", "mybin") 988 _, err = os.Create(binPath) 989 require.NoError(t, err) 990 ctx := context.New(config.Project{ 991 ProjectName: "mybin", 992 Dist: dist, 993 NFPMs: []config.NFPM{ 994 { 995 ID: "someid", 996 Builds: []string{"default"}, 997 Formats: []string{"deb", "rpm", "apk"}, 998 NFPMOverridables: config.NFPMOverridables{ 999 PackageName: "foo", 1000 FileNameTemplate: defaultNameTemplate, 1001 Contents: []*files.Content{ 1002 { 1003 Source: "testdata/testfile.txt", 1004 Destination: "/usr/share/testfile.txt", 1005 }, 1006 }, 1007 Deb: config.NFPMDeb{ 1008 Signature: config.NFPMDebSignature{ 1009 KeyFile: "/does/not/exist.gpg", 1010 }, 1011 }, 1012 RPM: config.NFPMRPM{ 1013 Signature: config.NFPMRPMSignature{ 1014 KeyFile: "/does/not/exist.gpg", 1015 }, 1016 }, 1017 APK: config.NFPMAPK{ 1018 Signature: config.NFPMAPKSignature{ 1019 KeyFile: "/does/not/exist.gpg", 1020 }, 1021 }, 1022 }, 1023 }, 1024 }, 1025 }) 1026 ctx.Version = "1.0.0" 1027 ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"} 1028 for _, goos := range []string{"linux", "darwin"} { 1029 for _, goarch := range []string{"amd64", "386"} { 1030 ctx.Artifacts.Add(&artifact.Artifact{ 1031 Name: "mybin", 1032 Path: binPath, 1033 Goarch: goarch, 1034 Goos: goos, 1035 Type: artifact.Binary, 1036 Extra: map[string]interface{}{ 1037 "ID": "default", 1038 }, 1039 }) 1040 } 1041 } 1042 1043 t.Run("skip sign not set", func(t *testing.T) { 1044 contains := "open /does/not/exist.gpg: no such file or directory" 1045 if runtime.GOOS == "windows" { 1046 contains = "open /does/not/exist.gpg: The system cannot find the path specified." 1047 } 1048 require.Contains( 1049 t, 1050 Pipe{}.Run(ctx).Error(), 1051 contains, 1052 ) 1053 }) 1054 1055 t.Run("skip sign set", func(t *testing.T) { 1056 ctx.SkipSign = true 1057 require.NoError(t, Pipe{}.Run(ctx)) 1058 }) 1059 } 1060 1061 func TestBinDirTemplating(t *testing.T) { 1062 folder := t.TempDir() 1063 dist := filepath.Join(folder, "dist") 1064 require.NoError(t, os.Mkdir(dist, 0o755)) 1065 require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755)) 1066 binPath := filepath.Join(dist, "mybin", "mybin") 1067 f, err := os.Create(binPath) 1068 require.NoError(t, err) 1069 require.NoError(t, f.Close()) 1070 ctx := context.New(config.Project{ 1071 ProjectName: "mybin", 1072 Dist: dist, 1073 Env: []string{ 1074 "PRO=pro", 1075 "DESC=templates", 1076 }, 1077 NFPMs: []config.NFPM{ 1078 { 1079 ID: "someid", 1080 // Bindir should pass through the template engine 1081 Bindir: "/usr/lib/{{ .Env.PRO }}/nagios/plugins", 1082 Builds: []string{"default"}, 1083 Formats: []string{"rpm"}, 1084 Section: "somesection", 1085 Priority: "standard", 1086 Description: "Some description with {{ .Env.DESC }}", 1087 License: "MIT", 1088 Maintainer: "me@me", 1089 Vendor: "asdf", 1090 Homepage: "https://goreleaser.com/{{ .Env.PRO }}", 1091 NFPMOverridables: config.NFPMOverridables{ 1092 PackageName: "foo", 1093 }, 1094 }, 1095 }, 1096 }) 1097 ctx.Version = "1.0.0" 1098 ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"} 1099 for _, goos := range []string{"linux"} { 1100 for _, goarch := range []string{"amd64", "386"} { 1101 ctx.Artifacts.Add(&artifact.Artifact{ 1102 Name: "subdir/mybin", 1103 Path: binPath, 1104 Goarch: goarch, 1105 Goos: goos, 1106 Type: artifact.Binary, 1107 Extra: map[string]interface{}{ 1108 "ID": "default", 1109 }, 1110 }) 1111 } 1112 } 1113 require.NoError(t, Pipe{}.Run(ctx)) 1114 packages := ctx.Artifacts.Filter(artifact.ByType(artifact.LinuxPackage)).List() 1115 1116 for _, pkg := range packages { 1117 format := pkg.ExtraOr("Format", "").(string) 1118 require.NotEmpty(t, format) 1119 // the final binary should contain the evaluated bindir (after template eval) 1120 require.ElementsMatch(t, []string{ 1121 "/usr/lib/pro/nagios/plugins/subdir/mybin", 1122 }, destinations(pkg.ExtraOr("Files", files.Contents{}).(files.Contents))) 1123 } 1124 } 1125 1126 func TestSkip(t *testing.T) { 1127 t.Run("skip", func(t *testing.T) { 1128 require.True(t, Pipe{}.Skip(context.New(config.Project{}))) 1129 }) 1130 1131 t.Run("dont skip", func(t *testing.T) { 1132 ctx := context.New(config.Project{ 1133 NFPMs: []config.NFPM{ 1134 {}, 1135 }, 1136 }) 1137 require.False(t, Pipe{}.Skip(ctx)) 1138 }) 1139 } 1140 1141 func sources(contents files.Contents) []string { 1142 result := make([]string, 0, len(contents)) 1143 for _, f := range contents { 1144 result = append(result, f.Source) 1145 } 1146 return result 1147 }