github.com/joselitofilho/goreleaser@v0.155.1-0.20210123221854-e4891856c593/internal/pipe/docker/docker_test.go (about) 1 package docker 2 3 import ( 4 "flag" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "os/exec" 9 "path/filepath" 10 "strings" 11 "syscall" 12 "testing" 13 14 "github.com/goreleaser/goreleaser/internal/artifact" 15 "github.com/goreleaser/goreleaser/internal/pipe" 16 "github.com/goreleaser/goreleaser/internal/testlib" 17 "github.com/goreleaser/goreleaser/pkg/config" 18 "github.com/goreleaser/goreleaser/pkg/context" 19 "github.com/stretchr/testify/require" 20 ) 21 22 var it = flag.Bool("it", false, "push images to docker hub") 23 var registry = "localhost:5000/" 24 var altRegistry = "localhost:5050/" 25 26 func TestMain(m *testing.M) { 27 flag.Parse() 28 if *it { 29 registry = "docker.io/" 30 } 31 os.Exit(m.Run()) 32 } 33 34 func start(t *testing.T) { 35 t.Helper() 36 if *it { 37 return 38 } 39 if out, err := exec.Command( 40 "docker", "run", "-d", "-p", "5000:5000", "--name", "registry", "registry:2", 41 ).CombinedOutput(); err != nil { 42 t.Log("failed to start docker registry", string(out), err) 43 t.FailNow() 44 } 45 if out, err := exec.Command( 46 "docker", "run", "-d", "-p", "5050:5000", "--name", "alt_registry", "registry:2", 47 ).CombinedOutput(); err != nil { 48 t.Log("failed to start alternate docker registry", string(out), err) 49 t.FailNow() 50 } 51 } 52 53 func killAndRm(t *testing.T) { 54 t.Helper() 55 if *it { 56 return 57 } 58 t.Log("killing registry") 59 _ = exec.Command("docker", "kill", "registry").Run() 60 _ = exec.Command("docker", "rm", "registry").Run() 61 _ = exec.Command("docker", "kill", "alt_registry").Run() 62 _ = exec.Command("docker", "rm", "alt_registry").Run() 63 } 64 65 // TODO: this test is too big... split in smaller tests? Mainly the manifest ones... 66 func TestRunPipe(t *testing.T) { 67 type errChecker func(*testing.T, error) 68 var shouldErr = func(msg string) errChecker { 69 return func(t *testing.T, err error) { 70 t.Helper() 71 require.Error(t, err) 72 require.Contains(t, err.Error(), msg) 73 } 74 } 75 var shouldNotErr = func(t *testing.T, err error) { 76 t.Helper() 77 require.NoError(t, err) 78 } 79 type imageLabelFinder func(*testing.T, int) 80 var shouldFindImagesWithLabels = func(image string, filters ...string) func(*testing.T, int) { 81 return func(t *testing.T, count int) { 82 t.Helper() 83 for _, filter := range filters { 84 output, err := exec.Command( 85 "docker", "images", "-q", "*/"+image, 86 "--filter", filter, 87 ).CombinedOutput() 88 require.NoError(t, err) 89 lines := strings.Split(strings.TrimSpace(string(output)), "\n") 90 require.Equal(t, count, len(lines)) 91 } 92 } 93 94 } 95 var noLabels = func(t *testing.T, count int) { 96 t.Helper() 97 } 98 99 var table = map[string]struct { 100 dockers []config.Docker 101 manifests []config.DockerManifest 102 env map[string]string 103 expect []string 104 assertImageLabels imageLabelFinder 105 assertError errChecker 106 pubAssertError errChecker 107 manifestAssertError errChecker 108 extraPrepare func(ctx *context.Context) 109 }{ 110 "multiarch": { 111 dockers: []config.Docker{ 112 { 113 ImageTemplates: []string{registry + "goreleaser/test_multiarch:test-amd64"}, 114 Goos: "linux", 115 Goarch: "amd64", 116 Dockerfile: "testdata/Dockerfile.arch", 117 BuildFlagTemplates: []string{"--build-arg", "ARCH=amd64"}, 118 }, 119 { 120 ImageTemplates: []string{registry + "goreleaser/test_multiarch:test-arm64v8"}, 121 Goos: "linux", 122 Goarch: "arm64", 123 Dockerfile: "testdata/Dockerfile.arch", 124 BuildFlagTemplates: []string{"--build-arg", "ARCH=arm64v8"}, 125 }, 126 }, 127 manifests: []config.DockerManifest{ 128 { 129 // XXX: fails if :latest https://github.com/docker/distribution/issues/3100 130 NameTemplate: registry + "goreleaser/test_multiarch:test", 131 ImageTemplates: []string{ 132 registry + "goreleaser/test_multiarch:test-amd64", 133 registry + "goreleaser/test_multiarch:test-arm64v8", 134 }, 135 CreateFlags: []string{"--insecure"}, 136 PushFlags: []string{"--insecure"}, 137 }, 138 }, 139 expect: []string{ 140 registry + "goreleaser/test_multiarch:test-amd64", 141 registry + "goreleaser/test_multiarch:test-arm64v8", 142 }, 143 assertError: shouldNotErr, 144 pubAssertError: shouldNotErr, 145 manifestAssertError: shouldNotErr, 146 assertImageLabels: noLabels, 147 }, 148 "multiarch with buildx": { 149 dockers: []config.Docker{ 150 { 151 ImageTemplates: []string{registry + "goreleaser/test_multiarch_buildx:amd64"}, 152 Goos: "linux", 153 Goarch: "amd64", 154 Dockerfile: "testdata/Dockerfile", 155 Buildx: true, 156 BuildFlagTemplates: []string{"--platform=linux/amd64"}, 157 }, 158 { 159 ImageTemplates: []string{registry + "goreleaser/test_multiarch_buildx:arm64v8"}, 160 Goos: "linux", 161 Goarch: "arm64", 162 Dockerfile: "testdata/Dockerfile", 163 Buildx: true, 164 BuildFlagTemplates: []string{"--platform=linux/arm64"}, 165 }, 166 }, 167 manifests: []config.DockerManifest{ 168 { 169 NameTemplate: registry + "goreleaser/test_multiarch_buildx:test", 170 ImageTemplates: []string{ 171 registry + "goreleaser/test_multiarch_buildx:amd64", 172 registry + "goreleaser/test_multiarch_buildx:arm64v8", 173 }, 174 CreateFlags: []string{"--insecure"}, 175 PushFlags: []string{"--insecure"}, 176 }, 177 }, 178 expect: []string{ 179 registry + "goreleaser/test_multiarch_buildx:amd64", 180 registry + "goreleaser/test_multiarch_buildx:arm64v8", 181 }, 182 assertError: shouldNotErr, 183 pubAssertError: shouldNotErr, 184 manifestAssertError: shouldNotErr, 185 assertImageLabels: noLabels, 186 }, 187 "multiarch image not found": { 188 dockers: []config.Docker{ 189 { 190 ImageTemplates: []string{registry + "goreleaser/test_multiarch_fail:latest-arm64v8"}, 191 Goos: "linux", 192 Goarch: "arm64", 193 Dockerfile: "testdata/Dockerfile.arch", 194 BuildFlagTemplates: []string{"--build-arg", "ARCH=arm64v8"}, 195 }, 196 }, 197 manifests: []config.DockerManifest{ 198 { 199 NameTemplate: registry + "goreleaser/test_multiarch_fail:test", 200 ImageTemplates: []string{registry + "goreleaser/test_multiarch_fail:latest-amd64"}, 201 CreateFlags: []string{"--insecure"}, 202 PushFlags: []string{"--insecure"}, 203 }, 204 }, 205 expect: []string{registry + "goreleaser/test_multiarch_fail:latest-arm64v8"}, 206 assertError: shouldNotErr, 207 pubAssertError: shouldNotErr, 208 manifestAssertError: shouldErr("failed to create docker manifest: localhost:5000/goreleaser/test_multiarch_fail:test"), 209 assertImageLabels: noLabels, 210 }, 211 "multiarch manifest template error": { 212 dockers: []config.Docker{ 213 { 214 ImageTemplates: []string{registry + "goreleaser/test_multiarch_manifest_tmpl_error"}, 215 Goos: "linux", 216 Goarch: "arm64", 217 Dockerfile: "testdata/Dockerfile", 218 }, 219 }, 220 manifests: []config.DockerManifest{ 221 { 222 NameTemplate: registry + "goreleaser/test_multiarch_manifest_tmpl_error:{{ .Goos }", 223 ImageTemplates: []string{registry + "goreleaser/test_multiarch_manifest_tmpl_error"}, 224 }, 225 }, 226 expect: []string{registry + "goreleaser/test_multiarch_manifest_tmpl_error"}, 227 assertError: shouldNotErr, 228 pubAssertError: shouldNotErr, 229 manifestAssertError: shouldErr(`template: tmpl:1: unexpected "}" in operand`), 230 assertImageLabels: noLabels, 231 }, 232 "multiarch image template error": { 233 dockers: []config.Docker{ 234 { 235 ImageTemplates: []string{registry + "goreleaser/test_multiarch_img_tmpl_error"}, 236 Goos: "linux", 237 Goarch: "arm64", 238 Dockerfile: "testdata/Dockerfile", 239 }, 240 }, 241 manifests: []config.DockerManifest{ 242 { 243 NameTemplate: registry + "goreleaser/test_multiarch_img_tmpl_error", 244 ImageTemplates: []string{registry + "goreleaser/test_multiarch_img_tmpl_error:{{ .Goos }"}, 245 }, 246 }, 247 expect: []string{registry + "goreleaser/test_multiarch_img_tmpl_error"}, 248 assertError: shouldNotErr, 249 pubAssertError: shouldNotErr, 250 manifestAssertError: shouldErr(`template: tmpl:1: unexpected "}" in operand`), 251 assertImageLabels: noLabels, 252 }, 253 "multiarch missing manifest name": { 254 dockers: []config.Docker{ 255 { 256 ImageTemplates: []string{registry + "goreleaser/test_multiarch_no_manifest_name"}, 257 Goos: "linux", 258 Goarch: "arm64", 259 Dockerfile: "testdata/Dockerfile", 260 }, 261 }, 262 manifests: []config.DockerManifest{ 263 { 264 NameTemplate: " ", 265 ImageTemplates: []string{registry + "goreleaser/test_multiarch_no_manifest_name"}, 266 }, 267 }, 268 expect: []string{registry + "goreleaser/test_multiarch_no_manifest_name"}, 269 assertError: shouldNotErr, 270 pubAssertError: shouldNotErr, 271 manifestAssertError: testlib.AssertSkipped, 272 assertImageLabels: noLabels, 273 }, 274 "multiarch missing images": { 275 dockers: []config.Docker{ 276 { 277 ImageTemplates: []string{registry + "goreleaser/test_multiarch_no_manifest_images"}, 278 Dockerfile: "testdata/Dockerfile", 279 Goos: "linux", 280 Goarch: "arm64", 281 }, 282 }, 283 manifests: []config.DockerManifest{ 284 { 285 NameTemplate: "ignored", 286 ImageTemplates: []string{" ", " ", ""}, 287 }, 288 }, 289 expect: []string{registry + "goreleaser/test_multiarch_no_manifest_images"}, 290 assertError: shouldNotErr, 291 pubAssertError: shouldNotErr, 292 manifestAssertError: testlib.AssertSkipped, 293 assertImageLabels: noLabels, 294 }, 295 "valid": { 296 env: map[string]string{ 297 "FOO": "123", 298 }, 299 dockers: []config.Docker{ 300 { 301 ImageTemplates: []string{ 302 registry + "goreleaser/test_run_pipe:{{.Tag}}-{{.Env.FOO}}", 303 registry + "goreleaser/test_run_pipe:v{{.Major}}", 304 registry + "goreleaser/test_run_pipe:v{{.Major}}.{{.Minor}}", 305 registry + "goreleaser/test_run_pipe:commit-{{.Commit}}", 306 registry + "goreleaser/test_run_pipe:latest", 307 altRegistry + "goreleaser/test_run_pipe:{{.Tag}}-{{.Env.FOO}}", 308 altRegistry + "goreleaser/test_run_pipe:v{{.Major}}", 309 altRegistry + "goreleaser/test_run_pipe:v{{.Major}}.{{.Minor}}", 310 altRegistry + "goreleaser/test_run_pipe:commit-{{.Commit}}", 311 altRegistry + "goreleaser/test_run_pipe:latest", 312 }, 313 Goos: "linux", 314 Goarch: "amd64", 315 Dockerfile: "testdata/Dockerfile", 316 BuildFlagTemplates: []string{ 317 "--label=org.label-schema.schema-version=1.0", 318 "--label=org.label-schema.version={{.Version}}", 319 "--label=org.label-schema.vcs-ref={{.Commit}}", 320 "--label=org.label-schema.name={{.ProjectName}}", 321 "--build-arg=FRED={{.Tag}}", 322 }, 323 Files: []string{ 324 "testdata/extra_file.txt", 325 }, 326 }, 327 }, 328 expect: []string{ 329 registry + "goreleaser/test_run_pipe:v1.0.0-123", 330 registry + "goreleaser/test_run_pipe:v1", 331 registry + "goreleaser/test_run_pipe:v1.0", 332 registry + "goreleaser/test_run_pipe:commit-a1b2c3d4", 333 registry + "goreleaser/test_run_pipe:latest", 334 altRegistry + "goreleaser/test_run_pipe:v1.0.0-123", 335 altRegistry + "goreleaser/test_run_pipe:v1", 336 altRegistry + "goreleaser/test_run_pipe:v1.0", 337 altRegistry + "goreleaser/test_run_pipe:commit-a1b2c3d4", 338 altRegistry + "goreleaser/test_run_pipe:latest", 339 }, 340 assertImageLabels: shouldFindImagesWithLabels( 341 "goreleaser/test_run_pipe", 342 "label=org.label-schema.schema-version=1.0", 343 "label=org.label-schema.version=1.0.0", 344 "label=org.label-schema.vcs-ref=a1b2c3d4", 345 "label=org.label-schema.name=mybin", 346 ), 347 assertError: shouldNotErr, 348 pubAssertError: shouldNotErr, 349 manifestAssertError: shouldNotErr, 350 }, 351 "empty image tag": { 352 dockers: []config.Docker{ 353 { 354 ImageTemplates: []string{ 355 "", 356 registry + "goreleaser/empty_tag:latest", 357 }, 358 Goos: "linux", 359 Goarch: "amd64", 360 Dockerfile: "testdata/Dockerfile", 361 }, 362 }, 363 expect: []string{ 364 registry + "goreleaser/empty_tag:latest", 365 }, 366 assertImageLabels: noLabels, 367 assertError: shouldNotErr, 368 pubAssertError: shouldNotErr, 369 manifestAssertError: shouldNotErr, 370 }, 371 "no image tags": { 372 dockers: []config.Docker{ 373 { 374 ImageTemplates: []string{ 375 "", 376 }, 377 Goos: "linux", 378 Goarch: "amd64", 379 Dockerfile: "testdata/Dockerfile", 380 }, 381 }, 382 expect: []string{}, 383 assertImageLabels: noLabels, 384 assertError: shouldErr("no image templates found"), 385 pubAssertError: shouldNotErr, 386 manifestAssertError: shouldNotErr, 387 }, 388 "valid with ids": { 389 dockers: []config.Docker{ 390 { 391 ImageTemplates: []string{ 392 registry + "goreleaser/test_run_pipe_build:latest", 393 }, 394 Goos: "linux", 395 Goarch: "amd64", 396 Dockerfile: "testdata/Dockerfile", 397 IDs: []string{"mybin"}, 398 }, 399 }, 400 expect: []string{ 401 registry + "goreleaser/test_run_pipe_build:latest", 402 }, 403 assertImageLabels: noLabels, 404 assertError: shouldNotErr, 405 pubAssertError: shouldNotErr, 406 manifestAssertError: shouldNotErr, 407 }, 408 "multiple images with same extra file": { 409 dockers: []config.Docker{ 410 { 411 ImageTemplates: []string{ 412 registry + "goreleaser/multiplefiles1:latest", 413 }, 414 Goos: "linux", 415 Goarch: "amd64", 416 Dockerfile: "testdata/Dockerfile", 417 Files: []string{"testdata/extra_file.txt"}, 418 }, 419 { 420 ImageTemplates: []string{ 421 registry + "goreleaser/multiplefiles2:latest", 422 }, 423 Goos: "linux", 424 Goarch: "amd64", 425 Dockerfile: "testdata/Dockerfile", 426 Files: []string{"testdata/extra_file.txt"}, 427 }, 428 }, 429 expect: []string{ 430 registry + "goreleaser/multiplefiles1:latest", 431 registry + "goreleaser/multiplefiles2:latest", 432 }, 433 assertImageLabels: noLabels, 434 assertError: shouldNotErr, 435 pubAssertError: shouldNotErr, 436 manifestAssertError: shouldNotErr, 437 }, 438 "multiple images with same dockerfile": { 439 dockers: []config.Docker{ 440 { 441 ImageTemplates: []string{ 442 registry + "goreleaser/test_run_pipe:latest", 443 }, 444 Goos: "linux", 445 Goarch: "amd64", 446 Dockerfile: "testdata/Dockerfile", 447 }, 448 { 449 ImageTemplates: []string{ 450 registry + "goreleaser/test_run_pipe2:latest", 451 }, 452 Goos: "linux", 453 Goarch: "amd64", 454 Dockerfile: "testdata/Dockerfile", 455 }, 456 }, 457 assertImageLabels: noLabels, 458 expect: []string{ 459 registry + "goreleaser/test_run_pipe:latest", 460 registry + "goreleaser/test_run_pipe2:latest", 461 }, 462 assertError: shouldNotErr, 463 pubAssertError: shouldNotErr, 464 manifestAssertError: shouldNotErr, 465 }, 466 "valid_skip_push": { 467 dockers: []config.Docker{ 468 { 469 ImageTemplates: []string{ 470 registry + "goreleaser/test_run_pipe:latest", 471 }, 472 Goos: "linux", 473 Goarch: "amd64", 474 Dockerfile: "testdata/Dockerfile", 475 SkipPush: "true", 476 }, 477 }, 478 expect: []string{ 479 registry + "goreleaser/test_run_pipe:latest", 480 }, 481 assertImageLabels: noLabels, 482 assertError: testlib.AssertSkipped, 483 }, 484 "one_img_error_with_skip_push": { 485 dockers: []config.Docker{ 486 { 487 ImageTemplates: []string{ 488 registry + "goreleaser/one_img_error_with_skip_push:true", 489 }, 490 Goos: "linux", 491 Goarch: "amd64", 492 Dockerfile: "testdata/Dockerfile.true", 493 SkipPush: "true", 494 }, 495 { 496 ImageTemplates: []string{ 497 registry + "goreleaser/one_img_error_with_skip_push:false", 498 }, 499 Goos: "linux", 500 Goarch: "amd64", 501 Dockerfile: "testdata/Dockerfile.false", 502 SkipPush: "true", 503 }, 504 }, 505 expect: []string{ 506 registry + "goreleaser/one_img_error_with_skip_push:true", 507 }, 508 assertImageLabels: noLabels, 509 assertError: shouldErr("failed to build docker image"), 510 }, 511 "valid_no_latest": { 512 dockers: []config.Docker{ 513 { 514 ImageTemplates: []string{ 515 registry + "goreleaser/test_run_pipe:{{.Version}}", 516 }, 517 Goos: "linux", 518 Goarch: "amd64", 519 Dockerfile: "testdata/Dockerfile", 520 }, 521 }, 522 expect: []string{ 523 registry + "goreleaser/test_run_pipe:1.0.0", 524 }, 525 assertImageLabels: noLabels, 526 assertError: shouldNotErr, 527 pubAssertError: shouldNotErr, 528 manifestAssertError: shouldNotErr, 529 }, 530 "valid build args": { 531 dockers: []config.Docker{ 532 { 533 ImageTemplates: []string{ 534 registry + "goreleaser/test_build_args:latest", 535 }, 536 Goos: "linux", 537 Goarch: "amd64", 538 Dockerfile: "testdata/Dockerfile", 539 BuildFlagTemplates: []string{ 540 "--label=foo=bar", 541 }, 542 }, 543 }, 544 expect: []string{ 545 registry + "goreleaser/test_build_args:latest", 546 }, 547 assertImageLabels: noLabels, 548 assertError: shouldNotErr, 549 pubAssertError: shouldNotErr, 550 manifestAssertError: shouldNotErr, 551 }, 552 "bad build args": { 553 dockers: []config.Docker{ 554 { 555 ImageTemplates: []string{ 556 registry + "goreleaser/test_build_args:latest", 557 }, 558 Goos: "linux", 559 Goarch: "amd64", 560 Dockerfile: "testdata/Dockerfile", 561 BuildFlagTemplates: []string{ 562 "--bad-flag", 563 }, 564 }, 565 }, 566 assertImageLabels: noLabels, 567 assertError: shouldErr("unknown flag: --bad-flag"), 568 }, 569 "bad_dockerfile": { 570 dockers: []config.Docker{ 571 { 572 ImageTemplates: []string{ 573 registry + "goreleaser/bad_dockerfile:latest", 574 }, 575 Goos: "linux", 576 Goarch: "amd64", 577 Dockerfile: "testdata/Dockerfile.bad", 578 }, 579 }, 580 assertImageLabels: noLabels, 581 assertError: shouldErr("pull access denied for nope, repository does not exist"), 582 }, 583 "tag_template_error": { 584 dockers: []config.Docker{ 585 { 586 ImageTemplates: []string{ 587 registry + "goreleaser/test_run_pipe:{{.Tag}", 588 }, 589 Goos: "linux", 590 Goarch: "amd64", 591 Dockerfile: "testdata/Dockerfile", 592 }, 593 }, 594 assertImageLabels: noLabels, 595 assertError: shouldErr(`template: tmpl:1: unexpected "}" in operand`), 596 }, 597 "build_flag_template_error": { 598 dockers: []config.Docker{ 599 { 600 ImageTemplates: []string{ 601 registry + "goreleaser/test_run_pipe:latest", 602 }, 603 Goos: "linux", 604 Goarch: "amd64", 605 Dockerfile: "testdata/Dockerfile", 606 BuildFlagTemplates: []string{ 607 "--label=tag={{.Tag}", 608 }, 609 }, 610 }, 611 assertImageLabels: noLabels, 612 assertError: shouldErr(`template: tmpl:1: unexpected "}" in operand`), 613 }, 614 "missing_env_on_tag_template": { 615 dockers: []config.Docker{ 616 { 617 ImageTemplates: []string{ 618 registry + "goreleaser/test_run_pipe:{{.Env.NOPE}}", 619 }, 620 Goos: "linux", 621 Goarch: "amd64", 622 Dockerfile: "testdata/Dockerfile", 623 }, 624 }, 625 assertImageLabels: noLabels, 626 assertError: shouldErr(`template: tmpl:1:46: executing "tmpl" at <.Env.NOPE>: map has no entry for key "NOPE"`), 627 }, 628 "missing_env_on_build_flag_template": { 629 dockers: []config.Docker{ 630 { 631 ImageTemplates: []string{ 632 registry + "goreleaser/test_run_pipe:latest", 633 }, 634 Goos: "linux", 635 Goarch: "amd64", 636 Dockerfile: "testdata/Dockerfile", 637 BuildFlagTemplates: []string{ 638 "--label=nope={{.Env.NOPE}}", 639 }, 640 }, 641 }, 642 assertImageLabels: noLabels, 643 assertError: shouldErr(`template: tmpl:1:19: executing "tmpl" at <.Env.NOPE>: map has no entry for key "NOPE"`), 644 }, 645 "image_has_projectname_template_variable": { 646 dockers: []config.Docker{ 647 { 648 ImageTemplates: []string{ 649 registry + "goreleaser/{{.ProjectName}}:{{.Tag}}-{{.Env.FOO}}", 650 registry + "goreleaser/{{.ProjectName}}:latest", 651 }, 652 Goos: "linux", 653 Goarch: "amd64", 654 Dockerfile: "testdata/Dockerfile", 655 SkipPush: "true", 656 }, 657 }, 658 env: map[string]string{ 659 "FOO": "123", 660 }, 661 expect: []string{ 662 registry + "goreleaser/mybin:v1.0.0-123", 663 registry + "goreleaser/mybin:latest", 664 }, 665 assertImageLabels: noLabels, 666 assertError: testlib.AssertSkipped, 667 }, 668 "no_permissions": { 669 dockers: []config.Docker{ 670 { 671 ImageTemplates: []string{"docker.io/nope:latest"}, 672 Goos: "linux", 673 Goarch: "amd64", 674 Dockerfile: "testdata/Dockerfile", 675 }, 676 }, 677 expect: []string{ 678 "docker.io/nope:latest", 679 }, 680 assertImageLabels: noLabels, 681 assertError: shouldNotErr, 682 pubAssertError: shouldErr(`requested access to the resource is denied`), 683 manifestAssertError: shouldNotErr, 684 }, 685 "dockerfile_doesnt_exist": { 686 dockers: []config.Docker{ 687 { 688 ImageTemplates: []string{"whatever:latest"}, 689 Goos: "linux", 690 Goarch: "amd64", 691 Dockerfile: "testdata/Dockerfilezzz", 692 }, 693 }, 694 assertImageLabels: noLabels, 695 assertError: shouldErr(`failed to link dockerfile`), 696 }, 697 "extra_file_doesnt_exist": { 698 dockers: []config.Docker{ 699 { 700 ImageTemplates: []string{"whatever:latest"}, 701 Goos: "linux", 702 Goarch: "amd64", 703 Dockerfile: "testdata/Dockerfile", 704 Files: []string{ 705 "testdata/nope.txt", 706 }, 707 }, 708 }, 709 assertImageLabels: noLabels, 710 assertError: shouldErr(`failed to link extra file 'testdata/nope.txt'`), 711 }, 712 "binary doesnt exist": { 713 dockers: []config.Docker{ 714 { 715 ImageTemplates: []string{"whatever:latest"}, 716 Goos: "linux", 717 Goarch: "amd64", 718 Dockerfile: "testdata/Dockerfile", 719 IDs: []string{"nope"}, 720 }, 721 }, 722 assertImageLabels: noLabels, 723 assertError: shouldErr(`/wont-exist: no such file or directory`), 724 extraPrepare: func(ctx *context.Context) { 725 ctx.Artifacts.Add(&artifact.Artifact{ 726 Name: "wont-exist", 727 Path: "wont-exist", 728 Goarch: "amd64", 729 Goos: "linux", 730 Type: artifact.Binary, 731 Extra: map[string]interface{}{ 732 "ID": "nope", 733 }, 734 }) 735 }, 736 }, 737 "multiple_ids": { 738 dockers: []config.Docker{ 739 { 740 ImageTemplates: []string{registry + "goreleaser/multiple:latest"}, 741 Goos: "darwin", 742 Goarch: "amd64", 743 IDs: []string{"mybin", "anotherbin"}, 744 Dockerfile: "testdata/Dockerfile.multiple", 745 }, 746 }, 747 assertImageLabels: noLabels, 748 assertError: shouldNotErr, 749 pubAssertError: shouldNotErr, 750 manifestAssertError: shouldNotErr, 751 expect: []string{ 752 registry + "goreleaser/multiple:latest", 753 }, 754 }, 755 "nfpm and multiple binaries": { 756 dockers: []config.Docker{ 757 { 758 ImageTemplates: []string{registry + "goreleaser/nfpm:latest"}, 759 Goos: "linux", 760 Goarch: "amd64", 761 IDs: []string{"mybin", "anotherbin"}, 762 Dockerfile: "testdata/Dockerfile.nfpm", 763 }, 764 }, 765 assertImageLabels: noLabels, 766 assertError: shouldNotErr, 767 pubAssertError: shouldNotErr, 768 manifestAssertError: shouldNotErr, 769 expect: []string{ 770 registry + "goreleaser/nfpm:latest", 771 }, 772 }, 773 "nfpm and multiple binaries on arm64": { 774 dockers: []config.Docker{ 775 { 776 ImageTemplates: []string{registry + "goreleaser/nfpm_arm:latest"}, 777 Goos: "linux", 778 Goarch: "arm64", 779 IDs: []string{"mybin", "anotherbin"}, 780 Dockerfile: "testdata/Dockerfile.nfpm", 781 }, 782 }, 783 assertImageLabels: noLabels, 784 assertError: shouldNotErr, 785 pubAssertError: shouldNotErr, 786 manifestAssertError: shouldNotErr, 787 expect: []string{ 788 registry + "goreleaser/nfpm_arm:latest", 789 }, 790 }, 791 } 792 793 killAndRm(t) 794 start(t) 795 defer killAndRm(t) 796 797 for name, docker := range table { 798 t.Run(name, func(t *testing.T) { 799 var folder = t.TempDir() 800 var dist = filepath.Join(folder, "dist") 801 require.NoError(t, os.Mkdir(dist, 0755)) 802 require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0755)) 803 _, err := os.Create(filepath.Join(dist, "mybin", "mybin")) 804 require.NoError(t, err) 805 _, err = os.Create(filepath.Join(dist, "mybin", "anotherbin")) 806 require.NoError(t, err) 807 _, err = os.Create(filepath.Join(dist, "mynfpm.apk")) 808 require.NoError(t, err) 809 for _, arch := range []string{"amd64", "386", "arm64"} { 810 _, err = os.Create(filepath.Join(dist, fmt.Sprintf("mybin_%s.apk", arch))) 811 require.NoError(t, err) 812 } 813 814 var ctx = context.New(config.Project{ 815 ProjectName: "mybin", 816 Dist: dist, 817 Dockers: docker.dockers, 818 DockerManifests: docker.manifests, 819 }) 820 ctx.Parallelism = 1 821 ctx.Env = docker.env 822 ctx.Version = "1.0.0" 823 ctx.Git = context.GitInfo{ 824 CurrentTag: "v1.0.0", 825 Commit: "a1b2c3d4", 826 } 827 ctx.Semver = context.Semver{ 828 Major: 1, 829 Minor: 0, 830 Patch: 0, 831 } 832 for _, os := range []string{"linux", "darwin"} { 833 for _, arch := range []string{"amd64", "386", "arm64"} { 834 for _, bin := range []string{"mybin", "anotherbin"} { 835 ctx.Artifacts.Add(&artifact.Artifact{ 836 Name: bin, 837 Path: filepath.Join(dist, "mybin", bin), 838 Goarch: arch, 839 Goos: os, 840 Type: artifact.Binary, 841 Extra: map[string]interface{}{ 842 "ID": bin, 843 }, 844 }) 845 } 846 } 847 } 848 for _, arch := range []string{"amd64", "386", "arm64"} { 849 var name = fmt.Sprintf("mybin_%s.apk", arch) 850 ctx.Artifacts.Add(&artifact.Artifact{ 851 Name: name, 852 Path: filepath.Join(dist, name), 853 Goarch: arch, 854 Goos: "linux", 855 Type: artifact.LinuxPackage, 856 Extra: map[string]interface{}{ 857 "ID": "mybin", 858 }, 859 }) 860 } 861 862 if docker.extraPrepare != nil { 863 docker.extraPrepare(ctx) 864 } 865 866 // this might fail as the image doesnt exist yet, so lets ignore the error 867 for _, img := range docker.expect { 868 _ = exec.Command("docker", "rmi", img).Run() 869 } 870 871 err = Pipe{}.Run(ctx) 872 docker.assertError(t, err) 873 if err == nil { 874 docker.pubAssertError(t, Pipe{}.Publish(ctx)) 875 docker.manifestAssertError(t, ManifestPipe{}.Publish(ctx)) 876 } 877 878 for _, d := range docker.dockers { 879 docker.assertImageLabels(t, len(d.ImageTemplates)) 880 } 881 882 // this might should not fail as the image should have been created when 883 // the step ran 884 for _, img := range docker.expect { 885 t.Log("removing docker image", img) 886 require.NoError(t, exec.Command("docker", "rmi", img).Run(), "could not delete image %s", img) 887 } 888 889 }) 890 } 891 } 892 893 func TestBuildCommand(t *testing.T) { 894 images := []string{"goreleaser/test_build_flag", "goreleaser/test_multiple_tags"} 895 tests := []struct { 896 name string 897 flags []string 898 buildx bool 899 expect []string 900 }{ 901 { 902 name: "no flags", 903 flags: []string{}, 904 expect: []string{"build", ".", "-t", images[0], "-t", images[1]}, 905 }, 906 { 907 name: "single flag", 908 flags: []string{"--label=foo"}, 909 expect: []string{"build", ".", "-t", images[0], "-t", images[1], "--label=foo"}, 910 }, 911 { 912 name: "multiple flags", 913 flags: []string{"--label=foo", "--build-arg=bar=baz"}, 914 expect: []string{"build", ".", "-t", images[0], "-t", images[1], "--label=foo", "--build-arg=bar=baz"}, 915 }, 916 { 917 name: "buildx", 918 buildx: true, 919 flags: []string{"--label=foo", "--build-arg=bar=baz"}, 920 expect: []string{"buildx", "build", ".", "--load", "-t", images[0], "-t", images[1], "--label=foo", "--build-arg=bar=baz"}, 921 }, 922 } 923 for _, tt := range tests { 924 t.Run(tt.name, func(t *testing.T) { 925 require.Equal(t, tt.expect, buildCommand(tt.buildx, images, tt.flags)) 926 }) 927 } 928 } 929 930 func TestDescription(t *testing.T) { 931 require.NotEmpty(t, Pipe{}.String()) 932 } 933 934 func TestNoDockers(t *testing.T) { 935 require.True(t, pipe.IsSkip(Pipe{}.Run(context.New(config.Project{})))) 936 } 937 938 func TestNoDockerWithoutImageName(t *testing.T) { 939 require.True(t, pipe.IsSkip(Pipe{}.Run(context.New(config.Project{ 940 Dockers: []config.Docker{ 941 { 942 Goos: "linux", 943 }, 944 }, 945 })))) 946 } 947 948 func TestDockerNotInPath(t *testing.T) { 949 var path = os.Getenv("PATH") 950 defer func() { 951 require.NoError(t, os.Setenv("PATH", path)) 952 }() 953 require.NoError(t, os.Setenv("PATH", "")) 954 var ctx = &context.Context{ 955 Version: "1.0.0", 956 Config: config.Project{ 957 Dockers: []config.Docker{ 958 { 959 ImageTemplates: []string{"a/b"}, 960 }, 961 }, 962 }, 963 } 964 require.EqualError(t, Pipe{}.Run(ctx), ErrNoDocker.Error()) 965 } 966 967 func TestDefault(t *testing.T) { 968 var ctx = &context.Context{ 969 Config: config.Project{ 970 Dockers: []config.Docker{ 971 { 972 IDs: []string{"aa"}, 973 Builds: []string{"foo"}, 974 Binaries: []string{"aaa"}, 975 }, 976 }, 977 }, 978 } 979 require.NoError(t, Pipe{}.Default(ctx)) 980 require.Len(t, ctx.Config.Dockers, 1) 981 var docker = ctx.Config.Dockers[0] 982 require.Equal(t, "linux", docker.Goos) 983 require.Equal(t, "amd64", docker.Goarch) 984 require.Equal(t, []string{"aa", "foo"}, docker.IDs) 985 } 986 987 func TestDefaultDockerfile(t *testing.T) { 988 var ctx = &context.Context{ 989 Config: config.Project{ 990 Builds: []config.Build{ 991 {}, 992 }, 993 Dockers: []config.Docker{ 994 {}, 995 {}, 996 }, 997 }, 998 } 999 require.NoError(t, Pipe{}.Default(ctx)) 1000 require.Len(t, ctx.Config.Dockers, 2) 1001 require.Equal(t, "Dockerfile", ctx.Config.Dockers[0].Dockerfile) 1002 require.Equal(t, "Dockerfile", ctx.Config.Dockers[1].Dockerfile) 1003 } 1004 1005 func TestDefaultNoDockers(t *testing.T) { 1006 var ctx = &context.Context{ 1007 Config: config.Project{ 1008 Dockers: []config.Docker{}, 1009 }, 1010 } 1011 require.NoError(t, Pipe{}.Default(ctx)) 1012 require.Empty(t, ctx.Config.Dockers) 1013 } 1014 1015 func TestDefaultFilesDot(t *testing.T) { 1016 var ctx = &context.Context{ 1017 Config: config.Project{ 1018 Dist: "/tmp/distt", 1019 Dockers: []config.Docker{ 1020 { 1021 Files: []string{"./lala", "./lolsob", "."}, 1022 }, 1023 }, 1024 }, 1025 } 1026 require.EqualError(t, Pipe{}.Default(ctx), `invalid docker.files: can't be . or inside dist folder: .`) 1027 } 1028 1029 func TestDefaultFilesDis(t *testing.T) { 1030 var ctx = &context.Context{ 1031 Config: config.Project{ 1032 Dist: "/tmp/dist", 1033 Dockers: []config.Docker{ 1034 { 1035 Files: []string{"./fooo", "/tmp/dist/asdasd/asd", "./bar"}, 1036 }, 1037 }, 1038 }, 1039 } 1040 require.EqualError(t, Pipe{}.Default(ctx), `invalid docker.files: can't be . or inside dist folder: /tmp/dist/asdasd/asd`) 1041 } 1042 1043 func TestDefaultSet(t *testing.T) { 1044 var ctx = &context.Context{ 1045 Config: config.Project{ 1046 Dockers: []config.Docker{ 1047 { 1048 IDs: []string{"foo"}, 1049 Goos: "windows", 1050 Goarch: "i386", 1051 Dockerfile: "Dockerfile.foo", 1052 }, 1053 }, 1054 }, 1055 } 1056 require.NoError(t, Pipe{}.Default(ctx)) 1057 require.Len(t, ctx.Config.Dockers, 1) 1058 var docker = ctx.Config.Dockers[0] 1059 require.Equal(t, "windows", docker.Goos) 1060 require.Equal(t, "i386", docker.Goarch) 1061 require.Equal(t, []string{"foo"}, docker.IDs) 1062 require.Equal(t, "Dockerfile.foo", docker.Dockerfile) 1063 } 1064 1065 func Test_processImageTemplates(t *testing.T) { 1066 var ctx = &context.Context{ 1067 Config: config.Project{ 1068 Builds: []config.Build{ 1069 { 1070 ID: "default", 1071 }, 1072 }, 1073 Dockers: []config.Docker{ 1074 { 1075 Dockerfile: "Dockerfile.foo", 1076 ImageTemplates: []string{ 1077 "user/image:{{.Tag}}", 1078 "gcr.io/image:{{.Tag}}-{{.Env.FOO}}", 1079 "gcr.io/image:v{{.Major}}.{{.Minor}}", 1080 }, 1081 SkipPush: "true", 1082 }, 1083 }, 1084 }, 1085 } 1086 ctx.SkipPublish = true 1087 ctx.Env = map[string]string{ 1088 "FOO": "123", 1089 } 1090 ctx.Version = "1.0.0" 1091 ctx.Git = context.GitInfo{ 1092 CurrentTag: "v1.0.0", 1093 Commit: "a1b2c3d4", 1094 } 1095 ctx.Semver = context.Semver{ 1096 Major: 1, 1097 Minor: 0, 1098 Patch: 0, 1099 } 1100 1101 require.NoError(t, Pipe{}.Default(ctx)) 1102 require.Len(t, ctx.Config.Dockers, 1) 1103 1104 docker := ctx.Config.Dockers[0] 1105 require.Equal(t, "Dockerfile.foo", docker.Dockerfile) 1106 1107 images, err := processImageTemplates(ctx, docker) 1108 require.NoError(t, err) 1109 require.Equal(t, []string{ 1110 "user/image:v1.0.0", 1111 "gcr.io/image:v1.0.0-123", 1112 "gcr.io/image:v1.0", 1113 }, images) 1114 } 1115 1116 func TestLinkFile(t *testing.T) { 1117 src, err := ioutil.TempFile(t.TempDir(), "src") 1118 require.NoError(t, err) 1119 require.NoError(t, src.Close()) 1120 dst := filepath.Join(filepath.Dir(src.Name()), "dst") 1121 t.Cleanup(func() { 1122 os.Remove(src.Name()) 1123 os.Remove(dst) 1124 }) 1125 fmt.Println("src:", src.Name()) 1126 fmt.Println("dst:", dst) 1127 require.NoError(t, ioutil.WriteFile(src.Name(), []byte("foo"), 0644)) 1128 require.NoError(t, link(src.Name(), dst)) 1129 require.Equal(t, inode(src.Name()), inode(dst)) 1130 } 1131 1132 func TestLinkDirectory(t *testing.T) { 1133 var srcDir = t.TempDir() 1134 var dstDir = t.TempDir() 1135 const testFile = "test" 1136 require.NoError(t, ioutil.WriteFile(filepath.Join(srcDir, testFile), []byte("foo"), 0644)) 1137 require.NoError(t, link(srcDir, dstDir)) 1138 require.Equal(t, inode(filepath.Join(srcDir, testFile)), inode(filepath.Join(dstDir, testFile))) 1139 } 1140 1141 func TestLinkTwoLevelDirectory(t *testing.T) { 1142 var srcDir = t.TempDir() 1143 var dstDir = t.TempDir() 1144 var srcLevel2 = filepath.Join(srcDir, "level2") 1145 const testFile = "test" 1146 1147 require.NoError(t, os.Mkdir(srcLevel2, 0755)) 1148 require.NoError(t, ioutil.WriteFile(filepath.Join(srcDir, testFile), []byte("foo"), 0644)) 1149 require.NoError(t, ioutil.WriteFile(filepath.Join(srcLevel2, testFile), []byte("foo"), 0644)) 1150 1151 require.NoError(t, link(srcDir, dstDir)) 1152 1153 require.Equal(t, inode(filepath.Join(srcDir, testFile)), inode(filepath.Join(dstDir, testFile))) 1154 require.Equal(t, inode(filepath.Join(srcLevel2, testFile)), inode(filepath.Join(dstDir, "level2", testFile))) 1155 } 1156 1157 func inode(file string) uint64 { 1158 fileInfo, err := os.Stat(file) 1159 if err != nil { 1160 return 0 1161 } 1162 stat := fileInfo.Sys().(*syscall.Stat_t) 1163 return stat.Ino 1164 }