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