github.com/goreleaser/goreleaser@v1.25.1/internal/pipe/docker/docker_test.go (about)

     1  package docker
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"os/exec"
     7  	"path/filepath"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/goreleaser/goreleaser/internal/artifact"
    12  	"github.com/goreleaser/goreleaser/internal/pipe"
    13  	"github.com/goreleaser/goreleaser/internal/skips"
    14  	"github.com/goreleaser/goreleaser/internal/testctx"
    15  	"github.com/goreleaser/goreleaser/internal/testlib"
    16  	"github.com/goreleaser/goreleaser/pkg/config"
    17  	"github.com/goreleaser/goreleaser/pkg/context"
    18  	"github.com/stretchr/testify/require"
    19  )
    20  
    21  const (
    22  	registryPort    = "5050"
    23  	registry        = "localhost:5050/"
    24  	altRegistryPort = "5051"
    25  	altRegistry     = "localhost:5051/"
    26  )
    27  
    28  func start(tb testing.TB) {
    29  	tb.Helper()
    30  	tb.Log("starting registries")
    31  	testlib.StartRegistry(tb, "registry", registryPort)
    32  	testlib.StartRegistry(tb, "alt_registry", altRegistryPort)
    33  }
    34  
    35  // TODO: this test is too big... split in smaller tests? Mainly the manifest ones...
    36  func TestRunPipe(t *testing.T) {
    37  	testlib.CheckPath(t, "docker")
    38  	type errChecker func(*testing.T, error)
    39  	shouldErr := func(msg string) errChecker {
    40  		return func(t *testing.T, err error) {
    41  			t.Helper()
    42  			require.ErrorContains(t, err, msg)
    43  		}
    44  	}
    45  	shouldNotErr := func(t *testing.T, err error) {
    46  		t.Helper()
    47  		require.NoError(t, err)
    48  	}
    49  	shouldTemplateErr := func(t *testing.T, err error) {
    50  		t.Helper()
    51  		testlib.RequireTemplateError(t, err)
    52  	}
    53  	type imageLabelFinder func(*testing.T, string)
    54  	shouldFindImagesWithLabels := func(image string, filters ...string) func(*testing.T, string) {
    55  		return func(t *testing.T, _ string) {
    56  			t.Helper()
    57  			for _, filter := range filters {
    58  				cmd := exec.Command("docker", "images", "-q", "--filter", "reference=*/"+image, "--filter", filter)
    59  				// t.Log("running", cmd)
    60  				output, err := cmd.CombinedOutput()
    61  				require.NoError(t, err, string(output))
    62  				uniqueIDs := map[string]string{}
    63  				for _, id := range strings.Split(strings.TrimSpace(string(output)), "\n") {
    64  					uniqueIDs[id] = id
    65  				}
    66  				require.Len(t, uniqueIDs, 1)
    67  			}
    68  		}
    69  	}
    70  	noLabels := func(t *testing.T, _ string) {
    71  		t.Helper()
    72  	}
    73  
    74  	table := map[string]struct {
    75  		dockers             []config.Docker
    76  		manifests           []config.DockerManifest
    77  		env                 map[string]string
    78  		expect              []string
    79  		assertImageLabels   imageLabelFinder
    80  		assertError         errChecker
    81  		pubAssertError      errChecker
    82  		manifestAssertError errChecker
    83  		extraPrepare        func(t *testing.T, ctx *context.Context)
    84  	}{
    85  		"multiarch": {
    86  			dockers: []config.Docker{
    87  				{
    88  					ImageTemplates:     []string{registry + "goreleaser/test_multiarch:test-amd64"},
    89  					Goos:               "linux",
    90  					Goarch:             "amd64",
    91  					Dockerfile:         "testdata/Dockerfile.arch",
    92  					BuildFlagTemplates: []string{"--build-arg", "ARCH=amd64"},
    93  				},
    94  				{
    95  					ImageTemplates:     []string{registry + "goreleaser/test_multiarch:test-arm64v8"},
    96  					Goos:               "linux",
    97  					Goarch:             "arm64",
    98  					Dockerfile:         "testdata/Dockerfile.arch",
    99  					BuildFlagTemplates: []string{"--build-arg", "ARCH=arm64v8"},
   100  				},
   101  			},
   102  			manifests: []config.DockerManifest{
   103  				{
   104  					NameTemplate: registry + "goreleaser/test_multiarch:test",
   105  					ImageTemplates: []string{
   106  						registry + "goreleaser/test_multiarch:test-amd64",
   107  						registry + "goreleaser/test_multiarch:test-arm64v8",
   108  					},
   109  				},
   110  			},
   111  			expect: []string{
   112  				registry + "goreleaser/test_multiarch:test-amd64",
   113  				registry + "goreleaser/test_multiarch:test-arm64v8",
   114  			},
   115  			assertError:         shouldNotErr,
   116  			pubAssertError:      shouldNotErr,
   117  			manifestAssertError: shouldNotErr,
   118  			assertImageLabels:   noLabels,
   119  		},
   120  		"manifest autoskip no prerelease": {
   121  			env: map[string]string{"AUTO": "auto"},
   122  			dockers: []config.Docker{
   123  				{
   124  					ImageTemplates: []string{registry + "goreleaser/test_manifestskip:test-amd64"},
   125  					Goos:           "linux",
   126  					Goarch:         "amd64",
   127  					Dockerfile:     "testdata/Dockerfile",
   128  				},
   129  			},
   130  			manifests: []config.DockerManifest{
   131  				{
   132  					NameTemplate: registry + "goreleaser/test_manifestskip:test",
   133  					ImageTemplates: []string{
   134  						registry + "goreleaser/test_manifestskip:test-amd64",
   135  					},
   136  					SkipPush: "{{ .Env.AUTO }}",
   137  				},
   138  			},
   139  			expect: []string{
   140  				registry + "goreleaser/test_manifestskip:test-amd64",
   141  			},
   142  			assertError:         shouldNotErr,
   143  			pubAssertError:      shouldNotErr,
   144  			manifestAssertError: shouldNotErr,
   145  			assertImageLabels:   noLabels,
   146  		},
   147  		"manifest autoskip prerelease": {
   148  			dockers: []config.Docker{
   149  				{
   150  					ImageTemplates: []string{registry + "goreleaser/test_manifestskip-prerelease:test-amd64"},
   151  					Goos:           "linux",
   152  					Goarch:         "amd64",
   153  					Dockerfile:     "testdata/Dockerfile",
   154  				},
   155  			},
   156  			manifests: []config.DockerManifest{
   157  				{
   158  					NameTemplate: registry + "goreleaser/test_manifestskip-prerelease:test",
   159  					ImageTemplates: []string{
   160  						registry + "goreleaser/test_manifestskip-prerelease:test-amd64",
   161  					},
   162  					SkipPush: "auto",
   163  				},
   164  			},
   165  			expect: []string{
   166  				registry + "goreleaser/test_manifestskip-prerelease:test-amd64",
   167  			},
   168  			assertError:         shouldNotErr,
   169  			pubAssertError:      shouldNotErr,
   170  			manifestAssertError: testlib.AssertSkipped,
   171  			assertImageLabels:   noLabels,
   172  			extraPrepare: func(t *testing.T, ctx *context.Context) {
   173  				t.Helper()
   174  				ctx.Semver.Prerelease = "beta"
   175  			},
   176  		},
   177  		"manifest skip": {
   178  			dockers: []config.Docker{
   179  				{
   180  					ImageTemplates: []string{registry + "goreleaser/test_manifestskip-true:test-amd64"},
   181  					Goos:           "linux",
   182  					Goarch:         "amd64",
   183  					Dockerfile:     "testdata/Dockerfile",
   184  				},
   185  			},
   186  			manifests: []config.DockerManifest{
   187  				{
   188  					NameTemplate: registry + "goreleaser/test_manifestskip-true:test",
   189  					ImageTemplates: []string{
   190  						registry + "goreleaser/test_manifestskip-true:test-amd64",
   191  					},
   192  					SkipPush: "true",
   193  				},
   194  			},
   195  			expect: []string{
   196  				registry + "goreleaser/test_manifestskip-true:test-amd64",
   197  			},
   198  			assertError:         shouldNotErr,
   199  			pubAssertError:      shouldNotErr,
   200  			manifestAssertError: testlib.AssertSkipped,
   201  			assertImageLabels:   noLabels,
   202  		},
   203  		"multiarch with previous existing manifest": {
   204  			dockers: []config.Docker{
   205  				{
   206  					ImageTemplates:     []string{registry + "goreleaser/test_multiarch:2test-amd64"},
   207  					Goos:               "linux",
   208  					Goarch:             "amd64",
   209  					Dockerfile:         "testdata/Dockerfile.arch",
   210  					BuildFlagTemplates: []string{"--build-arg", "ARCH=amd64"},
   211  				},
   212  				{
   213  					ImageTemplates:     []string{registry + "goreleaser/test_multiarch:2test-arm64v8"},
   214  					Goos:               "linux",
   215  					Goarch:             "arm64",
   216  					Dockerfile:         "testdata/Dockerfile.arch",
   217  					BuildFlagTemplates: []string{"--build-arg", "ARCH=arm64v8"},
   218  				},
   219  			},
   220  			manifests: []config.DockerManifest{
   221  				{
   222  					NameTemplate: registry + "goreleaser/test_multiarch:2test",
   223  					ImageTemplates: []string{
   224  						registry + "goreleaser/test_multiarch:2test-amd64",
   225  						registry + "goreleaser/test_multiarch:2test-arm64v8",
   226  					},
   227  				},
   228  			},
   229  			expect: []string{
   230  				registry + "goreleaser/test_multiarch:2test-amd64",
   231  				registry + "goreleaser/test_multiarch:2test-arm64v8",
   232  			},
   233  			assertError:         shouldNotErr,
   234  			pubAssertError:      shouldNotErr,
   235  			manifestAssertError: shouldNotErr,
   236  			assertImageLabels:   noLabels,
   237  			extraPrepare: func(t *testing.T, ctx *context.Context) {
   238  				t.Helper()
   239  				for _, cmd := range []string{
   240  					fmt.Sprintf("docker manifest rm %sgoreleaser/test_multiarch:2test || true", registry),
   241  					fmt.Sprintf("docker build -t %sgoreleaser/dummy:v1 --platform linux/amd64 -f testdata/Dockerfile.dummy .", registry),
   242  					fmt.Sprintf("docker push %sgoreleaser/dummy:v1", registry),
   243  					fmt.Sprintf("docker manifest create %sgoreleaser/test_multiarch:2test --amend %sgoreleaser/dummy:v1 --insecure", registry, registry),
   244  				} {
   245  					parts := strings.Fields(strings.TrimSuffix(cmd, " || true"))
   246  					out, err := exec.CommandContext(ctx, parts[0], parts[1:]...).CombinedOutput()
   247  					if !strings.HasSuffix(cmd, " || true") {
   248  						require.NoError(t, err, cmd+": "+string(out))
   249  					}
   250  				}
   251  			},
   252  		},
   253  		"multiarch image not found": {
   254  			dockers: []config.Docker{
   255  				{
   256  					ImageTemplates:     []string{registry + "goreleaser/test_multiarch_fail:latest-arm64v8"},
   257  					Goos:               "linux",
   258  					Goarch:             "arm64",
   259  					Dockerfile:         "testdata/Dockerfile.arch",
   260  					BuildFlagTemplates: []string{"--build-arg", "ARCH=arm64v8"},
   261  				},
   262  			},
   263  			manifests: []config.DockerManifest{
   264  				{
   265  					NameTemplate:   registry + "goreleaser/test_multiarch_fail:test",
   266  					ImageTemplates: []string{registry + "goreleaser/test_multiarch_fail:latest-amd64"},
   267  				},
   268  			},
   269  			expect:              []string{registry + "goreleaser/test_multiarch_fail:latest-arm64v8"},
   270  			assertError:         shouldNotErr,
   271  			pubAssertError:      shouldNotErr,
   272  			manifestAssertError: shouldErr("failed to create localhost:5050/goreleaser/test_multiarch_fail:test"),
   273  			assertImageLabels:   noLabels,
   274  		},
   275  		"multiarch manifest template error": {
   276  			dockers: []config.Docker{
   277  				{
   278  					ImageTemplates: []string{registry + "goreleaser/test_multiarch_manifest_tmpl_error"},
   279  					Goos:           "linux",
   280  					Goarch:         "arm64",
   281  					Dockerfile:     "testdata/Dockerfile",
   282  				},
   283  			},
   284  			manifests: []config.DockerManifest{
   285  				{
   286  					NameTemplate:   registry + "goreleaser/test_multiarch_manifest_tmpl_error:{{ .Goos }",
   287  					ImageTemplates: []string{registry + "goreleaser/test_multiarch_manifest_tmpl_error"},
   288  				},
   289  			},
   290  			expect:              []string{registry + "goreleaser/test_multiarch_manifest_tmpl_error"},
   291  			assertError:         shouldNotErr,
   292  			pubAssertError:      shouldNotErr,
   293  			manifestAssertError: shouldTemplateErr,
   294  			assertImageLabels:   noLabels,
   295  		},
   296  		"multiarch image template error": {
   297  			dockers: []config.Docker{
   298  				{
   299  					ImageTemplates: []string{registry + "goreleaser/test_multiarch_img_tmpl_error"},
   300  					Goos:           "linux",
   301  					Goarch:         "arm64",
   302  					Dockerfile:     "testdata/Dockerfile",
   303  				},
   304  			},
   305  			manifests: []config.DockerManifest{
   306  				{
   307  					NameTemplate:   registry + "goreleaser/test_multiarch_img_tmpl_error",
   308  					ImageTemplates: []string{registry + "goreleaser/test_multiarch_img_tmpl_error:{{ .Goos }"},
   309  				},
   310  			},
   311  			expect:              []string{registry + "goreleaser/test_multiarch_img_tmpl_error"},
   312  			assertError:         shouldNotErr,
   313  			pubAssertError:      shouldNotErr,
   314  			manifestAssertError: shouldTemplateErr,
   315  			assertImageLabels:   noLabels,
   316  		},
   317  		"multiarch missing manifest name": {
   318  			dockers: []config.Docker{
   319  				{
   320  					ImageTemplates: []string{registry + "goreleaser/test_multiarch_no_manifest_name"},
   321  					Goos:           "linux",
   322  					Goarch:         "arm64",
   323  					Dockerfile:     "testdata/Dockerfile",
   324  				},
   325  			},
   326  			manifests: []config.DockerManifest{
   327  				{
   328  					NameTemplate:   "  ",
   329  					ImageTemplates: []string{registry + "goreleaser/test_multiarch_no_manifest_name"},
   330  				},
   331  			},
   332  			expect:              []string{registry + "goreleaser/test_multiarch_no_manifest_name"},
   333  			assertError:         shouldNotErr,
   334  			pubAssertError:      shouldNotErr,
   335  			manifestAssertError: testlib.AssertSkipped,
   336  			assertImageLabels:   noLabels,
   337  		},
   338  		"multiarch missing images": {
   339  			dockers: []config.Docker{
   340  				{
   341  					ImageTemplates: []string{registry + "goreleaser/test_multiarch_no_manifest_images"},
   342  					Dockerfile:     "testdata/Dockerfile",
   343  					Goos:           "linux",
   344  					Goarch:         "arm64",
   345  				},
   346  			},
   347  			manifests: []config.DockerManifest{
   348  				{
   349  					NameTemplate:   "ignored",
   350  					ImageTemplates: []string{" ", "   ", ""},
   351  				},
   352  			},
   353  			expect:              []string{registry + "goreleaser/test_multiarch_no_manifest_images"},
   354  			assertError:         shouldNotErr,
   355  			pubAssertError:      shouldNotErr,
   356  			manifestAssertError: testlib.AssertSkipped,
   357  			assertImageLabels:   noLabels,
   358  		},
   359  		"valid": {
   360  			env: map[string]string{
   361  				"FOO": "123",
   362  			},
   363  			dockers: []config.Docker{
   364  				{
   365  					ImageTemplates: []string{
   366  						registry + "goreleaser/test_run_pipe:{{.Tag}}-{{.Env.FOO}}",
   367  						registry + "goreleaser/test_run_pipe:v{{.Major}}",
   368  						registry + "goreleaser/test_run_pipe:v{{.Major}}.{{.Minor}}",
   369  						registry + "goreleaser/test_run_pipe:commit-{{.Commit}}",
   370  						registry + "goreleaser/test_run_pipe:latest",
   371  						altRegistry + "goreleaser/test_run_pipe:{{.Tag}}-{{.Env.FOO}}",
   372  						altRegistry + "goreleaser/test_run_pipe:v{{.Major}}",
   373  						altRegistry + "goreleaser/test_run_pipe:v{{.Major}}.{{.Minor}}",
   374  						altRegistry + "goreleaser/test_run_pipe:commit-{{.Commit}}",
   375  						altRegistry + "goreleaser/test_run_pipe:latest",
   376  					},
   377  					Goos:       "linux",
   378  					Goarch:     "amd64",
   379  					Dockerfile: "testdata/Dockerfile",
   380  					BuildFlagTemplates: []string{
   381  						"--label=org.label-schema.schema-version=1.0",
   382  						"--label=org.label-schema.version={{.Version}}",
   383  						"--label=org.label-schema.vcs-ref={{.Commit}}",
   384  						"--label=org.label-schema.name={{.ProjectName}}",
   385  						"--build-arg=FRED={{.Tag}}",
   386  					},
   387  					Files: []string{
   388  						"testdata/extra_file.txt",
   389  					},
   390  				},
   391  			},
   392  			expect: []string{
   393  				registry + "goreleaser/test_run_pipe:v1.0.0-123",
   394  				registry + "goreleaser/test_run_pipe:v1",
   395  				registry + "goreleaser/test_run_pipe:v1.0",
   396  				registry + "goreleaser/test_run_pipe:commit-a1b2c3d4",
   397  				registry + "goreleaser/test_run_pipe:latest",
   398  				altRegistry + "goreleaser/test_run_pipe:v1.0.0-123",
   399  				altRegistry + "goreleaser/test_run_pipe:v1",
   400  				altRegistry + "goreleaser/test_run_pipe:v1.0",
   401  				altRegistry + "goreleaser/test_run_pipe:commit-a1b2c3d4",
   402  				altRegistry + "goreleaser/test_run_pipe:latest",
   403  			},
   404  			assertImageLabels: shouldFindImagesWithLabels(
   405  				"goreleaser/test_run_pipe",
   406  				"label=org.label-schema.schema-version=1.0",
   407  				"label=org.label-schema.version=1.0.0",
   408  				"label=org.label-schema.vcs-ref=a1b2c3d4",
   409  				"label=org.label-schema.name=mybin",
   410  			),
   411  			assertError:         shouldNotErr,
   412  			pubAssertError:      shouldNotErr,
   413  			manifestAssertError: shouldNotErr,
   414  		},
   415  		"templated-dockerfile": {
   416  			env: map[string]string{
   417  				"Dockerfile": "testdata/Dockerfile",
   418  			},
   419  			dockers: []config.Docker{
   420  				{
   421  					ImageTemplates: []string{
   422  						registry + "goreleaser/templated_dockerfile:v1",
   423  					},
   424  					Goos:       "linux",
   425  					Goarch:     "amd64",
   426  					Dockerfile: "{{ .Env.Dockerfile }}",
   427  					Files: []string{
   428  						"testdata/extra_file.txt",
   429  					},
   430  				},
   431  			},
   432  			expect: []string{
   433  				registry + "goreleaser/templated_dockerfile:v1",
   434  			},
   435  			assertError:         shouldNotErr,
   436  			assertImageLabels:   noLabels,
   437  			pubAssertError:      shouldNotErr,
   438  			manifestAssertError: shouldNotErr,
   439  		},
   440  		"wrong binary name": {
   441  			dockers: []config.Docker{
   442  				{
   443  					ImageTemplates: []string{
   444  						registry + "goreleaser/wrong_bin_name:v1",
   445  					},
   446  					Goos:       "linux",
   447  					Goarch:     "amd64",
   448  					Dockerfile: "testdata/Dockerfile.wrongbin",
   449  				},
   450  			},
   451  			assertError:       shouldErr("seems like you tried to copy a file that is not available in the build context"),
   452  			assertImageLabels: noLabels,
   453  		},
   454  		"templated-dockerfile-invalid": {
   455  			dockers: []config.Docker{
   456  				{
   457  					ImageTemplates: []string{
   458  						registry + "goreleaser/invalid-templated-dockerfile:v1",
   459  					},
   460  					Goos:       "linux",
   461  					Goarch:     "amd64",
   462  					Dockerfile: "{{ .Env.Dockerfile }}",
   463  				},
   464  			},
   465  			expect:              []string{},
   466  			assertError:         shouldTemplateErr,
   467  			assertImageLabels:   noLabels,
   468  			pubAssertError:      shouldNotErr,
   469  			manifestAssertError: shouldNotErr,
   470  		},
   471  		"image template with env": {
   472  			env: map[string]string{
   473  				"FOO": "test_run_pipe_template",
   474  			},
   475  			dockers: []config.Docker{
   476  				{
   477  					ImageTemplates: []string{
   478  						registry + "goreleaser/{{.Env.FOO}}:{{.Tag}}",
   479  					},
   480  					Goos:       "linux",
   481  					Goarch:     "amd64",
   482  					Dockerfile: "testdata/Dockerfile",
   483  				},
   484  			},
   485  			expect: []string{
   486  				registry + "goreleaser/test_run_pipe_template:v1.0.0",
   487  			},
   488  			assertImageLabels:   noLabels,
   489  			assertError:         shouldNotErr,
   490  			pubAssertError:      shouldNotErr,
   491  			manifestAssertError: shouldNotErr,
   492  		},
   493  		"image template uppercase": {
   494  			env: map[string]string{
   495  				"FOO": "test_run_pipe_template_UPPERCASE",
   496  			},
   497  			dockers: []config.Docker{
   498  				{
   499  					ImageTemplates: []string{
   500  						registry + "goreleaser/{{.Env.FOO}}:{{.Tag}}",
   501  					},
   502  					Goos:       "linux",
   503  					Goarch:     "amd64",
   504  					Dockerfile: "testdata/Dockerfile",
   505  				},
   506  			},
   507  			expect:              []string{},
   508  			assertImageLabels:   noLabels,
   509  			assertError:         shouldErr(`failed to build localhost:5050/goreleaser/test_run_pipe_template_UPPERCASE:v1.0.0`),
   510  			pubAssertError:      shouldNotErr,
   511  			manifestAssertError: shouldNotErr,
   512  		},
   513  		"empty image tag": {
   514  			dockers: []config.Docker{
   515  				{
   516  					ImageTemplates: []string{
   517  						"",
   518  						registry + "goreleaser/empty_tag:latest",
   519  					},
   520  					Goos:       "linux",
   521  					Goarch:     "amd64",
   522  					Dockerfile: "testdata/Dockerfile",
   523  				},
   524  			},
   525  			expect: []string{
   526  				registry + "goreleaser/empty_tag:latest",
   527  			},
   528  			assertImageLabels:   noLabels,
   529  			assertError:         shouldNotErr,
   530  			pubAssertError:      shouldNotErr,
   531  			manifestAssertError: shouldNotErr,
   532  		},
   533  		"no image tags": {
   534  			dockers: []config.Docker{
   535  				{
   536  					ImageTemplates: []string{
   537  						"",
   538  					},
   539  					Goos:       "linux",
   540  					Goarch:     "amd64",
   541  					Dockerfile: "testdata/Dockerfile",
   542  				},
   543  			},
   544  			expect:              []string{},
   545  			assertImageLabels:   noLabels,
   546  			assertError:         shouldErr("no image templates found"),
   547  			pubAssertError:      shouldNotErr,
   548  			manifestAssertError: shouldNotErr,
   549  		},
   550  		"valid with ids": {
   551  			dockers: []config.Docker{
   552  				{
   553  					ImageTemplates: []string{
   554  						registry + "goreleaser/test_run_pipe_build:latest",
   555  					},
   556  					Goos:       "linux",
   557  					Goarch:     "amd64",
   558  					Dockerfile: "testdata/Dockerfile",
   559  					IDs:        []string{"mybin"},
   560  				},
   561  			},
   562  			expect: []string{
   563  				registry + "goreleaser/test_run_pipe_build:latest",
   564  			},
   565  			assertImageLabels:   noLabels,
   566  			assertError:         shouldNotErr,
   567  			pubAssertError:      shouldNotErr,
   568  			manifestAssertError: shouldNotErr,
   569  		},
   570  		"multiple images with same extra file": {
   571  			dockers: []config.Docker{
   572  				{
   573  					ImageTemplates: []string{
   574  						registry + "goreleaser/multiplefiles1:latest",
   575  					},
   576  					Goos:       "linux",
   577  					Goarch:     "amd64",
   578  					Dockerfile: "testdata/Dockerfile",
   579  					Files:      []string{"testdata/extra_file.txt"},
   580  				},
   581  				{
   582  					ImageTemplates: []string{
   583  						registry + "goreleaser/multiplefiles2:latest",
   584  					},
   585  					Goos:       "linux",
   586  					Goarch:     "amd64",
   587  					Dockerfile: "testdata/Dockerfile",
   588  					Files:      []string{"testdata/extra_file.txt"},
   589  				},
   590  			},
   591  			expect: []string{
   592  				registry + "goreleaser/multiplefiles1:latest",
   593  				registry + "goreleaser/multiplefiles2:latest",
   594  			},
   595  			assertImageLabels:   noLabels,
   596  			assertError:         shouldNotErr,
   597  			pubAssertError:      shouldNotErr,
   598  			manifestAssertError: shouldNotErr,
   599  		},
   600  		"multiple images with same dockerfile": {
   601  			dockers: []config.Docker{
   602  				{
   603  					ImageTemplates: []string{
   604  						registry + "goreleaser/test_run_pipe:latest",
   605  					},
   606  					Goos:       "linux",
   607  					Goarch:     "amd64",
   608  					Dockerfile: "testdata/Dockerfile",
   609  				},
   610  				{
   611  					ImageTemplates: []string{
   612  						registry + "goreleaser/test_run_pipe2:latest",
   613  					},
   614  					Goos:       "linux",
   615  					Goarch:     "amd64",
   616  					Dockerfile: "testdata/Dockerfile",
   617  				},
   618  			},
   619  			assertImageLabels: noLabels,
   620  			expect: []string{
   621  				registry + "goreleaser/test_run_pipe:latest",
   622  				registry + "goreleaser/test_run_pipe2:latest",
   623  			},
   624  			assertError:         shouldNotErr,
   625  			pubAssertError:      shouldNotErr,
   626  			manifestAssertError: shouldNotErr,
   627  		},
   628  		"valid_skip_push": {
   629  			env: map[string]string{"TRUE": "true"},
   630  			dockers: []config.Docker{
   631  				{
   632  					ImageTemplates: []string{
   633  						registry + "goreleaser/test_run_pipe:latest",
   634  					},
   635  					Goos:       "linux",
   636  					Goarch:     "amd64",
   637  					Dockerfile: "testdata/Dockerfile",
   638  					SkipPush:   "{{.Env.TRUE}}",
   639  				},
   640  			},
   641  			expect: []string{
   642  				registry + "goreleaser/test_run_pipe:latest",
   643  			},
   644  			assertImageLabels:   noLabels,
   645  			assertError:         shouldNotErr,
   646  			pubAssertError:      testlib.AssertSkipped,
   647  			manifestAssertError: shouldNotErr,
   648  		},
   649  		"one_img_error_with_skip_push": {
   650  			dockers: []config.Docker{
   651  				{
   652  					ImageTemplates: []string{
   653  						registry + "goreleaser/one_img_error_with_skip_push:true",
   654  					},
   655  					Goos:       "linux",
   656  					Goarch:     "amd64",
   657  					Dockerfile: "testdata/Dockerfile.true",
   658  					SkipPush:   "true",
   659  				},
   660  				{
   661  					ImageTemplates: []string{
   662  						registry + "goreleaser/one_img_error_with_skip_push:false",
   663  					},
   664  					Goos:       "linux",
   665  					Goarch:     "amd64",
   666  					Dockerfile: "testdata/Dockerfile.false",
   667  					SkipPush:   "true",
   668  				},
   669  			},
   670  			expect: []string{
   671  				registry + "goreleaser/one_img_error_with_skip_push:true",
   672  			},
   673  			assertImageLabels: noLabels,
   674  			assertError:       shouldErr("failed to build localhost:5050/goreleaser/one_img_error_with_skip_push:false"),
   675  		},
   676  		"valid_no_latest": {
   677  			dockers: []config.Docker{
   678  				{
   679  					ImageTemplates: []string{
   680  						registry + "goreleaser/test_run_pipe:{{.Version}}",
   681  					},
   682  					Goos:       "linux",
   683  					Goarch:     "amd64",
   684  					Dockerfile: "testdata/Dockerfile",
   685  				},
   686  			},
   687  			expect: []string{
   688  				registry + "goreleaser/test_run_pipe:1.0.0",
   689  			},
   690  			assertImageLabels:   noLabels,
   691  			assertError:         shouldNotErr,
   692  			pubAssertError:      shouldNotErr,
   693  			manifestAssertError: shouldNotErr,
   694  		},
   695  		"valid build args": {
   696  			dockers: []config.Docker{
   697  				{
   698  					ImageTemplates: []string{
   699  						registry + "goreleaser/test_build_args:latest",
   700  					},
   701  					Goos:       "linux",
   702  					Goarch:     "amd64",
   703  					Dockerfile: "testdata/Dockerfile",
   704  					BuildFlagTemplates: []string{
   705  						"--label=foo=bar",
   706  					},
   707  				},
   708  			},
   709  			expect: []string{
   710  				registry + "goreleaser/test_build_args:latest",
   711  			},
   712  			assertImageLabels:   noLabels,
   713  			assertError:         shouldNotErr,
   714  			pubAssertError:      shouldNotErr,
   715  			manifestAssertError: shouldNotErr,
   716  		},
   717  		"bad build args": {
   718  			dockers: []config.Docker{
   719  				{
   720  					ImageTemplates: []string{
   721  						registry + "goreleaser/test_build_args:latest",
   722  					},
   723  					Goos:       "linux",
   724  					Goarch:     "amd64",
   725  					Dockerfile: "testdata/Dockerfile",
   726  					BuildFlagTemplates: []string{
   727  						"--bad-flag",
   728  					},
   729  				},
   730  			},
   731  			assertImageLabels: noLabels,
   732  			assertError:       shouldErr("failed to build localhost:5050/goreleaser/test_build_args:latest"),
   733  		},
   734  		"bad_dockerfile": {
   735  			dockers: []config.Docker{
   736  				{
   737  					ImageTemplates: []string{
   738  						registry + "goreleaser/bad_dockerfile:latest",
   739  					},
   740  					Goos:       "linux",
   741  					Goarch:     "amd64",
   742  					Dockerfile: "testdata/Dockerfile.bad",
   743  				},
   744  			},
   745  			assertImageLabels: noLabels,
   746  			assertError:       shouldErr("failed to build localhost:5050/goreleaser/bad_dockerfile:latest"),
   747  		},
   748  		"tag_template_error": {
   749  			dockers: []config.Docker{
   750  				{
   751  					ImageTemplates: []string{
   752  						registry + "goreleaser/test_run_pipe:{{.Tag}",
   753  					},
   754  					Goos:       "linux",
   755  					Goarch:     "amd64",
   756  					Dockerfile: "testdata/Dockerfile",
   757  				},
   758  			},
   759  			assertImageLabels: noLabels,
   760  			assertError:       shouldTemplateErr,
   761  		},
   762  		"build_flag_template_error": {
   763  			dockers: []config.Docker{
   764  				{
   765  					ImageTemplates: []string{
   766  						registry + "goreleaser/test_run_pipe:latest",
   767  					},
   768  					Goos:       "linux",
   769  					Goarch:     "amd64",
   770  					Dockerfile: "testdata/Dockerfile",
   771  					BuildFlagTemplates: []string{
   772  						"--label=tag={{.Tag}",
   773  					},
   774  				},
   775  			},
   776  			assertImageLabels: noLabels,
   777  			assertError:       shouldTemplateErr,
   778  		},
   779  		"missing_env_on_tag_template": {
   780  			dockers: []config.Docker{
   781  				{
   782  					ImageTemplates: []string{
   783  						registry + "goreleaser/test_run_pipe:{{.Env.NOPE}}",
   784  					},
   785  					Goos:       "linux",
   786  					Goarch:     "amd64",
   787  					Dockerfile: "testdata/Dockerfile",
   788  				},
   789  			},
   790  			assertImageLabels: noLabels,
   791  			assertError:       shouldTemplateErr,
   792  		},
   793  		"missing_env_on_build_flag_template": {
   794  			dockers: []config.Docker{
   795  				{
   796  					ImageTemplates: []string{
   797  						registry + "goreleaser/test_run_pipe:latest",
   798  					},
   799  					Goos:       "linux",
   800  					Goarch:     "amd64",
   801  					Dockerfile: "testdata/Dockerfile",
   802  					BuildFlagTemplates: []string{
   803  						"--label=nope={{.Env.NOPE}}",
   804  					},
   805  				},
   806  			},
   807  			assertImageLabels: noLabels,
   808  			assertError:       shouldTemplateErr,
   809  		},
   810  		"image_has_projectname_template_variable": {
   811  			dockers: []config.Docker{
   812  				{
   813  					ImageTemplates: []string{
   814  						registry + "goreleaser/{{.ProjectName}}:{{.Tag}}-{{.Env.FOO}}",
   815  						registry + "goreleaser/{{.ProjectName}}:latest",
   816  					},
   817  					Goos:       "linux",
   818  					Goarch:     "amd64",
   819  					Dockerfile: "testdata/Dockerfile",
   820  					SkipPush:   "true",
   821  				},
   822  			},
   823  			env: map[string]string{
   824  				"FOO": "123",
   825  			},
   826  			expect: []string{
   827  				registry + "goreleaser/mybin:v1.0.0-123",
   828  				registry + "goreleaser/mybin:latest",
   829  			},
   830  			assertImageLabels:   noLabels,
   831  			assertError:         shouldNotErr,
   832  			pubAssertError:      testlib.AssertSkipped,
   833  			manifestAssertError: shouldNotErr,
   834  		},
   835  		"no_permissions": {
   836  			dockers: []config.Docker{
   837  				{
   838  					ImageTemplates: []string{"docker.io/nope:latest"},
   839  					Goos:           "linux",
   840  					Goarch:         "amd64",
   841  					Dockerfile:     "testdata/Dockerfile",
   842  				},
   843  			},
   844  			expect: []string{
   845  				"docker.io/nope:latest",
   846  			},
   847  			assertImageLabels:   noLabels,
   848  			assertError:         shouldNotErr,
   849  			pubAssertError:      shouldErr(`failed to push docker.io/nope:latest`),
   850  			manifestAssertError: shouldNotErr,
   851  		},
   852  		"dockerfile_doesnt_exist": {
   853  			dockers: []config.Docker{
   854  				{
   855  					ImageTemplates: []string{"whatever:latest"},
   856  					Goos:           "linux",
   857  					Goarch:         "amd64",
   858  					Dockerfile:     "testdata/Dockerfilezzz",
   859  				},
   860  			},
   861  			assertImageLabels: noLabels,
   862  			assertError:       shouldErr(`failed to copy dockerfile`),
   863  		},
   864  		"extra_file_doesnt_exist": {
   865  			dockers: []config.Docker{
   866  				{
   867  					ImageTemplates: []string{"whatever:latest"},
   868  					Goos:           "linux",
   869  					Goarch:         "amd64",
   870  					Dockerfile:     "testdata/Dockerfile",
   871  					Files: []string{
   872  						"testdata/nope.txt",
   873  					},
   874  				},
   875  			},
   876  			assertImageLabels: noLabels,
   877  			assertError:       shouldErr(`failed to copy extra file 'testdata/nope.txt'`),
   878  		},
   879  		"binary doesnt exist": {
   880  			dockers: []config.Docker{
   881  				{
   882  					ImageTemplates: []string{"whatever:latest"},
   883  					Goos:           "linux",
   884  					Goarch:         "amd64",
   885  					Dockerfile:     "testdata/Dockerfile",
   886  					IDs:            []string{"nope"},
   887  				},
   888  			},
   889  			assertImageLabels: noLabels,
   890  			assertError:       shouldErr(`failed to copy wont-exist`),
   891  			extraPrepare: func(t *testing.T, ctx *context.Context) {
   892  				t.Helper()
   893  				ctx.Artifacts.Add(&artifact.Artifact{
   894  					Name:   "wont-exist",
   895  					Path:   "wont-exist",
   896  					Goarch: "amd64",
   897  					Goos:   "linux",
   898  					Type:   artifact.Binary,
   899  					Extra: map[string]interface{}{
   900  						artifact.ExtraID: "nope",
   901  					},
   902  				})
   903  			},
   904  		},
   905  		"multiple_ids": {
   906  			dockers: []config.Docker{
   907  				{
   908  					ImageTemplates: []string{registry + "goreleaser/multiple:latest"},
   909  					Goos:           "darwin",
   910  					Goarch:         "amd64",
   911  					IDs:            []string{"mybin", "anotherbin", "subdir/subbin"},
   912  					Dockerfile:     "testdata/Dockerfile.multiple",
   913  				},
   914  			},
   915  			assertImageLabels:   noLabels,
   916  			assertError:         shouldNotErr,
   917  			pubAssertError:      shouldNotErr,
   918  			manifestAssertError: shouldNotErr,
   919  			expect: []string{
   920  				registry + "goreleaser/multiple:latest",
   921  			},
   922  		},
   923  		"nfpm and multiple binaries": {
   924  			dockers: []config.Docker{
   925  				{
   926  					ImageTemplates: []string{registry + "goreleaser/test_nfpm:latest"},
   927  					Goos:           "linux",
   928  					Goarch:         "amd64",
   929  					IDs:            []string{"mybin", "anotherbin"},
   930  					Dockerfile:     "testdata/Dockerfile.nfpm",
   931  				},
   932  			},
   933  			assertImageLabels:   noLabels,
   934  			assertError:         shouldNotErr,
   935  			pubAssertError:      shouldNotErr,
   936  			manifestAssertError: shouldNotErr,
   937  			expect: []string{
   938  				registry + "goreleaser/test_nfpm:latest",
   939  			},
   940  		},
   941  		"nfpm and multiple binaries on arm64": {
   942  			dockers: []config.Docker{
   943  				{
   944  					ImageTemplates: []string{registry + "goreleaser/test_nfpm_arm:latest"},
   945  					Goos:           "linux",
   946  					Goarch:         "arm64",
   947  					IDs:            []string{"mybin", "anotherbin"},
   948  					Dockerfile:     "testdata/Dockerfile.nfpm",
   949  				},
   950  			},
   951  			assertImageLabels:   noLabels,
   952  			assertError:         shouldNotErr,
   953  			pubAssertError:      shouldNotErr,
   954  			manifestAssertError: shouldNotErr,
   955  			expect: []string{
   956  				registry + "goreleaser/test_nfpm_arm:latest",
   957  			},
   958  		},
   959  	}
   960  
   961  	start(t)
   962  
   963  	for name, docker := range table {
   964  		for imager := range imagers {
   965  			t.Run(name+" on "+imager, func(t *testing.T) {
   966  				folder := t.TempDir()
   967  				dist := filepath.Join(folder, "dist")
   968  				require.NoError(t, os.MkdirAll(filepath.Join(dist, "mybin", "subdir"), 0o755))
   969  				f, err := os.Create(filepath.Join(dist, "mybin", "mybin"))
   970  				require.NoError(t, err)
   971  				require.NoError(t, f.Close())
   972  				f, err = os.Create(filepath.Join(dist, "mybin", "anotherbin"))
   973  				require.NoError(t, err)
   974  				require.NoError(t, f.Close())
   975  				f, err = os.Create(filepath.Join(dist, "mybin", "subdir", "subbin"))
   976  				require.NoError(t, err)
   977  				require.NoError(t, f.Close())
   978  				f, err = os.Create(filepath.Join(dist, "mynfpm.apk"))
   979  				require.NoError(t, err)
   980  				require.NoError(t, f.Close())
   981  				for _, arch := range []string{"amd64", "386", "arm64"} {
   982  					f, err = os.Create(filepath.Join(dist, fmt.Sprintf("mybin_%s.apk", arch)))
   983  					require.NoError(t, err)
   984  					require.NoError(t, f.Close())
   985  				}
   986  
   987  				ctx := testctx.NewWithCfg(
   988  					config.Project{
   989  						ProjectName:     "mybin",
   990  						Dist:            dist,
   991  						Dockers:         docker.dockers,
   992  						DockerManifests: docker.manifests,
   993  					},
   994  					testctx.WithEnv(docker.env),
   995  					testctx.WithVersion("1.0.0"),
   996  					testctx.WithCurrentTag("v1.0.0"),
   997  					testctx.WithCommit("a1b2c3d4"),
   998  					testctx.WithSemver(1, 0, 0, ""),
   999  				)
  1000  				for _, os := range []string{"linux", "darwin"} {
  1001  					for _, arch := range []string{"amd64", "386", "arm64"} {
  1002  						for _, bin := range []string{"mybin", "anotherbin", "subdir/subbin"} {
  1003  							ctx.Artifacts.Add(&artifact.Artifact{
  1004  								Name:   bin,
  1005  								Path:   filepath.Join(dist, "mybin", bin),
  1006  								Goarch: arch,
  1007  								Goos:   os,
  1008  								Type:   artifact.Binary,
  1009  								Extra: map[string]interface{}{
  1010  									artifact.ExtraID: bin,
  1011  								},
  1012  							})
  1013  						}
  1014  					}
  1015  				}
  1016  				for _, arch := range []string{"amd64", "386", "arm64"} {
  1017  					name := fmt.Sprintf("mybin_%s.apk", arch)
  1018  					ctx.Artifacts.Add(&artifact.Artifact{
  1019  						Name:   name,
  1020  						Path:   filepath.Join(dist, name),
  1021  						Goarch: arch,
  1022  						Goos:   "linux",
  1023  						Type:   artifact.LinuxPackage,
  1024  						Extra: map[string]interface{}{
  1025  							artifact.ExtraID: "mybin",
  1026  						},
  1027  					})
  1028  				}
  1029  
  1030  				if docker.extraPrepare != nil {
  1031  					docker.extraPrepare(t, ctx)
  1032  				}
  1033  
  1034  				rmi := func(img string) error {
  1035  					return exec.Command("docker", "rmi", "--force", img).Run()
  1036  				}
  1037  
  1038  				// this might fail as the image doesnt exist yet, so lets ignore the error
  1039  				for _, img := range docker.expect {
  1040  					_ = rmi(img)
  1041  				}
  1042  
  1043  				for i := range ctx.Config.Dockers {
  1044  					docker := &ctx.Config.Dockers[i]
  1045  					docker.Use = imager
  1046  					docker.PushFlags = []string{}
  1047  				}
  1048  				for i := range ctx.Config.DockerManifests {
  1049  					manifest := &ctx.Config.DockerManifests[i]
  1050  					manifest.Use = useDocker
  1051  					manifest.PushFlags = []string{"--insecure"}
  1052  					manifest.CreateFlags = []string{"--insecure"}
  1053  				}
  1054  				err = Pipe{}.Run(ctx)
  1055  				docker.assertError(t, err)
  1056  				if err == nil {
  1057  					docker.pubAssertError(t, Pipe{}.Publish(ctx))
  1058  					docker.manifestAssertError(t, ManifestPipe{}.Publish(ctx))
  1059  				}
  1060  
  1061  				for _, d := range docker.dockers {
  1062  					docker.assertImageLabels(t, d.Use)
  1063  				}
  1064  
  1065  				// this might should not fail as the image should have been created when
  1066  				// the step ran
  1067  				for _, img := range docker.expect {
  1068  					// t.Log("removing docker image", img)
  1069  					require.NoError(t, rmi(img), "could not delete image %s", img)
  1070  				}
  1071  
  1072  				_ = ctx.Artifacts.Filter(
  1073  					artifact.Or(
  1074  						artifact.ByType(artifact.DockerImage),
  1075  						artifact.ByType(artifact.DockerManifest),
  1076  					),
  1077  				).Visit(func(a *artifact.Artifact) error {
  1078  					digest, err := artifact.Extra[string](*a, artifact.ExtraDigest)
  1079  					require.NoError(t, err)
  1080  					require.NotEmpty(t, digest, "missing digest for "+a.Name)
  1081  					return nil
  1082  				})
  1083  			})
  1084  		}
  1085  	}
  1086  }
  1087  
  1088  func TestBuildCommand(t *testing.T) {
  1089  	images := []string{"goreleaser/test_build_flag", "goreleaser/test_multiple_tags"}
  1090  	tests := []struct {
  1091  		name   string
  1092  		flags  []string
  1093  		buildx bool
  1094  		expect []string
  1095  	}{
  1096  		{
  1097  			name:   "no flags",
  1098  			flags:  []string{},
  1099  			expect: []string{"build", ".", "-t", images[0], "-t", images[1]},
  1100  		},
  1101  		{
  1102  			name:   "single flag",
  1103  			flags:  []string{"--label=foo"},
  1104  			expect: []string{"build", ".", "-t", images[0], "-t", images[1], "--label=foo"},
  1105  		},
  1106  		{
  1107  			name:   "multiple flags",
  1108  			flags:  []string{"--label=foo", "--build-arg=bar=baz"},
  1109  			expect: []string{"build", ".", "-t", images[0], "-t", images[1], "--label=foo", "--build-arg=bar=baz"},
  1110  		},
  1111  		{
  1112  			name:   "buildx",
  1113  			buildx: true,
  1114  			flags:  []string{"--label=foo", "--build-arg=bar=baz"},
  1115  			expect: []string{"buildx", "build", ".", "--load", "-t", images[0], "-t", images[1], "--label=foo", "--build-arg=bar=baz"},
  1116  		},
  1117  	}
  1118  	for _, tt := range tests {
  1119  		t.Run(tt.name, func(t *testing.T) {
  1120  			imager := dockerImager{
  1121  				buildx: tt.buildx,
  1122  			}
  1123  			require.Equal(t, tt.expect, imager.buildCommand(images, tt.flags))
  1124  		})
  1125  	}
  1126  }
  1127  
  1128  func TestDescription(t *testing.T) {
  1129  	require.NotEmpty(t, Pipe{}.String())
  1130  }
  1131  
  1132  func TestNoDockerWithoutImageName(t *testing.T) {
  1133  	testlib.AssertSkipped(t, Pipe{}.Run(testctx.NewWithCfg(config.Project{
  1134  		Dockers: []config.Docker{
  1135  			{
  1136  				Goos: "linux",
  1137  			},
  1138  		},
  1139  	})))
  1140  }
  1141  
  1142  func TestDefault(t *testing.T) {
  1143  	ctx := testctx.NewWithCfg(config.Project{
  1144  		Dockers: []config.Docker{
  1145  			{
  1146  				IDs: []string{"aa"},
  1147  			},
  1148  			{
  1149  				Use: useBuildx,
  1150  			},
  1151  		},
  1152  		DockerManifests: []config.DockerManifest{
  1153  			{},
  1154  			{
  1155  				Use: useDocker,
  1156  			},
  1157  		},
  1158  	})
  1159  	require.NoError(t, Pipe{}.Default(ctx))
  1160  	require.Len(t, ctx.Config.Dockers, 2)
  1161  	docker := ctx.Config.Dockers[0]
  1162  	require.Equal(t, "linux", docker.Goos)
  1163  	require.Equal(t, "amd64", docker.Goarch)
  1164  	require.Equal(t, "6", docker.Goarm)
  1165  	require.Equal(t, []string{"aa"}, docker.IDs)
  1166  	require.Equal(t, useDocker, docker.Use)
  1167  	docker = ctx.Config.Dockers[1]
  1168  	require.Equal(t, useBuildx, docker.Use)
  1169  
  1170  	require.NoError(t, ManifestPipe{}.Default(ctx))
  1171  	require.Len(t, ctx.Config.DockerManifests, 2)
  1172  	require.Equal(t, useDocker, ctx.Config.DockerManifests[0].Use)
  1173  	require.Equal(t, useDocker, ctx.Config.DockerManifests[1].Use)
  1174  }
  1175  
  1176  func TestDefaultDuplicateID(t *testing.T) {
  1177  	ctx := testctx.NewWithCfg(config.Project{
  1178  		Dockers: []config.Docker{
  1179  			{ID: "foo"},
  1180  			{ /* empty */ },
  1181  			{ID: "bar"},
  1182  			{ID: "foo"},
  1183  		},
  1184  		DockerManifests: []config.DockerManifest{
  1185  			{ID: "bar"},
  1186  			{ /* empty */ },
  1187  			{ID: "bar"},
  1188  			{ID: "foo"},
  1189  		},
  1190  	})
  1191  	require.EqualError(t, Pipe{}.Default(ctx), "found 2 dockers with the ID 'foo', please fix your config")
  1192  	require.EqualError(t, ManifestPipe{}.Default(ctx), "found 2 docker_manifests with the ID 'bar', please fix your config")
  1193  }
  1194  
  1195  func TestDefaultInvalidUse(t *testing.T) {
  1196  	ctx := testctx.NewWithCfg(config.Project{
  1197  		Dockers: []config.Docker{
  1198  			{
  1199  				Use: "something",
  1200  			},
  1201  		},
  1202  		DockerManifests: []config.DockerManifest{
  1203  			{
  1204  				Use: "something",
  1205  			},
  1206  		},
  1207  	})
  1208  	err := Pipe{}.Default(ctx)
  1209  	require.Error(t, err)
  1210  	require.True(t, strings.HasPrefix(err.Error(), `docker: invalid use: something, valid options are`))
  1211  
  1212  	err = ManifestPipe{}.Default(ctx)
  1213  	require.Error(t, err)
  1214  	require.True(t, strings.HasPrefix(err.Error(), `docker manifest: invalid use: something, valid options are`))
  1215  }
  1216  
  1217  func TestDefaultDockerfile(t *testing.T) {
  1218  	ctx := testctx.NewWithCfg(config.Project{
  1219  		Builds: []config.Build{
  1220  			{},
  1221  		},
  1222  		Dockers: []config.Docker{
  1223  			{},
  1224  			{},
  1225  		},
  1226  	})
  1227  	require.NoError(t, Pipe{}.Default(ctx))
  1228  	require.Len(t, ctx.Config.Dockers, 2)
  1229  	require.Equal(t, "Dockerfile", ctx.Config.Dockers[0].Dockerfile)
  1230  	require.Equal(t, "Dockerfile", ctx.Config.Dockers[1].Dockerfile)
  1231  }
  1232  
  1233  func TestDraftRelease(t *testing.T) {
  1234  	ctx := testctx.NewWithCfg(config.Project{
  1235  		Release: config.Release{
  1236  			Draft: true,
  1237  		},
  1238  	})
  1239  
  1240  	require.False(t, pipe.IsSkip(Pipe{}.Publish(ctx)))
  1241  }
  1242  
  1243  func TestDefaultNoDockers(t *testing.T) {
  1244  	ctx := testctx.NewWithCfg(config.Project{
  1245  		Dockers: []config.Docker{},
  1246  	})
  1247  	require.NoError(t, Pipe{}.Default(ctx))
  1248  	require.Empty(t, ctx.Config.Dockers)
  1249  }
  1250  
  1251  func TestDefaultFilesDot(t *testing.T) {
  1252  	ctx := testctx.NewWithCfg(config.Project{
  1253  		Dist: "/tmp/distt",
  1254  		Dockers: []config.Docker{
  1255  			{
  1256  				Files: []string{"./lala", "./lolsob", "."},
  1257  			},
  1258  		},
  1259  	})
  1260  	require.NoError(t, Pipe{}.Default(ctx))
  1261  }
  1262  
  1263  func TestDefaultFilesDis(t *testing.T) {
  1264  	ctx := testctx.NewWithCfg(config.Project{
  1265  		Dist: "/tmp/dist",
  1266  		Dockers: []config.Docker{
  1267  			{
  1268  				Files: []string{"./fooo", "/tmp/dist/asdasd/asd", "./bar"},
  1269  			},
  1270  		},
  1271  	})
  1272  	require.NoError(t, Pipe{}.Default(ctx))
  1273  }
  1274  
  1275  func TestDefaultSet(t *testing.T) {
  1276  	ctx := testctx.NewWithCfg(config.Project{
  1277  		Dockers: []config.Docker{
  1278  			{
  1279  				IDs:        []string{"foo"},
  1280  				Goos:       "windows",
  1281  				Goarch:     "i386",
  1282  				Dockerfile: "Dockerfile.foo",
  1283  			},
  1284  		},
  1285  	})
  1286  	require.NoError(t, Pipe{}.Default(ctx))
  1287  	require.Len(t, ctx.Config.Dockers, 1)
  1288  	docker := ctx.Config.Dockers[0]
  1289  	require.Equal(t, "windows", docker.Goos)
  1290  	require.Equal(t, "i386", docker.Goarch)
  1291  	require.Equal(t, []string{"foo"}, docker.IDs)
  1292  	require.Equal(t, "Dockerfile.foo", docker.Dockerfile)
  1293  }
  1294  
  1295  func Test_processImageTemplates(t *testing.T) {
  1296  	ctx := testctx.NewWithCfg(
  1297  		config.Project{
  1298  			Builds: []config.Build{
  1299  				{
  1300  					ID: "default",
  1301  				},
  1302  			},
  1303  			Dockers: []config.Docker{
  1304  				{
  1305  					Dockerfile: "Dockerfile.foo",
  1306  					ImageTemplates: []string{
  1307  						"user/image:{{.Tag}}",
  1308  						"gcr.io/image:{{.Tag}}-{{.Env.FOO}}",
  1309  						"gcr.io/image:v{{.Major}}.{{.Minor}}",
  1310  					},
  1311  					SkipPush: "true",
  1312  				},
  1313  			},
  1314  			Env: []string{"FOO=123"},
  1315  		},
  1316  		testctx.WithVersion("1.0.0"),
  1317  		testctx.WithCurrentTag("v1.0.0"),
  1318  		testctx.WithCommit("a1b2c3d4"),
  1319  		testctx.WithSemver(1, 0, 0, ""),
  1320  	)
  1321  
  1322  	require.NoError(t, Pipe{}.Default(ctx))
  1323  	require.Len(t, ctx.Config.Dockers, 1)
  1324  
  1325  	docker := ctx.Config.Dockers[0]
  1326  	require.Equal(t, "Dockerfile.foo", docker.Dockerfile)
  1327  
  1328  	images, err := processImageTemplates(ctx, docker)
  1329  	require.NoError(t, err)
  1330  	require.Equal(t, []string{
  1331  		"user/image:v1.0.0",
  1332  		"gcr.io/image:v1.0.0-123",
  1333  		"gcr.io/image:v1.0",
  1334  	}, images)
  1335  }
  1336  
  1337  func TestSkip(t *testing.T) {
  1338  	t.Run("image", func(t *testing.T) {
  1339  		t.Run("skip", func(t *testing.T) {
  1340  			require.True(t, Pipe{}.Skip(testctx.New()))
  1341  		})
  1342  
  1343  		t.Run("skip docker", func(t *testing.T) {
  1344  			ctx := testctx.NewWithCfg(config.Project{
  1345  				Dockers: []config.Docker{{}},
  1346  			}, testctx.Skip(skips.Docker))
  1347  			require.True(t, Pipe{}.Skip(ctx))
  1348  		})
  1349  
  1350  		t.Run("dont skip", func(t *testing.T) {
  1351  			ctx := testctx.NewWithCfg(config.Project{
  1352  				Dockers: []config.Docker{{}},
  1353  			})
  1354  			require.False(t, Pipe{}.Skip(ctx))
  1355  		})
  1356  	})
  1357  
  1358  	t.Run("manifest", func(t *testing.T) {
  1359  		t.Run("skip", func(t *testing.T) {
  1360  			require.True(t, ManifestPipe{}.Skip(testctx.New()))
  1361  		})
  1362  
  1363  		t.Run("skip docker", func(t *testing.T) {
  1364  			ctx := testctx.NewWithCfg(config.Project{
  1365  				DockerManifests: []config.DockerManifest{{}},
  1366  			}, testctx.Skip(skips.Docker))
  1367  			require.True(t, ManifestPipe{}.Skip(ctx))
  1368  		})
  1369  
  1370  		t.Run("dont skip", func(t *testing.T) {
  1371  			ctx := testctx.NewWithCfg(config.Project{
  1372  				DockerManifests: []config.DockerManifest{{}},
  1373  			})
  1374  			require.False(t, ManifestPipe{}.Skip(ctx))
  1375  		})
  1376  	})
  1377  }
  1378  
  1379  func TestWithDigest(t *testing.T) {
  1380  	artifacts := artifact.New()
  1381  	artifacts.Add(&artifact.Artifact{
  1382  		Name: "localhost:5050/owner/img:t1",
  1383  		Type: artifact.DockerImage,
  1384  		Extra: artifact.Extras{
  1385  			artifact.ExtraDigest: "sha256:d1",
  1386  		},
  1387  	})
  1388  	artifacts.Add(&artifact.Artifact{
  1389  		Name: "localhost:5050/owner/img:t2",
  1390  		Type: artifact.DockerImage,
  1391  		Extra: artifact.Extras{
  1392  			artifact.ExtraDigest: "sha256:d2",
  1393  		},
  1394  	})
  1395  	artifacts.Add(&artifact.Artifact{
  1396  		Name: "localhost:5050/owner/img:t3",
  1397  		Type: artifact.DockerImage,
  1398  	})
  1399  
  1400  	for _, use := range []string{useDocker, useBuildx} {
  1401  		use := use
  1402  		t.Run(use, func(t *testing.T) {
  1403  			t.Run("good", func(t *testing.T) {
  1404  				require.Equal(t, "localhost:5050/owner/img:t1@sha256:d1", withDigest(use, "localhost:5050/owner/img:t1", artifacts.List()))
  1405  			})
  1406  
  1407  			t.Run("no digest", func(t *testing.T) {
  1408  				require.Equal(t, "localhost:5050/owner/img:t3", withDigest(use, "localhost:5050/owner/img:t3", artifacts.List()))
  1409  			})
  1410  
  1411  			t.Run("no match", func(t *testing.T) {
  1412  				require.Equal(t, "localhost:5050/owner/img:t4", withDigest(use, "localhost:5050/owner/img:t4", artifacts.List()))
  1413  			})
  1414  		})
  1415  	}
  1416  }
  1417  
  1418  func TestDependencies(t *testing.T) {
  1419  	ctx := testctx.NewWithCfg(config.Project{
  1420  		Dockers: []config.Docker{
  1421  			{Use: useBuildx},
  1422  			{Use: useDocker},
  1423  			{Use: "nope"},
  1424  		},
  1425  		DockerManifests: []config.DockerManifest{
  1426  			{Use: useBuildx},
  1427  			{Use: useDocker},
  1428  			{Use: "nope"},
  1429  		},
  1430  	})
  1431  	require.Equal(t, []string{"docker", "docker"}, Pipe{}.Dependencies(ctx))
  1432  	require.Equal(t, []string{"docker", "docker"}, ManifestPipe{}.Dependencies(ctx))
  1433  }
  1434  
  1435  func TestIsFileNotFoundError(t *testing.T) {
  1436  	t.Run("executable not in path", func(t *testing.T) {
  1437  		require.False(t, isFileNotFoundError(`error getting credentials - err: exec: "docker-credential-desktop": executable file not found in $PATH, out:`))
  1438  	})
  1439  
  1440  	t.Run("file not found", func(t *testing.T) {
  1441  		require.True(t, isFileNotFoundError(`./foo: file not found`))
  1442  		require.True(t, isFileNotFoundError(`./foo: not found: not found`))
  1443  	})
  1444  }