mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 18:13:42 +08:00 
			
		
		
		
	This changes how the composable attributes are implemented and provides various fixes to the first iteration. Cache-from and cache-to now no longer print sensitive values that are automatically added. These automatically added attributes are added when the protobuf is created rather than at the time of parsing so they will no longer be printed. If they are part of the original configuration file, they will still be printed. Empty strings will now be skipped. This was the original behavior and composable attributes removed this functionality accidentally. This functionality is now restored. This also expands the available syntax that works with each of the composable attributes. It is now possible to interleave the csv syntax with the object syntax without any problems. The canonical form is still the object syntax and variables are resolved according to that syntax. Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
		
			
				
	
	
		
			1877 lines
		
	
	
		
			47 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			1877 lines
		
	
	
		
			47 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package tests
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"encoding/json"
 | 
						|
	"fmt"
 | 
						|
	"os"
 | 
						|
	"path/filepath"
 | 
						|
	"strconv"
 | 
						|
	"strings"
 | 
						|
	"testing"
 | 
						|
 | 
						|
	"github.com/containerd/continuity/fs/fstest"
 | 
						|
	"github.com/docker/buildx/bake"
 | 
						|
	"github.com/docker/buildx/util/gitutil"
 | 
						|
	"github.com/moby/buildkit/client"
 | 
						|
	"github.com/moby/buildkit/frontend/subrequests/lint"
 | 
						|
	"github.com/moby/buildkit/identity"
 | 
						|
	provenancetypes "github.com/moby/buildkit/solver/llbsolver/provenance/types"
 | 
						|
	"github.com/moby/buildkit/util/contentutil"
 | 
						|
	"github.com/moby/buildkit/util/testutil"
 | 
						|
	"github.com/moby/buildkit/util/testutil/integration"
 | 
						|
	"github.com/pkg/errors"
 | 
						|
	"github.com/stretchr/testify/require"
 | 
						|
)
 | 
						|
 | 
						|
func bakeCmd(sb integration.Sandbox, opts ...cmdOpt) (string, error) {
 | 
						|
	opts = append([]cmdOpt{withArgs("bake", "--progress=quiet")}, opts...)
 | 
						|
	cmd := buildxCmd(sb, opts...)
 | 
						|
	out, err := cmd.CombinedOutput()
 | 
						|
	return string(out), err
 | 
						|
}
 | 
						|
 | 
						|
var bakeTests = []func(t *testing.T, sb integration.Sandbox){
 | 
						|
	testBakePrint,
 | 
						|
	testBakePrintSensitive,
 | 
						|
	testBakeLocal,
 | 
						|
	testBakeLocalMulti,
 | 
						|
	testBakeRemote,
 | 
						|
	testBakeRemoteAuth,
 | 
						|
	testBakeRemoteCmdContext,
 | 
						|
	testBakeRemoteLocalOverride,
 | 
						|
	testBakeLocalCwdOverride,
 | 
						|
	testBakeRemoteCmdContextOverride,
 | 
						|
	testBakeRemoteContextSubdir,
 | 
						|
	testBakeRemoteCmdContextEscapeRoot,
 | 
						|
	testBakeRemoteCmdContextEscapeRelative,
 | 
						|
	testBakeRemoteDockerfileCwd,
 | 
						|
	testBakeRemoteLocalContextRemoteDockerfile,
 | 
						|
	testBakeEmpty,
 | 
						|
	testBakeSetNonExistingSubdirNoParallel,
 | 
						|
	testBakeSetNonExistingOutsideNoParallel,
 | 
						|
	testBakeSetExistingOutsideNoParallel,
 | 
						|
	testBakeDefinitionNotExistingSubdirNoParallel,
 | 
						|
	testBakeDefinitionNotExistingOutsideNoParallel,
 | 
						|
	testBakeDefinitionExistingOutsideNoParallel,
 | 
						|
	testBakeDefinitionSymlinkOutsideNoParallel,
 | 
						|
	testBakeDefinitionSymlinkOutsideGrantedNoParallel,
 | 
						|
	testBakeShmSize,
 | 
						|
	testBakeUlimits,
 | 
						|
	testBakeMetadataProvenance,
 | 
						|
	testBakeMetadataWarnings,
 | 
						|
	testBakeMetadataWarningsDedup,
 | 
						|
	testBakeMultiExporters,
 | 
						|
	testBakeLoadPush,
 | 
						|
	testListTargets,
 | 
						|
	testListVariables,
 | 
						|
	testBakeCallCheck,
 | 
						|
	testBakeCallCheckFlag,
 | 
						|
	testBakeCallMetadata,
 | 
						|
	testBakeMultiPlatform,
 | 
						|
	testBakeCheckCallOutput,
 | 
						|
}
 | 
						|
 | 
						|
func testBakePrint(t *testing.T, sb integration.Sandbox) {
 | 
						|
	testCases := []struct {
 | 
						|
		name string
 | 
						|
		f    string
 | 
						|
		dt   []byte
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			"HCL",
 | 
						|
			"docker-bake.hcl",
 | 
						|
			[]byte(`
 | 
						|
target "build" {
 | 
						|
  args = {
 | 
						|
    HELLO = "foo"
 | 
						|
  }
 | 
						|
}
 | 
						|
`),
 | 
						|
		},
 | 
						|
		{
 | 
						|
			"Compose",
 | 
						|
			"compose.yml",
 | 
						|
			[]byte(`
 | 
						|
services:
 | 
						|
  build:
 | 
						|
    build:
 | 
						|
      context: .
 | 
						|
      args:
 | 
						|
        HELLO: foo
 | 
						|
`),
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, tc := range testCases {
 | 
						|
		t.Run(tc.name, func(t *testing.T) {
 | 
						|
			dir := tmpdir(
 | 
						|
				t,
 | 
						|
				fstest.CreateFile(tc.f, tc.dt, 0600),
 | 
						|
				fstest.CreateFile("Dockerfile", []byte(`
 | 
						|
FROM busybox
 | 
						|
ARG HELLO
 | 
						|
RUN echo "Hello ${HELLO}"
 | 
						|
	`), 0600),
 | 
						|
			)
 | 
						|
 | 
						|
			cmd := buildxCmd(sb, withDir(dir), withArgs("bake", "--print", "build"))
 | 
						|
			stdout := bytes.Buffer{}
 | 
						|
			stderr := bytes.Buffer{}
 | 
						|
			cmd.Stdout = &stdout
 | 
						|
			cmd.Stderr = &stderr
 | 
						|
			require.NoError(t, cmd.Run(), stdout.String(), stderr.String())
 | 
						|
 | 
						|
			var def struct {
 | 
						|
				Group  map[string]*bake.Group  `json:"group,omitempty"`
 | 
						|
				Target map[string]*bake.Target `json:"target"`
 | 
						|
			}
 | 
						|
			require.NoError(t, json.Unmarshal(stdout.Bytes(), &def))
 | 
						|
 | 
						|
			require.Len(t, def.Group, 1)
 | 
						|
			require.Contains(t, def.Group, "default")
 | 
						|
 | 
						|
			require.Equal(t, []string{"build"}, def.Group["default"].Targets)
 | 
						|
			require.Len(t, def.Target, 1)
 | 
						|
			require.Contains(t, def.Target, "build")
 | 
						|
			require.Equal(t, ".", *def.Target["build"].Context)
 | 
						|
			require.Equal(t, "Dockerfile", *def.Target["build"].Dockerfile)
 | 
						|
			require.Equal(t, map[string]*string{"HELLO": ptrstr("foo")}, def.Target["build"].Args)
 | 
						|
 | 
						|
			require.JSONEq(t, `{
 | 
						|
  "group": {
 | 
						|
    "default": {
 | 
						|
      "targets": [
 | 
						|
        "build"
 | 
						|
      ]
 | 
						|
    }
 | 
						|
  },
 | 
						|
  "target": {
 | 
						|
    "build": {
 | 
						|
      "context": ".",
 | 
						|
      "dockerfile": "Dockerfile",
 | 
						|
      "args": {
 | 
						|
        "HELLO": "foo"
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
`, stdout.String())
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func testBakePrintSensitive(t *testing.T, sb integration.Sandbox) {
 | 
						|
	testCases := []struct {
 | 
						|
		name string
 | 
						|
		f    string
 | 
						|
		dt   []byte
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			"HCL",
 | 
						|
			"docker-bake.hcl",
 | 
						|
			[]byte(`
 | 
						|
target "build" {
 | 
						|
  args = {
 | 
						|
    HELLO = "foo"
 | 
						|
  }
 | 
						|
 | 
						|
  cache-from = [
 | 
						|
    "type=gha,token=abc",
 | 
						|
    "type=s3,region=us-west-2,bucket=my_bucket,name=my_image",
 | 
						|
  ]
 | 
						|
}
 | 
						|
`),
 | 
						|
		},
 | 
						|
		{
 | 
						|
			"Compose",
 | 
						|
			"compose.yml",
 | 
						|
			[]byte(`
 | 
						|
services:
 | 
						|
  build:
 | 
						|
    build:
 | 
						|
      context: .
 | 
						|
      args:
 | 
						|
        HELLO: foo
 | 
						|
      cache_from:
 | 
						|
        - type=gha,token=abc
 | 
						|
        - type=s3,region=us-west-2,bucket=my_bucket,name=my_image
 | 
						|
`),
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, tc := range testCases {
 | 
						|
		t.Run(tc.name, func(t *testing.T) {
 | 
						|
			dir := tmpdir(
 | 
						|
				t,
 | 
						|
				fstest.CreateFile(tc.f, tc.dt, 0600),
 | 
						|
				fstest.CreateFile("Dockerfile", []byte(`
 | 
						|
FROM busybox
 | 
						|
ARG HELLO
 | 
						|
RUN echo "Hello ${HELLO}"
 | 
						|
	`), 0600),
 | 
						|
			)
 | 
						|
 | 
						|
			cmd := buildxCmd(sb, withDir(dir), withArgs("bake", "--print", "build"),
 | 
						|
				withEnv(
 | 
						|
					"ACTIONS_RUNTIME_TOKEN=sensitive_token",
 | 
						|
					"ACTIONS_CACHE_URL=https://cache.github.com",
 | 
						|
					"AWS_ACCESS_KEY_ID=definitely_dont_look_here",
 | 
						|
					"AWS_SECRET_ACCESS_KEY=hackers_please_dont_steal",
 | 
						|
					"AWS_SESSION_TOKEN=not_a_mitm_attack",
 | 
						|
				),
 | 
						|
			)
 | 
						|
			stdout := bytes.Buffer{}
 | 
						|
			stderr := bytes.Buffer{}
 | 
						|
			cmd.Stdout = &stdout
 | 
						|
			cmd.Stderr = &stderr
 | 
						|
			require.NoError(t, cmd.Run(), stdout.String(), stderr.String())
 | 
						|
 | 
						|
			var def struct {
 | 
						|
				Group  map[string]*bake.Group  `json:"group,omitempty"`
 | 
						|
				Target map[string]*bake.Target `json:"target"`
 | 
						|
			}
 | 
						|
			require.NoError(t, json.Unmarshal(stdout.Bytes(), &def))
 | 
						|
 | 
						|
			require.Len(t, def.Group, 1)
 | 
						|
			require.Contains(t, def.Group, "default")
 | 
						|
 | 
						|
			require.Equal(t, []string{"build"}, def.Group["default"].Targets)
 | 
						|
			require.Len(t, def.Target, 1)
 | 
						|
			require.Contains(t, def.Target, "build")
 | 
						|
			require.Equal(t, ".", *def.Target["build"].Context)
 | 
						|
			require.Equal(t, "Dockerfile", *def.Target["build"].Dockerfile)
 | 
						|
			require.Equal(t, map[string]*string{"HELLO": ptrstr("foo")}, def.Target["build"].Args)
 | 
						|
			require.NotNil(t, def.Target["build"].CacheFrom)
 | 
						|
			require.Len(t, def.Target["build"].CacheFrom, 2)
 | 
						|
 | 
						|
			require.JSONEq(t, `{
 | 
						|
  "group": {
 | 
						|
    "default": {
 | 
						|
      "targets": [
 | 
						|
        "build"
 | 
						|
      ]
 | 
						|
    }
 | 
						|
  },
 | 
						|
  "target": {
 | 
						|
    "build": {
 | 
						|
      "context": ".",
 | 
						|
      "dockerfile": "Dockerfile",
 | 
						|
      "args": {
 | 
						|
        "HELLO": "foo"
 | 
						|
      },
 | 
						|
      "cache-from": [
 | 
						|
        {
 | 
						|
          "type": "gha",
 | 
						|
          "token": "abc"
 | 
						|
        },
 | 
						|
        {
 | 
						|
          "type": "s3",
 | 
						|
          "region": "us-west-2",
 | 
						|
          "bucket": "my_bucket",
 | 
						|
          "name": "my_image"
 | 
						|
        }
 | 
						|
      ]
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
`, stdout.String())
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func testBakeLocal(t *testing.T, sb integration.Sandbox) {
 | 
						|
	dockerfile := []byte(`
 | 
						|
FROM scratch
 | 
						|
COPY foo /foo
 | 
						|
	`)
 | 
						|
	bakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
}
 | 
						|
`)
 | 
						|
	dir := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
		fstest.CreateFile("foo", []byte("foo"), 0600),
 | 
						|
	)
 | 
						|
 | 
						|
	dirDest := t.TempDir()
 | 
						|
 | 
						|
	cmd := buildxCmd(sb, withDir(dir), withArgs("bake", "--progress=plain", "--set", "*.output=type=local,dest="+dirDest))
 | 
						|
	out, err := cmd.CombinedOutput()
 | 
						|
	require.NoError(t, err, string(out))
 | 
						|
	require.Contains(t, string(out), `#1 [internal] load local bake definitions`)
 | 
						|
	require.Contains(t, string(out), `#1 reading docker-bake.hcl`)
 | 
						|
 | 
						|
	require.FileExists(t, filepath.Join(dirDest, "foo"))
 | 
						|
}
 | 
						|
 | 
						|
func testBakeLocalMulti(t *testing.T, sb integration.Sandbox) {
 | 
						|
	dockerfile := []byte(`
 | 
						|
FROM scratch
 | 
						|
COPY foo /foo
 | 
						|
	`)
 | 
						|
	bakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
}
 | 
						|
`)
 | 
						|
	composefile := []byte(`
 | 
						|
services:
 | 
						|
  app:
 | 
						|
    build: {}
 | 
						|
`)
 | 
						|
 | 
						|
	dir := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
		fstest.CreateFile("compose.yaml", composefile, 0600),
 | 
						|
		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
		fstest.CreateFile("foo", []byte("foo"), 0600),
 | 
						|
	)
 | 
						|
 | 
						|
	dirDest := t.TempDir()
 | 
						|
 | 
						|
	cmd := buildxCmd(sb, withDir(dir), withArgs("bake", "--progress=plain", "--set", "*.output=type=local,dest="+dirDest))
 | 
						|
	dt, err := cmd.CombinedOutput()
 | 
						|
	require.NoError(t, err, string(dt))
 | 
						|
	require.Contains(t, string(dt), `#1 [internal] load local bake definitions`)
 | 
						|
	require.Contains(t, string(dt), `#1 reading compose.yaml`)
 | 
						|
	require.Contains(t, string(dt), `#1 reading docker-bake.hcl`)
 | 
						|
	require.FileExists(t, filepath.Join(dirDest, "foo"))
 | 
						|
 | 
						|
	dirDest2 := t.TempDir()
 | 
						|
 | 
						|
	out, err := bakeCmd(sb, withDir(dir), withArgs("--file", "cwd://docker-bake.hcl", "--set", "*.output=type=local,dest="+dirDest2))
 | 
						|
	require.NoError(t, err, out)
 | 
						|
 | 
						|
	require.FileExists(t, filepath.Join(dirDest2, "foo"))
 | 
						|
}
 | 
						|
 | 
						|
func testBakeRemote(t *testing.T, sb integration.Sandbox) {
 | 
						|
	bakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
	dockerfile-inline = <<EOT
 | 
						|
FROM scratch
 | 
						|
COPY foo /foo
 | 
						|
EOT
 | 
						|
}
 | 
						|
`)
 | 
						|
	dir := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
		fstest.CreateFile("foo", []byte("foo"), 0600),
 | 
						|
	)
 | 
						|
	dirDest := t.TempDir()
 | 
						|
 | 
						|
	git, err := gitutil.New(gitutil.WithWorkingDir(dir))
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	gitutil.GitInit(git, t)
 | 
						|
	gitutil.GitAdd(git, t, "docker-bake.hcl", "foo")
 | 
						|
	gitutil.GitCommit(git, t, "initial commit")
 | 
						|
	addr := gitutil.GitServeHTTP(git, t)
 | 
						|
 | 
						|
	out, err := bakeCmd(sb, withDir(dir), withArgs(addr, "--set", "*.output=type=local,dest="+dirDest))
 | 
						|
	require.NoError(t, err, out)
 | 
						|
 | 
						|
	require.FileExists(t, filepath.Join(dirDest, "foo"))
 | 
						|
}
 | 
						|
 | 
						|
func testBakeRemoteAuth(t *testing.T, sb integration.Sandbox) {
 | 
						|
	bakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
	dockerfile-inline = <<EOT
 | 
						|
FROM scratch
 | 
						|
COPY foo /foo
 | 
						|
EOT
 | 
						|
}
 | 
						|
`)
 | 
						|
	dir := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
		fstest.CreateFile("foo", []byte("foo"), 0600),
 | 
						|
	)
 | 
						|
	dirDest := t.TempDir()
 | 
						|
 | 
						|
	git, err := gitutil.New(gitutil.WithWorkingDir(dir))
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	gitutil.GitInit(git, t)
 | 
						|
	gitutil.GitAdd(git, t, "docker-bake.hcl", "foo")
 | 
						|
	gitutil.GitCommit(git, t, "initial commit")
 | 
						|
 | 
						|
	token := identity.NewID()
 | 
						|
	addr := gitutil.GitServeHTTP(git, t, gitutil.WithAccessToken(token))
 | 
						|
 | 
						|
	out, err := bakeCmd(sb, withDir(dir),
 | 
						|
		withEnv("BUILDX_BAKE_GIT_AUTH_TOKEN="+token),
 | 
						|
		withArgs(addr, "--set", "*.output=type=local,dest="+dirDest),
 | 
						|
	)
 | 
						|
	require.NoError(t, err, out)
 | 
						|
 | 
						|
	require.FileExists(t, filepath.Join(dirDest, "foo"))
 | 
						|
}
 | 
						|
 | 
						|
func testBakeRemoteLocalOverride(t *testing.T, sb integration.Sandbox) {
 | 
						|
	remoteBakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
	dockerfile-inline = <<EOT
 | 
						|
FROM scratch
 | 
						|
COPY foo /foo
 | 
						|
EOT
 | 
						|
}
 | 
						|
`)
 | 
						|
	localBakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
	dockerfile-inline = <<EOT
 | 
						|
FROM scratch
 | 
						|
COPY bar /bar
 | 
						|
EOT
 | 
						|
}
 | 
						|
`)
 | 
						|
	dirSpec := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", remoteBakefile, 0600),
 | 
						|
		fstest.CreateFile("bar", []byte("bar"), 0600),
 | 
						|
	)
 | 
						|
	dirSrc := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("local-docker-bake.hcl", localBakefile, 0600),
 | 
						|
	)
 | 
						|
	dirDest := t.TempDir()
 | 
						|
 | 
						|
	git, err := gitutil.New(gitutil.WithWorkingDir(dirSpec))
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	gitutil.GitInit(git, t)
 | 
						|
	gitutil.GitAdd(git, t, "docker-bake.hcl", "bar")
 | 
						|
	gitutil.GitCommit(git, t, "initial commit")
 | 
						|
	addr := gitutil.GitServeHTTP(git, t)
 | 
						|
 | 
						|
	out, err := bakeCmd(sb, withDir(dirSrc), withArgs(addr, "--file", "cwd://local-docker-bake.hcl", "--set", "*.output=type=local,dest="+dirDest))
 | 
						|
	require.NoError(t, err, out)
 | 
						|
 | 
						|
	require.FileExists(t, filepath.Join(dirDest, "bar"))
 | 
						|
}
 | 
						|
 | 
						|
func testBakeLocalCwdOverride(t *testing.T, sb integration.Sandbox) {
 | 
						|
	bakeFile := []byte(`
 | 
						|
target "default" {
 | 
						|
	dockerfile-inline = <<EOT
 | 
						|
FROM scratch
 | 
						|
COPY foo /foo
 | 
						|
EOT
 | 
						|
}
 | 
						|
`)
 | 
						|
	cwdBakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
	dockerfile-inline = <<EOT
 | 
						|
FROM scratch
 | 
						|
COPY bar /bar
 | 
						|
EOT
 | 
						|
}
 | 
						|
`)
 | 
						|
 | 
						|
	dir := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakeFile, 0600),
 | 
						|
		fstest.CreateFile("docker-bake-cwd.hcl", cwdBakefile, 0600),
 | 
						|
		fstest.CreateFile("bar", []byte("bar"), 0600),
 | 
						|
	)
 | 
						|
	dirDest := t.TempDir()
 | 
						|
 | 
						|
	cmd := buildxCmd(sb, withDir(dir), withArgs("bake", "--file", "docker-bake.hcl", "--file", "cwd://docker-bake-cwd.hcl", "--progress=plain", "--set", "*.output=type=local,dest="+dirDest))
 | 
						|
	dt, err := cmd.CombinedOutput()
 | 
						|
	require.NoError(t, err, string(dt))
 | 
						|
	require.Contains(t, string(dt), `#1 [internal] load local bake definitions`)
 | 
						|
	require.Contains(t, string(dt), `#1 reading docker-bake.hcl`)
 | 
						|
	require.Contains(t, string(dt), `#1 reading docker-bake-cwd.hcl`)
 | 
						|
	require.FileExists(t, filepath.Join(dirDest, "bar"))
 | 
						|
}
 | 
						|
 | 
						|
func testBakeRemoteCmdContext(t *testing.T, sb integration.Sandbox) {
 | 
						|
	bakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
	context = BAKE_CMD_CONTEXT
 | 
						|
	dockerfile-inline = <<EOT
 | 
						|
FROM scratch
 | 
						|
COPY foo /foo
 | 
						|
EOT
 | 
						|
}
 | 
						|
`)
 | 
						|
	dirSpec := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
	)
 | 
						|
	dirSrc := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("foo", []byte("foo"), 0600),
 | 
						|
	)
 | 
						|
	dirDest := t.TempDir()
 | 
						|
 | 
						|
	git, err := gitutil.New(gitutil.WithWorkingDir(dirSpec))
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	gitutil.GitInit(git, t)
 | 
						|
	gitutil.GitAdd(git, t, "docker-bake.hcl")
 | 
						|
	gitutil.GitCommit(git, t, "initial commit")
 | 
						|
	addr := gitutil.GitServeHTTP(git, t)
 | 
						|
 | 
						|
	out, err := bakeCmd(sb, withDir(dirSrc), withArgs(addr, "--set", "*.output=type=local,dest="+dirDest))
 | 
						|
	require.NoError(t, err, out)
 | 
						|
 | 
						|
	require.FileExists(t, filepath.Join(dirDest, "foo"))
 | 
						|
}
 | 
						|
 | 
						|
func testBakeRemoteCmdContextOverride(t *testing.T, sb integration.Sandbox) {
 | 
						|
	bakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
	context = BAKE_CMD_CONTEXT
 | 
						|
	dockerfile-inline = <<EOT
 | 
						|
FROM scratch
 | 
						|
COPY foo /foo
 | 
						|
EOT
 | 
						|
}
 | 
						|
`)
 | 
						|
	dirSpec := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
	)
 | 
						|
	dirSrc := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("foo", []byte("foo"), 0600),
 | 
						|
	)
 | 
						|
	dirDest := t.TempDir()
 | 
						|
 | 
						|
	gitSpec, err := gitutil.New(gitutil.WithWorkingDir(dirSpec))
 | 
						|
	require.NoError(t, err)
 | 
						|
	gitutil.GitInit(gitSpec, t)
 | 
						|
	gitutil.GitAdd(gitSpec, t, "docker-bake.hcl")
 | 
						|
	gitutil.GitCommit(gitSpec, t, "initial commit")
 | 
						|
	addrSpec := gitutil.GitServeHTTP(gitSpec, t)
 | 
						|
 | 
						|
	gitSrc, err := gitutil.New(gitutil.WithWorkingDir(dirSrc))
 | 
						|
	require.NoError(t, err)
 | 
						|
	gitutil.GitInit(gitSrc, t)
 | 
						|
	gitutil.GitAdd(gitSrc, t, "foo")
 | 
						|
	gitutil.GitCommit(gitSrc, t, "initial commit")
 | 
						|
	addrSrc := gitutil.GitServeHTTP(gitSrc, t)
 | 
						|
 | 
						|
	out, err := bakeCmd(sb, withDir("/tmp"), withArgs(addrSpec, addrSrc, "--set", "*.output=type=local,dest="+dirDest))
 | 
						|
	require.NoError(t, err, out)
 | 
						|
 | 
						|
	require.FileExists(t, filepath.Join(dirDest, "foo"))
 | 
						|
}
 | 
						|
 | 
						|
// https://github.com/docker/buildx/issues/1738
 | 
						|
func testBakeRemoteContextSubdir(t *testing.T, sb integration.Sandbox) {
 | 
						|
	bakefile := []byte(`
 | 
						|
target default {
 | 
						|
	context = "./bar"
 | 
						|
}
 | 
						|
`)
 | 
						|
	dockerfile := []byte(`
 | 
						|
FROM scratch
 | 
						|
COPY super-cool.txt /
 | 
						|
`)
 | 
						|
 | 
						|
	dir := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
		fstest.CreateDir("bar", 0700),
 | 
						|
		fstest.CreateFile("bar/Dockerfile", dockerfile, 0600),
 | 
						|
		fstest.CreateFile("bar/super-cool.txt", []byte("super cool"), 0600),
 | 
						|
	)
 | 
						|
	dirDest := t.TempDir()
 | 
						|
 | 
						|
	git, err := gitutil.New(gitutil.WithWorkingDir(dir))
 | 
						|
	require.NoError(t, err)
 | 
						|
	gitutil.GitInit(git, t)
 | 
						|
	gitutil.GitAdd(git, t, "docker-bake.hcl", "bar")
 | 
						|
	gitutil.GitCommit(git, t, "initial commit")
 | 
						|
	addr := gitutil.GitServeHTTP(git, t)
 | 
						|
 | 
						|
	out, err := bakeCmd(sb, withDir("/tmp"), withArgs(addr, "--set", "*.output=type=local,dest="+dirDest))
 | 
						|
	require.NoError(t, err, out)
 | 
						|
 | 
						|
	require.FileExists(t, filepath.Join(dirDest, "super-cool.txt"))
 | 
						|
}
 | 
						|
 | 
						|
func testBakeRemoteCmdContextEscapeRoot(t *testing.T, sb integration.Sandbox) {
 | 
						|
	dirSrc := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("foo", []byte("foo"), 0600),
 | 
						|
	)
 | 
						|
	dirSrc, err := filepath.Abs(dirSrc)
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	dirCurrent := tmpdir(t)
 | 
						|
	dirCurrent, err = filepath.Abs(dirCurrent)
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	bakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
	context = "cwd://` + dirSrc + `"
 | 
						|
	dockerfile-inline = <<EOT
 | 
						|
FROM scratch
 | 
						|
COPY foo /foo
 | 
						|
EOT
 | 
						|
}
 | 
						|
`)
 | 
						|
	dirSpec := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
	)
 | 
						|
	dirDest := t.TempDir()
 | 
						|
 | 
						|
	git, err := gitutil.New(gitutil.WithWorkingDir(dirSpec))
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	gitutil.GitInit(git, t)
 | 
						|
	gitutil.GitAdd(git, t, "docker-bake.hcl")
 | 
						|
	gitutil.GitCommit(git, t, "initial commit")
 | 
						|
	addr := gitutil.GitServeHTTP(git, t)
 | 
						|
 | 
						|
	out, err := bakeCmd(
 | 
						|
		sb,
 | 
						|
		withDir(dirCurrent),
 | 
						|
		withArgs(addr, "--set", "*.output=type=local,dest="+dirDest),
 | 
						|
	)
 | 
						|
	require.Error(t, err, out)
 | 
						|
	require.Contains(t, out, "Your build is requesting privileges for following possibly insecure capabilities")
 | 
						|
	require.Contains(t, out, "Read access to path ../")
 | 
						|
 | 
						|
	out, err = bakeCmd(
 | 
						|
		sb,
 | 
						|
		withDir(dirCurrent),
 | 
						|
		withArgs(addr, "--set", "*.output=type=local,dest="+dirDest),
 | 
						|
		withEnv("BAKE_ALLOW_REMOTE_FS_ACCESS=1"),
 | 
						|
	)
 | 
						|
	require.NoError(t, err, out)
 | 
						|
	require.FileExists(t, filepath.Join(dirDest, "foo"))
 | 
						|
}
 | 
						|
 | 
						|
func testBakeRemoteCmdContextEscapeRelative(t *testing.T, sb integration.Sandbox) {
 | 
						|
	bakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
	context = "cwd://../"
 | 
						|
	dockerfile-inline = <<EOT
 | 
						|
FROM scratch
 | 
						|
COPY foo /foo
 | 
						|
EOT
 | 
						|
}
 | 
						|
`)
 | 
						|
	dirSpec := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
	)
 | 
						|
	dirSrc := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("foo", []byte("foo"), 0600),
 | 
						|
		fstest.CreateDir("subdir", 0700),
 | 
						|
	)
 | 
						|
	dirDest := t.TempDir()
 | 
						|
 | 
						|
	git, err := gitutil.New(gitutil.WithWorkingDir(dirSpec))
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	gitutil.GitInit(git, t)
 | 
						|
	gitutil.GitAdd(git, t, "docker-bake.hcl")
 | 
						|
	gitutil.GitCommit(git, t, "initial commit")
 | 
						|
	addr := gitutil.GitServeHTTP(git, t)
 | 
						|
 | 
						|
	out, err := bakeCmd(
 | 
						|
		sb,
 | 
						|
		withDir(filepath.Join(dirSrc, "subdir")),
 | 
						|
		withArgs(addr, "--set", "*.output=type=local,dest="+dirDest),
 | 
						|
	)
 | 
						|
	require.Error(t, err, out)
 | 
						|
	require.Contains(t, out, "Your build is requesting privileges for following possibly insecure capabilities")
 | 
						|
	require.Contains(t, out, "Read access to path ..")
 | 
						|
 | 
						|
	out, err = bakeCmd(
 | 
						|
		sb,
 | 
						|
		withDir(filepath.Join(dirSrc, "subdir")),
 | 
						|
		withArgs(addr, "--set", "*.output=type=local,dest="+dirDest),
 | 
						|
		withEnv("BAKE_ALLOW_REMOTE_FS_ACCESS=1"),
 | 
						|
	)
 | 
						|
	require.NoError(t, err, out)
 | 
						|
	require.FileExists(t, filepath.Join(dirDest, "foo"))
 | 
						|
}
 | 
						|
 | 
						|
func testBakeRemoteDockerfileCwd(t *testing.T, sb integration.Sandbox) {
 | 
						|
	bakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
	context = "."
 | 
						|
	dockerfile = "cwd://Dockerfile.app"
 | 
						|
}
 | 
						|
`)
 | 
						|
	dockerfile := []byte(`
 | 
						|
FROM scratch
 | 
						|
COPY bar /bar
 | 
						|
	`)
 | 
						|
	dockerfileApp := []byte(`
 | 
						|
FROM scratch
 | 
						|
COPY foo /foo
 | 
						|
	`)
 | 
						|
 | 
						|
	dirSpec := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
		fstest.CreateFile("foo", []byte("foo"), 0600),
 | 
						|
		fstest.CreateFile("bar", []byte("bar"), 0600),
 | 
						|
	)
 | 
						|
	dirSrc := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("Dockerfile.app", dockerfileApp, 0600),
 | 
						|
	)
 | 
						|
	dirDest := t.TempDir()
 | 
						|
 | 
						|
	git, err := gitutil.New(gitutil.WithWorkingDir(dirSpec))
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	gitutil.GitInit(git, t)
 | 
						|
	gitutil.GitAdd(git, t, "docker-bake.hcl")
 | 
						|
	gitutil.GitAdd(git, t, "Dockerfile")
 | 
						|
	gitutil.GitAdd(git, t, "foo")
 | 
						|
	gitutil.GitAdd(git, t, "bar")
 | 
						|
	gitutil.GitCommit(git, t, "initial commit")
 | 
						|
	addr := gitutil.GitServeHTTP(git, t)
 | 
						|
 | 
						|
	out, err := bakeCmd(
 | 
						|
		sb,
 | 
						|
		withDir(dirSrc),
 | 
						|
		withArgs(addr, "--set", "*.output=type=local,dest="+dirDest),
 | 
						|
	)
 | 
						|
	require.NoError(t, err, out)
 | 
						|
	require.FileExists(t, filepath.Join(dirDest, "foo"))
 | 
						|
 | 
						|
	err = os.Remove(filepath.Join(dirSrc, "Dockerfile.app"))
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	out, err = bakeCmd(
 | 
						|
		sb,
 | 
						|
		withDir(dirSrc),
 | 
						|
		withArgs(addr, "--set", "*.output=type=cacheonly"),
 | 
						|
	)
 | 
						|
	require.Error(t, err, out)
 | 
						|
}
 | 
						|
 | 
						|
func testBakeRemoteLocalContextRemoteDockerfile(t *testing.T, sb integration.Sandbox) {
 | 
						|
	bakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
	context = BAKE_CMD_CONTEXT
 | 
						|
	dockerfile = "Dockerfile.app"
 | 
						|
}
 | 
						|
`)
 | 
						|
	dockerfileApp := []byte(`
 | 
						|
FROM scratch
 | 
						|
COPY foo /foo
 | 
						|
	`)
 | 
						|
 | 
						|
	dirSpec := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
	)
 | 
						|
	dirSrc := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("Dockerfile.app", dockerfileApp, 0600),
 | 
						|
		fstest.CreateFile("foo", []byte("foo"), 0600),
 | 
						|
	)
 | 
						|
 | 
						|
	git, err := gitutil.New(gitutil.WithWorkingDir(dirSpec))
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	gitutil.GitInit(git, t)
 | 
						|
	gitutil.GitAdd(git, t, "docker-bake.hcl")
 | 
						|
	gitutil.GitCommit(git, t, "initial commit")
 | 
						|
	addr := gitutil.GitServeHTTP(git, t)
 | 
						|
 | 
						|
	out, err := bakeCmd(
 | 
						|
		sb,
 | 
						|
		withDir(dirSrc),
 | 
						|
		withArgs(addr, "--set", "*.output=type=cacheonly"),
 | 
						|
	)
 | 
						|
	require.Error(t, err, out)
 | 
						|
	require.Contains(t, out, "reading a dockerfile for a remote build invocation is currently not supported")
 | 
						|
}
 | 
						|
 | 
						|
func testBakeEmpty(t *testing.T, sb integration.Sandbox) {
 | 
						|
	out, err := bakeCmd(sb)
 | 
						|
	require.Error(t, err, out)
 | 
						|
	require.Contains(t, out, "couldn't find a bake definition")
 | 
						|
}
 | 
						|
 | 
						|
func testBakeShmSize(t *testing.T, sb integration.Sandbox) {
 | 
						|
	dockerfile := []byte(`
 | 
						|
FROM busybox AS build
 | 
						|
RUN mount | grep /dev/shm > /shmsize
 | 
						|
FROM scratch
 | 
						|
COPY --from=build /shmsize /
 | 
						|
	`)
 | 
						|
	bakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
  shm-size = "128m"
 | 
						|
}
 | 
						|
`)
 | 
						|
	dir := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
	)
 | 
						|
 | 
						|
	dirDest := t.TempDir()
 | 
						|
 | 
						|
	out, err := bakeCmd(
 | 
						|
		sb,
 | 
						|
		withDir(dir),
 | 
						|
		withArgs("--set", "*.output=type=local,dest="+dirDest),
 | 
						|
	)
 | 
						|
	require.NoError(t, err, out)
 | 
						|
 | 
						|
	dt, err := os.ReadFile(filepath.Join(dirDest, "shmsize"))
 | 
						|
	require.NoError(t, err)
 | 
						|
	require.Contains(t, string(dt), `size=131072k`)
 | 
						|
}
 | 
						|
 | 
						|
func testBakeSetNonExistingSubdirNoParallel(t *testing.T, sb integration.Sandbox) {
 | 
						|
	for _, ent := range []bool{true, false} {
 | 
						|
		t.Run(fmt.Sprintf("ent=%v", ent), func(t *testing.T) {
 | 
						|
			t.Setenv("BUILDX_BAKE_ENTITLEMENTS_FS", strconv.FormatBool(ent))
 | 
						|
			dockerfile := []byte(`
 | 
						|
FROM scratch
 | 
						|
COPY foo /foo
 | 
						|
	`)
 | 
						|
			bakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
}
 | 
						|
`)
 | 
						|
			dir := tmpdir(
 | 
						|
				t,
 | 
						|
				fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
				fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
				fstest.CreateFile("foo", []byte("foo"), 0600),
 | 
						|
			)
 | 
						|
 | 
						|
			cmd := buildxCmd(sb, withDir(dir), withArgs("bake", "--progress=plain", "--set", "*.output=type=local,dest="+filepath.Join(dir, "not/exists")))
 | 
						|
			out, err := cmd.CombinedOutput()
 | 
						|
			require.NoError(t, err, string(out))
 | 
						|
			require.Contains(t, string(out), `#1 [internal] load local bake definitions`)
 | 
						|
			require.Contains(t, string(out), `#1 reading docker-bake.hcl`)
 | 
						|
 | 
						|
			require.FileExists(t, filepath.Join(dir, "not/exists/foo"))
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
func testBakeSetNonExistingOutsideNoParallel(t *testing.T, sb integration.Sandbox) {
 | 
						|
	for _, ent := range []bool{true, false} {
 | 
						|
		t.Run(fmt.Sprintf("ent=%v", ent), func(t *testing.T) {
 | 
						|
			t.Setenv("BUILDX_BAKE_ENTITLEMENTS_FS", strconv.FormatBool(ent))
 | 
						|
			dockerfile := []byte(`
 | 
						|
FROM scratch
 | 
						|
COPY foo /foo
 | 
						|
	`)
 | 
						|
			bakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
}
 | 
						|
`)
 | 
						|
			dir := tmpdir(
 | 
						|
				t,
 | 
						|
				fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
				fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
				fstest.CreateFile("foo", []byte("foo"), 0600),
 | 
						|
			)
 | 
						|
 | 
						|
			destDir := t.TempDir()
 | 
						|
 | 
						|
			cmd := buildxCmd(sb, withDir(dir), withArgs("bake", "--progress=plain", "--set", "*.output=type=local,dest="+filepath.Join(destDir, "not/exists")))
 | 
						|
			out, err := cmd.CombinedOutput()
 | 
						|
			if ent {
 | 
						|
				require.Error(t, err, string(out))
 | 
						|
				require.Contains(t, string(out), "ERROR: additional privileges requested")
 | 
						|
			} else {
 | 
						|
				require.NoError(t, err, string(out))
 | 
						|
				require.FileExists(t, filepath.Join(destDir, "not/exists/foo"))
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func testBakeSetExistingOutsideNoParallel(t *testing.T, sb integration.Sandbox) {
 | 
						|
	for _, ent := range []bool{true, false} {
 | 
						|
		t.Run(fmt.Sprintf("ent=%v", ent), func(t *testing.T) {
 | 
						|
			t.Setenv("BUILDX_BAKE_ENTITLEMENTS_FS", strconv.FormatBool(ent))
 | 
						|
			dockerfile := []byte(`
 | 
						|
FROM scratch
 | 
						|
COPY foo /foo
 | 
						|
	`)
 | 
						|
			bakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
}
 | 
						|
`)
 | 
						|
			dir := tmpdir(
 | 
						|
				t,
 | 
						|
				fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
				fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
				fstest.CreateFile("foo", []byte("foo"), 0600),
 | 
						|
			)
 | 
						|
 | 
						|
			destDir := t.TempDir()
 | 
						|
 | 
						|
			cmd := buildxCmd(sb, withDir(dir), withArgs("bake", "--progress=plain", "--set", "*.output=type=local,dest="+destDir))
 | 
						|
			out, err := cmd.CombinedOutput()
 | 
						|
			// existing directory via --set is always allowed
 | 
						|
			require.NoError(t, err, string(out))
 | 
						|
			require.FileExists(t, filepath.Join(destDir, "foo"))
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func testBakeDefinitionNotExistingSubdirNoParallel(t *testing.T, sb integration.Sandbox) {
 | 
						|
	for _, ent := range []bool{true, false} {
 | 
						|
		t.Run(fmt.Sprintf("ent=%v", ent), func(t *testing.T) {
 | 
						|
			t.Setenv("BUILDX_BAKE_ENTITLEMENTS_FS", strconv.FormatBool(ent))
 | 
						|
			dockerfile := []byte(`
 | 
						|
FROM scratch
 | 
						|
COPY foo /foo
 | 
						|
	`)
 | 
						|
			bakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
	output = ["type=local,dest=not/exists"]
 | 
						|
}
 | 
						|
`)
 | 
						|
			dir := tmpdir(
 | 
						|
				t,
 | 
						|
				fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
				fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
				fstest.CreateFile("foo", []byte("foo"), 0600),
 | 
						|
			)
 | 
						|
 | 
						|
			cmd := buildxCmd(sb, withDir(dir), withArgs("bake", "--progress=plain"))
 | 
						|
			out, err := cmd.CombinedOutput()
 | 
						|
			// subdirs of working directory are always allowed
 | 
						|
			require.NoError(t, err, string(out))
 | 
						|
			require.FileExists(t, filepath.Join(dir, "not/exists/foo"))
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func testBakeDefinitionNotExistingOutsideNoParallel(t *testing.T, sb integration.Sandbox) {
 | 
						|
	for _, ent := range []bool{true, false} {
 | 
						|
		t.Run(fmt.Sprintf("ent=%v", ent), func(t *testing.T) {
 | 
						|
			t.Setenv("BUILDX_BAKE_ENTITLEMENTS_FS", strconv.FormatBool(ent))
 | 
						|
			dockerfile := []byte(`
 | 
						|
FROM scratch
 | 
						|
COPY foo /foo
 | 
						|
	`)
 | 
						|
			destDir := t.TempDir()
 | 
						|
			bakefile := []byte(fmt.Sprintf(`
 | 
						|
target "default" {
 | 
						|
	output = ["type=local,dest=%s/not/exists"]
 | 
						|
}
 | 
						|
`, destDir))
 | 
						|
			dir := tmpdir(
 | 
						|
				t,
 | 
						|
				fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
				fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
				fstest.CreateFile("foo", []byte("foo"), 0600),
 | 
						|
			)
 | 
						|
 | 
						|
			cmd := buildxCmd(sb, withDir(dir), withArgs("bake", "--progress=plain"))
 | 
						|
			out, err := cmd.CombinedOutput()
 | 
						|
			if ent {
 | 
						|
				require.Error(t, err, string(out))
 | 
						|
				require.Contains(t, string(out), "ERROR: additional privileges requested")
 | 
						|
			} else {
 | 
						|
				require.NoError(t, err, string(out))
 | 
						|
				require.FileExists(t, filepath.Join(destDir, "not/exists/foo"))
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func testBakeDefinitionExistingOutsideNoParallel(t *testing.T, sb integration.Sandbox) {
 | 
						|
	for _, ent := range []bool{true, false} {
 | 
						|
		t.Run(fmt.Sprintf("ent=%v", ent), func(t *testing.T) {
 | 
						|
			t.Setenv("BUILDX_BAKE_ENTITLEMENTS_FS", strconv.FormatBool(ent))
 | 
						|
			dockerfile := []byte(`
 | 
						|
FROM scratch
 | 
						|
COPY foo /foo
 | 
						|
	`)
 | 
						|
			destDir := t.TempDir()
 | 
						|
			bakefile := []byte(fmt.Sprintf(`
 | 
						|
target "default" {
 | 
						|
	output = ["type=local,dest=%s"]
 | 
						|
}
 | 
						|
`, destDir))
 | 
						|
			dir := tmpdir(
 | 
						|
				t,
 | 
						|
				fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
				fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
				fstest.CreateFile("foo", []byte("foo"), 0600),
 | 
						|
			)
 | 
						|
 | 
						|
			cmd := buildxCmd(sb, withDir(dir), withArgs("bake", "--progress=plain"))
 | 
						|
			out, err := cmd.CombinedOutput()
 | 
						|
			if ent {
 | 
						|
				require.Error(t, err, string(out))
 | 
						|
				require.Contains(t, string(out), "ERROR: additional privileges requested")
 | 
						|
			} else {
 | 
						|
				require.NoError(t, err, string(out))
 | 
						|
				require.FileExists(t, filepath.Join(destDir, "foo"))
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func testBakeDefinitionSymlinkOutsideNoParallel(t *testing.T, sb integration.Sandbox) {
 | 
						|
	for _, ent := range []bool{true, false} {
 | 
						|
		t.Run(fmt.Sprintf("ent=%v", ent), func(t *testing.T) {
 | 
						|
			t.Setenv("BUILDX_BAKE_ENTITLEMENTS_FS", strconv.FormatBool(ent))
 | 
						|
			dockerfile := []byte(`
 | 
						|
FROM scratch
 | 
						|
COPY foo /foo
 | 
						|
	`)
 | 
						|
			destDir := t.TempDir()
 | 
						|
			bakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
	output = ["type=local,dest=out"]
 | 
						|
}
 | 
						|
`)
 | 
						|
			dir := tmpdir(
 | 
						|
				t,
 | 
						|
				fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
				fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
				fstest.CreateFile("foo", []byte("foo"), 0600),
 | 
						|
				fstest.Symlink(destDir, "out"),
 | 
						|
			)
 | 
						|
 | 
						|
			cmd := buildxCmd(sb, withDir(dir), withArgs("bake", "--progress=plain"))
 | 
						|
			out, err := cmd.CombinedOutput()
 | 
						|
			if ent {
 | 
						|
				require.Error(t, err, string(out))
 | 
						|
				require.Contains(t, string(out), "ERROR: additional privileges requested")
 | 
						|
			} else {
 | 
						|
				require.NoError(t, err, string(out))
 | 
						|
				require.FileExists(t, filepath.Join(destDir, "foo"))
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func testBakeDefinitionSymlinkOutsideGrantedNoParallel(t *testing.T, sb integration.Sandbox) {
 | 
						|
	for _, ent := range []bool{true, false} {
 | 
						|
		t.Run(fmt.Sprintf("ent=%v", ent), func(t *testing.T) {
 | 
						|
			t.Setenv("BUILDX_BAKE_ENTITLEMENTS_FS", strconv.FormatBool(ent))
 | 
						|
			dockerfile := []byte(`
 | 
						|
FROM scratch
 | 
						|
COPY foo /foo
 | 
						|
	`)
 | 
						|
			destDir := t.TempDir()
 | 
						|
			bakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
	output = ["type=local,dest=out"]
 | 
						|
}
 | 
						|
`)
 | 
						|
			dir := tmpdir(
 | 
						|
				t,
 | 
						|
				fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
				fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
				fstest.CreateFile("foo", []byte("foo"), 0600),
 | 
						|
				fstest.Symlink(destDir, "out"),
 | 
						|
			)
 | 
						|
 | 
						|
			cmd := buildxCmd(sb, withDir(dir), withArgs("bake", "--progress=plain", "--allow", "fs.write="+destDir))
 | 
						|
			out, err := cmd.CombinedOutput()
 | 
						|
			require.NoError(t, err, string(out))
 | 
						|
			require.FileExists(t, filepath.Join(destDir, "foo"))
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func testBakeUlimits(t *testing.T, sb integration.Sandbox) {
 | 
						|
	dockerfile := []byte(`
 | 
						|
FROM busybox AS build
 | 
						|
RUN ulimit -n > first > /ulimit
 | 
						|
FROM scratch
 | 
						|
COPY --from=build /ulimit /
 | 
						|
	`)
 | 
						|
	bakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
  ulimits = ["nofile=1024:1024"]
 | 
						|
}
 | 
						|
`)
 | 
						|
	dir := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
	)
 | 
						|
 | 
						|
	dirDest := t.TempDir()
 | 
						|
 | 
						|
	out, err := bakeCmd(
 | 
						|
		sb,
 | 
						|
		withDir(dir),
 | 
						|
		withArgs("--set", "*.output=type=local,dest="+dirDest),
 | 
						|
	)
 | 
						|
	require.NoError(t, err, out)
 | 
						|
 | 
						|
	dt, err := os.ReadFile(filepath.Join(dirDest, "ulimit"))
 | 
						|
	require.NoError(t, err)
 | 
						|
	require.Contains(t, string(dt), `1024`)
 | 
						|
}
 | 
						|
 | 
						|
func testBakeMetadataProvenance(t *testing.T, sb integration.Sandbox) {
 | 
						|
	t.Run("default", func(t *testing.T) {
 | 
						|
		bakeMetadataProvenance(t, sb, "")
 | 
						|
	})
 | 
						|
	t.Run("max", func(t *testing.T) {
 | 
						|
		bakeMetadataProvenance(t, sb, "max")
 | 
						|
	})
 | 
						|
	t.Run("min", func(t *testing.T) {
 | 
						|
		bakeMetadataProvenance(t, sb, "min")
 | 
						|
	})
 | 
						|
	t.Run("disabled", func(t *testing.T) {
 | 
						|
		bakeMetadataProvenance(t, sb, "disabled")
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func bakeMetadataProvenance(t *testing.T, sb integration.Sandbox, metadataMode string) {
 | 
						|
	dockerfile := []byte(`
 | 
						|
FROM scratch
 | 
						|
COPY foo /foo
 | 
						|
	`)
 | 
						|
	bakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
}
 | 
						|
`)
 | 
						|
	dir := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
		fstest.CreateFile("foo", []byte("foo"), 0600),
 | 
						|
	)
 | 
						|
 | 
						|
	dirDest := t.TempDir()
 | 
						|
 | 
						|
	outFlag := "default.output=type=docker"
 | 
						|
	if sb.DockerAddress() == "" {
 | 
						|
		// there is no Docker atm to load the image
 | 
						|
		outFlag += ",dest=" + dirDest + "/image.tar"
 | 
						|
	}
 | 
						|
 | 
						|
	cmd := buildxCmd(
 | 
						|
		sb,
 | 
						|
		withDir(dir),
 | 
						|
		withArgs("bake", "--metadata-file", filepath.Join(dirDest, "md.json"), "--set", outFlag),
 | 
						|
		withEnv("BUILDX_METADATA_PROVENANCE="+metadataMode),
 | 
						|
	)
 | 
						|
	out, err := cmd.CombinedOutput()
 | 
						|
	require.NoError(t, err, string(out))
 | 
						|
 | 
						|
	dt, err := os.ReadFile(filepath.Join(dirDest, "md.json"))
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	type mdT struct {
 | 
						|
		Default struct {
 | 
						|
			BuildRef        string                 `json:"buildx.build.ref"`
 | 
						|
			BuildProvenance map[string]interface{} `json:"buildx.build.provenance"`
 | 
						|
		} `json:"default"`
 | 
						|
	}
 | 
						|
	var md mdT
 | 
						|
	err = json.Unmarshal(dt, &md)
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.NotEmpty(t, md.Default.BuildRef)
 | 
						|
	if metadataMode == "disabled" {
 | 
						|
		require.Empty(t, md.Default.BuildProvenance)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	require.NotEmpty(t, md.Default.BuildProvenance)
 | 
						|
 | 
						|
	dtprv, err := json.Marshal(md.Default.BuildProvenance)
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	var prv provenancetypes.ProvenancePredicate
 | 
						|
	require.NoError(t, json.Unmarshal(dtprv, &prv))
 | 
						|
	require.Equal(t, provenancetypes.BuildKitBuildType, prv.BuildType)
 | 
						|
}
 | 
						|
 | 
						|
func testBakeMetadataWarnings(t *testing.T, sb integration.Sandbox) {
 | 
						|
	t.Run("default", func(t *testing.T) {
 | 
						|
		bakeMetadataWarnings(t, sb, "")
 | 
						|
	})
 | 
						|
	t.Run("true", func(t *testing.T) {
 | 
						|
		bakeMetadataWarnings(t, sb, "true")
 | 
						|
	})
 | 
						|
	t.Run("false", func(t *testing.T) {
 | 
						|
		bakeMetadataWarnings(t, sb, "false")
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func bakeMetadataWarnings(t *testing.T, sb integration.Sandbox, mode string) {
 | 
						|
	dockerfile := []byte(`
 | 
						|
frOM busybox as base
 | 
						|
cOpy Dockerfile .
 | 
						|
from scratch
 | 
						|
COPy --from=base \
 | 
						|
  /Dockerfile \
 | 
						|
  /
 | 
						|
	`)
 | 
						|
	bakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
}
 | 
						|
`)
 | 
						|
	dir := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
	)
 | 
						|
 | 
						|
	dirDest := t.TempDir()
 | 
						|
 | 
						|
	cmd := buildxCmd(
 | 
						|
		sb,
 | 
						|
		withDir(dir),
 | 
						|
		withArgs("bake", "--metadata-file", filepath.Join(dirDest, "md.json"), "--set", "*.output=type=cacheonly"),
 | 
						|
		withEnv("BUILDX_METADATA_WARNINGS="+mode),
 | 
						|
	)
 | 
						|
	out, err := cmd.CombinedOutput()
 | 
						|
	require.NoError(t, err, string(out))
 | 
						|
 | 
						|
	dt, err := os.ReadFile(filepath.Join(dirDest, "md.json"))
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	type mdT struct {
 | 
						|
		BuildWarnings []client.VertexWarning `json:"buildx.build.warnings"`
 | 
						|
		Default       struct {
 | 
						|
			BuildRef string `json:"buildx.build.ref"`
 | 
						|
		} `json:"default"`
 | 
						|
	}
 | 
						|
	var md mdT
 | 
						|
	err = json.Unmarshal(dt, &md)
 | 
						|
	require.NoError(t, err, string(dt))
 | 
						|
 | 
						|
	require.NotEmpty(t, md.Default.BuildRef, string(dt))
 | 
						|
	if mode == "" || mode == "false" {
 | 
						|
		require.Empty(t, md.BuildWarnings, string(dt))
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	skipNoCompatBuildKit(t, sb, ">= 0.14.0-0", "lint")
 | 
						|
	require.Len(t, md.BuildWarnings, 3, string(dt))
 | 
						|
}
 | 
						|
 | 
						|
func testBakeMetadataWarningsDedup(t *testing.T, sb integration.Sandbox) {
 | 
						|
	dockerfile := []byte(`
 | 
						|
frOM busybox as base
 | 
						|
cOpy Dockerfile .
 | 
						|
from scratch
 | 
						|
COPy --from=base \
 | 
						|
  /Dockerfile \
 | 
						|
  /
 | 
						|
	`)
 | 
						|
	bakefile := []byte(`
 | 
						|
group "default" {
 | 
						|
  targets = ["base", "def"]
 | 
						|
}
 | 
						|
target "base" {
 | 
						|
  target = "base"
 | 
						|
}
 | 
						|
target "def" {
 | 
						|
}
 | 
						|
`)
 | 
						|
	dir := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
	)
 | 
						|
 | 
						|
	dirDest := t.TempDir()
 | 
						|
 | 
						|
	cmd := buildxCmd(
 | 
						|
		sb,
 | 
						|
		withDir(dir),
 | 
						|
		withArgs("bake", "--metadata-file", filepath.Join(dirDest, "md.json"), "--set", "*.output=type=cacheonly"),
 | 
						|
		withEnv("BUILDX_METADATA_WARNINGS=true"),
 | 
						|
	)
 | 
						|
	out, err := cmd.CombinedOutput()
 | 
						|
	require.NoError(t, err, string(out))
 | 
						|
 | 
						|
	dt, err := os.ReadFile(filepath.Join(dirDest, "md.json"))
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	type mdT struct {
 | 
						|
		BuildWarnings []client.VertexWarning `json:"buildx.build.warnings"`
 | 
						|
		Base          struct {
 | 
						|
			BuildRef string `json:"buildx.build.ref"`
 | 
						|
		} `json:"base"`
 | 
						|
		Def struct {
 | 
						|
			BuildRef string `json:"buildx.build.ref"`
 | 
						|
		} `json:"def"`
 | 
						|
	}
 | 
						|
	var md mdT
 | 
						|
	err = json.Unmarshal(dt, &md)
 | 
						|
	require.NoError(t, err, string(dt))
 | 
						|
 | 
						|
	require.NotEmpty(t, md.Base.BuildRef, string(dt))
 | 
						|
	require.NotEmpty(t, md.Def.BuildRef, string(dt))
 | 
						|
 | 
						|
	skipNoCompatBuildKit(t, sb, ">= 0.14.0-0", "lint")
 | 
						|
	require.Len(t, md.BuildWarnings, 3, string(dt))
 | 
						|
}
 | 
						|
 | 
						|
func testBakeMultiPlatform(t *testing.T, sb integration.Sandbox) {
 | 
						|
	registry, err := sb.NewRegistry()
 | 
						|
	if errors.Is(err, integration.ErrRequirements) {
 | 
						|
		t.Skip(err.Error())
 | 
						|
	}
 | 
						|
	require.NoError(t, err)
 | 
						|
	target := registry + "/buildx/registry:latest"
 | 
						|
 | 
						|
	dockerfile := []byte(`
 | 
						|
	FROM --platform=$BUILDPLATFORM busybox:latest AS base
 | 
						|
	COPY foo /etc/foo
 | 
						|
	RUN cp /etc/foo /etc/bar
 | 
						|
 | 
						|
	FROM scratch
 | 
						|
	COPY --from=base /etc/bar /bar
 | 
						|
	`)
 | 
						|
	bakefile := []byte(`
 | 
						|
	target "default" {
 | 
						|
	platforms = ["linux/amd64", "linux/arm64"]
 | 
						|
	}
 | 
						|
	`)
 | 
						|
	dir := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
		fstest.CreateFile("foo", []byte("foo"), 0600),
 | 
						|
	)
 | 
						|
 | 
						|
	cmd := buildxCmd(sb, withDir(dir), withArgs("bake"), withArgs("--set", fmt.Sprintf("*.output=type=image,name=%s,push=true", target)))
 | 
						|
	out, err := cmd.CombinedOutput()
 | 
						|
 | 
						|
	if !isMobyWorker(sb) {
 | 
						|
		require.NoError(t, err, string(out))
 | 
						|
 | 
						|
		desc, provider, err := contentutil.ProviderFromRef(target)
 | 
						|
		require.NoError(t, err)
 | 
						|
		imgs, err := testutil.ReadImages(sb.Context(), provider, desc)
 | 
						|
		require.NoError(t, err)
 | 
						|
 | 
						|
		img := imgs.Find("linux/amd64")
 | 
						|
		require.NotNil(t, img)
 | 
						|
		img = imgs.Find("linux/arm64")
 | 
						|
		require.NotNil(t, img)
 | 
						|
	} else {
 | 
						|
		require.Error(t, err, string(out))
 | 
						|
		require.Contains(t, string(out), "Multi-platform build is not supported")
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func testBakeMultiExporters(t *testing.T, sb integration.Sandbox) {
 | 
						|
	if !isDockerContainerWorker(sb) {
 | 
						|
		t.Skip("only testing with docker-container worker")
 | 
						|
	}
 | 
						|
	skipNoCompatBuildKit(t, sb, ">= 0.13.0-0", "multi exporters")
 | 
						|
 | 
						|
	registry, err := sb.NewRegistry()
 | 
						|
	if errors.Is(err, integration.ErrRequirements) {
 | 
						|
		t.Skip(err.Error())
 | 
						|
	}
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	targetReg := registry + "/buildx/registry:latest"
 | 
						|
	targetStore := "buildx:local-" + identity.NewID()
 | 
						|
 | 
						|
	t.Cleanup(func() {
 | 
						|
		cmd := dockerCmd(sb, withArgs("image", "rm", targetStore))
 | 
						|
		cmd.Stderr = os.Stderr
 | 
						|
		require.NoError(t, cmd.Run())
 | 
						|
	})
 | 
						|
 | 
						|
	dockerfile := []byte(`
 | 
						|
FROM scratch
 | 
						|
COPY foo /foo
 | 
						|
	`)
 | 
						|
	bakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
}
 | 
						|
`)
 | 
						|
	dir := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
		fstest.CreateFile("foo", []byte("foo"), 0600),
 | 
						|
	)
 | 
						|
 | 
						|
	outputs := []string{
 | 
						|
		"--set", fmt.Sprintf("*.output=type=image,name=%s,push=true", targetReg),
 | 
						|
		"--set", fmt.Sprintf("*.output=type=docker,name=%s", targetStore),
 | 
						|
		"--set", fmt.Sprintf("*.output=type=oci,dest=%s/result", dir),
 | 
						|
	}
 | 
						|
	cmd := buildxCmd(sb, withDir(dir), withArgs("bake"), withArgs(outputs...))
 | 
						|
	outb, err := cmd.CombinedOutput()
 | 
						|
	require.NoError(t, err, string(outb))
 | 
						|
 | 
						|
	// test registry
 | 
						|
	desc, provider, err := contentutil.ProviderFromRef(targetReg)
 | 
						|
	require.NoError(t, err)
 | 
						|
	_, err = testutil.ReadImages(sb.Context(), provider, desc)
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	// test docker store
 | 
						|
	cmd = dockerCmd(sb, withArgs("image", "inspect", targetStore))
 | 
						|
	cmd.Stderr = os.Stderr
 | 
						|
	require.NoError(t, cmd.Run())
 | 
						|
 | 
						|
	// test oci
 | 
						|
	_, err = os.ReadFile(fmt.Sprintf("%s/result", dir))
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	// TODO: test metadata file when supported by multi exporters https://github.com/docker/buildx/issues/2181
 | 
						|
}
 | 
						|
 | 
						|
func testBakeLoadPush(t *testing.T, sb integration.Sandbox) {
 | 
						|
	if !isDockerContainerWorker(sb) {
 | 
						|
		t.Skip("only testing with docker-container worker")
 | 
						|
	}
 | 
						|
	skipNoCompatBuildKit(t, sb, ">= 0.13.0-0", "multi exporters")
 | 
						|
 | 
						|
	registry, err := sb.NewRegistry()
 | 
						|
	if errors.Is(err, integration.ErrRequirements) {
 | 
						|
		t.Skip(err.Error())
 | 
						|
	}
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	target := registry + "/buildx/registry:" + identity.NewID()
 | 
						|
 | 
						|
	t.Cleanup(func() {
 | 
						|
		cmd := dockerCmd(sb, withArgs("image", "rm", target))
 | 
						|
		cmd.Stderr = os.Stderr
 | 
						|
		require.NoError(t, cmd.Run())
 | 
						|
	})
 | 
						|
 | 
						|
	dockerfile := []byte(`
 | 
						|
FROM scratch
 | 
						|
COPY foo /foo
 | 
						|
	`)
 | 
						|
	bakefile := []byte(`
 | 
						|
target "default" {
 | 
						|
}
 | 
						|
`)
 | 
						|
	dir := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
		fstest.CreateFile("foo", []byte("foo"), 0600),
 | 
						|
	)
 | 
						|
 | 
						|
	cmd := buildxCmd(sb, withDir(dir), withArgs("bake", "--push", "--load", fmt.Sprintf("--set=*.tags=%s", target)))
 | 
						|
	outb, err := cmd.CombinedOutput()
 | 
						|
	require.NoError(t, err, string(outb))
 | 
						|
 | 
						|
	// test registry
 | 
						|
	desc, provider, err := contentutil.ProviderFromRef(target)
 | 
						|
	require.NoError(t, err)
 | 
						|
	_, err = testutil.ReadImages(sb.Context(), provider, desc)
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	// test docker store
 | 
						|
	cmd = dockerCmd(sb, withArgs("image", "inspect", target))
 | 
						|
	cmd.Stderr = os.Stderr
 | 
						|
	require.NoError(t, cmd.Run())
 | 
						|
 | 
						|
	// TODO: test metadata file when supported by multi exporters https://github.com/docker/buildx/issues/2181
 | 
						|
}
 | 
						|
 | 
						|
func testListTargets(t *testing.T, sb integration.Sandbox) {
 | 
						|
	bakefile := []byte(`
 | 
						|
target "foo" {
 | 
						|
	description = "This builds foo"
 | 
						|
}
 | 
						|
target "abc" {
 | 
						|
}
 | 
						|
`)
 | 
						|
	dir := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
	)
 | 
						|
 | 
						|
	out, err := bakeCmd(
 | 
						|
		sb,
 | 
						|
		withDir(dir),
 | 
						|
		withArgs("--list-targets"),
 | 
						|
	)
 | 
						|
	require.NoError(t, err, out)
 | 
						|
 | 
						|
	require.Equal(t, "TARGET\tDESCRIPTION\nabc\t\nfoo\tThis builds foo", strings.TrimSpace(out))
 | 
						|
}
 | 
						|
 | 
						|
func testListVariables(t *testing.T, sb integration.Sandbox) {
 | 
						|
	bakefile := []byte(`
 | 
						|
variable "foo" {
 | 
						|
	default = "bar"
 | 
						|
	description = "This is foo"
 | 
						|
}
 | 
						|
variable "abc" {
 | 
						|
	default = null
 | 
						|
}
 | 
						|
variable "def" {
 | 
						|
}
 | 
						|
target "default" {
 | 
						|
}
 | 
						|
`)
 | 
						|
	dir := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
	)
 | 
						|
 | 
						|
	out, err := bakeCmd(
 | 
						|
		sb,
 | 
						|
		withDir(dir),
 | 
						|
		withArgs("--list-variables"),
 | 
						|
	)
 | 
						|
	require.NoError(t, err, out)
 | 
						|
 | 
						|
	require.Equal(t, "VARIABLE\tVALUE\tDESCRIPTION\nabc\t\t<null>\t\ndef\t\t\t\nfoo\t\tbar\tThis is foo", strings.TrimSpace(out))
 | 
						|
}
 | 
						|
 | 
						|
func testBakeCallCheck(t *testing.T, sb integration.Sandbox) {
 | 
						|
	dockerfile := []byte(`
 | 
						|
FROM scratch
 | 
						|
COPy foo /foo
 | 
						|
	`)
 | 
						|
	bakefile := []byte(`
 | 
						|
target "validate" {
 | 
						|
	call = "check"
 | 
						|
}
 | 
						|
`)
 | 
						|
	dir := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
	)
 | 
						|
 | 
						|
	out, err := bakeCmd(
 | 
						|
		sb,
 | 
						|
		withDir(dir),
 | 
						|
		withArgs("validate"),
 | 
						|
	)
 | 
						|
	require.Error(t, err, out)
 | 
						|
 | 
						|
	require.Contains(t, out, "validate")
 | 
						|
	require.Contains(t, out, "ConsistentInstructionCasing")
 | 
						|
}
 | 
						|
 | 
						|
func testBakeCallCheckFlag(t *testing.T, sb integration.Sandbox) {
 | 
						|
	dockerfile := []byte(`
 | 
						|
FROM scratch
 | 
						|
COPy foo /foo
 | 
						|
	`)
 | 
						|
	dockerfile2 := []byte(`
 | 
						|
FROM scratch
 | 
						|
COPY foo$BAR /foo
 | 
						|
		`)
 | 
						|
	bakefile := []byte(`
 | 
						|
target "build" {
 | 
						|
	dockerfile = "a.Dockerfile"
 | 
						|
}
 | 
						|
 | 
						|
target "another" {
 | 
						|
	dockerfile = "b.Dockerfile"
 | 
						|
}
 | 
						|
`)
 | 
						|
	dir := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
		fstest.CreateFile("a.Dockerfile", dockerfile, 0600),
 | 
						|
		fstest.CreateFile("b.Dockerfile", dockerfile2, 0600),
 | 
						|
	)
 | 
						|
 | 
						|
	out, err := bakeCmd(
 | 
						|
		sb,
 | 
						|
		withDir(dir),
 | 
						|
		withArgs("build", "another", "--check"),
 | 
						|
	)
 | 
						|
	require.Error(t, err, out)
 | 
						|
 | 
						|
	require.Contains(t, out, "build")
 | 
						|
	require.Contains(t, out, "ConsistentInstructionCasing")
 | 
						|
 | 
						|
	require.Contains(t, out, "another")
 | 
						|
	require.Contains(t, out, "UndefinedVar")
 | 
						|
 | 
						|
	cmd := buildxCmd(
 | 
						|
		sb,
 | 
						|
		withDir(dir),
 | 
						|
		withArgs("bake", "--progress=quiet", "build", "another", "--call", "check,format=json"),
 | 
						|
	)
 | 
						|
	outB, err := cmd.Output()
 | 
						|
	require.Error(t, err, string(outB))
 | 
						|
 | 
						|
	var res map[string]any
 | 
						|
	err = json.Unmarshal(outB, &res)
 | 
						|
	require.NoError(t, err, out)
 | 
						|
 | 
						|
	targets, ok := res["target"].(map[string]any)
 | 
						|
	require.True(t, ok)
 | 
						|
 | 
						|
	build, ok := targets["build"].(map[string]any)
 | 
						|
	require.True(t, ok)
 | 
						|
 | 
						|
	_, ok = build["build"]
 | 
						|
	require.True(t, ok)
 | 
						|
 | 
						|
	check, ok := build["check"].(map[string]any)
 | 
						|
	require.True(t, ok)
 | 
						|
 | 
						|
	warnings, ok := check["warnings"].([]any)
 | 
						|
	require.True(t, ok)
 | 
						|
 | 
						|
	require.Len(t, warnings, 1)
 | 
						|
 | 
						|
	another, ok := targets["another"].(map[string]any)
 | 
						|
	require.True(t, ok)
 | 
						|
 | 
						|
	_, ok = another["build"]
 | 
						|
	require.True(t, ok)
 | 
						|
 | 
						|
	check, ok = another["check"].(map[string]any)
 | 
						|
	require.True(t, ok)
 | 
						|
 | 
						|
	warnings, ok = check["warnings"].([]any)
 | 
						|
	require.True(t, ok)
 | 
						|
 | 
						|
	require.Len(t, warnings, 1)
 | 
						|
}
 | 
						|
 | 
						|
func testBakeCallMetadata(t *testing.T, sb integration.Sandbox) {
 | 
						|
	dockerfile := []byte(`
 | 
						|
frOM busybox as base
 | 
						|
cOpy Dockerfile .
 | 
						|
from scratch
 | 
						|
COPy --from=base \
 | 
						|
  /Dockerfile \
 | 
						|
  /
 | 
						|
	`)
 | 
						|
	bakefile := []byte(`
 | 
						|
target "default" {}
 | 
						|
`)
 | 
						|
	dir := tmpdir(
 | 
						|
		t,
 | 
						|
		fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
		fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
	)
 | 
						|
 | 
						|
	cmd := buildxCmd(
 | 
						|
		sb,
 | 
						|
		withDir(dir),
 | 
						|
		withArgs("bake", "--call", "check,format=json", "--metadata-file", filepath.Join(dir, "md.json")),
 | 
						|
	)
 | 
						|
	stdout := bytes.Buffer{}
 | 
						|
	stderr := bytes.Buffer{}
 | 
						|
	cmd.Stdout = &stdout
 | 
						|
	cmd.Stderr = &stderr
 | 
						|
	require.Error(t, cmd.Run(), stdout.String(), stderr.String())
 | 
						|
 | 
						|
	var res map[string]any
 | 
						|
	require.NoError(t, json.Unmarshal(stdout.Bytes(), &res), stdout.String())
 | 
						|
	targets, ok := res["target"].(map[string]any)
 | 
						|
	require.True(t, ok)
 | 
						|
	def, ok := targets["default"].(map[string]any)
 | 
						|
	require.True(t, ok)
 | 
						|
	_, ok = def["build"]
 | 
						|
	require.True(t, ok)
 | 
						|
	check, ok := def["check"].(map[string]any)
 | 
						|
	require.True(t, ok)
 | 
						|
	warnings, ok := check["warnings"].([]any)
 | 
						|
	require.True(t, ok)
 | 
						|
	require.Len(t, warnings, 3)
 | 
						|
 | 
						|
	dt, err := os.ReadFile(filepath.Join(dir, "md.json"))
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	type mdT struct {
 | 
						|
		Default struct {
 | 
						|
			BuildRef   string           `json:"buildx.build.ref"`
 | 
						|
			ResultJSON lint.LintResults `json:"result.json"`
 | 
						|
		} `json:"default"`
 | 
						|
	}
 | 
						|
	var md mdT
 | 
						|
	require.NoError(t, json.Unmarshal(dt, &md), dt)
 | 
						|
	require.Empty(t, md.Default.BuildRef)
 | 
						|
	require.Len(t, md.Default.ResultJSON.Warnings, 3)
 | 
						|
}
 | 
						|
 | 
						|
func testBakeCheckCallOutput(t *testing.T, sb integration.Sandbox) {
 | 
						|
	t.Run("check for warning count msg in check without warnings", func(t *testing.T) {
 | 
						|
		dockerfile := []byte(`
 | 
						|
FROM busybox
 | 
						|
COPY Dockerfile .
 | 
						|
		`)
 | 
						|
		bakefile := []byte(`
 | 
						|
	target "default" {}
 | 
						|
	`)
 | 
						|
		dir := tmpdir(
 | 
						|
			t,
 | 
						|
			fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
			fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
		)
 | 
						|
 | 
						|
		cmd := buildxCmd(
 | 
						|
			sb,
 | 
						|
			withDir(dir),
 | 
						|
			withArgs("bake", "--call", "check"),
 | 
						|
		)
 | 
						|
		stdout := bytes.Buffer{}
 | 
						|
		stderr := bytes.Buffer{}
 | 
						|
		cmd.Stdout = &stdout
 | 
						|
		cmd.Stderr = &stderr
 | 
						|
		require.NoError(t, cmd.Run(), stdout.String(), stderr.String())
 | 
						|
		require.Contains(t, stdout.String(), "Check complete, no warnings found.")
 | 
						|
	})
 | 
						|
	t.Run("check for warning count msg in check with single warning", func(t *testing.T) {
 | 
						|
		dockerfile := []byte(`
 | 
						|
FROM busybox
 | 
						|
copy Dockerfile .
 | 
						|
		`)
 | 
						|
		bakefile := []byte(`
 | 
						|
	target "default" {}
 | 
						|
	`)
 | 
						|
		dir := tmpdir(
 | 
						|
			t,
 | 
						|
			fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
			fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
		)
 | 
						|
 | 
						|
		cmd := buildxCmd(
 | 
						|
			sb,
 | 
						|
			withDir(dir),
 | 
						|
			withArgs("bake", "--call", "check"),
 | 
						|
		)
 | 
						|
		stdout := bytes.Buffer{}
 | 
						|
		stderr := bytes.Buffer{}
 | 
						|
		cmd.Stdout = &stdout
 | 
						|
		cmd.Stderr = &stderr
 | 
						|
		require.Error(t, cmd.Run(), stdout.String(), stderr.String())
 | 
						|
		require.Contains(t, stdout.String(), "Check complete, 1 warning has been found!")
 | 
						|
	})
 | 
						|
	t.Run("check for warning count msg in check with multiple warnings", func(t *testing.T) {
 | 
						|
		dockerfile := []byte(`
 | 
						|
FROM busybox
 | 
						|
copy Dockerfile .
 | 
						|
 | 
						|
FROM busybox as base
 | 
						|
COPY Dockerfile .
 | 
						|
		`)
 | 
						|
		bakefile := []byte(`
 | 
						|
	target "default" {}
 | 
						|
	`)
 | 
						|
		dir := tmpdir(
 | 
						|
			t,
 | 
						|
			fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
			fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
		)
 | 
						|
 | 
						|
		cmd := buildxCmd(
 | 
						|
			sb,
 | 
						|
			withDir(dir),
 | 
						|
			withArgs("bake", "--call", "check"),
 | 
						|
		)
 | 
						|
		stdout := bytes.Buffer{}
 | 
						|
		stderr := bytes.Buffer{}
 | 
						|
		cmd.Stdout = &stdout
 | 
						|
		cmd.Stderr = &stderr
 | 
						|
		require.Error(t, cmd.Run(), stdout.String(), stderr.String())
 | 
						|
		require.Contains(t, stdout.String(), "Check complete, 2 warnings have been found!")
 | 
						|
	})
 | 
						|
	t.Run("check for warnings with multiple build targets", func(t *testing.T) {
 | 
						|
		dockerfile1 := []byte(`
 | 
						|
FROM busybox
 | 
						|
copy Dockerfile .
 | 
						|
		`)
 | 
						|
		dockerfile2 := []byte(`
 | 
						|
FROM busybox
 | 
						|
copy Dockerfile .
 | 
						|
 | 
						|
FROM busybox as base
 | 
						|
COPY Dockerfile .
 | 
						|
		`)
 | 
						|
		bakefile := []byte(`
 | 
						|
target "first" {
 | 
						|
	dockerfile = "Dockerfile.first"
 | 
						|
}
 | 
						|
target "second" {
 | 
						|
	dockerfile = "Dockerfile.second"
 | 
						|
}
 | 
						|
	`)
 | 
						|
		dir := tmpdir(
 | 
						|
			t,
 | 
						|
			fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
			fstest.CreateFile("Dockerfile.first", dockerfile1, 0600),
 | 
						|
			fstest.CreateFile("Dockerfile.second", dockerfile2, 0600),
 | 
						|
		)
 | 
						|
 | 
						|
		cmd := buildxCmd(
 | 
						|
			sb,
 | 
						|
			withDir(dir),
 | 
						|
			withArgs("bake", "--call", "check", "first", "second"),
 | 
						|
		)
 | 
						|
		stdout := bytes.Buffer{}
 | 
						|
		stderr := bytes.Buffer{}
 | 
						|
		cmd.Stdout = &stdout
 | 
						|
		cmd.Stderr = &stderr
 | 
						|
		require.Error(t, cmd.Run(), stdout.String(), stderr.String())
 | 
						|
		require.Contains(t, stdout.String(), "Check complete, 1 warning has been found!")
 | 
						|
		require.Contains(t, stdout.String(), "Check complete, 2 warnings have been found!")
 | 
						|
	})
 | 
						|
	t.Run("check for Dockerfile path printed with context when displaying rule check warnings with multiple build targets", func(t *testing.T) {
 | 
						|
		dockerfile := []byte(`
 | 
						|
FROM busybox
 | 
						|
copy Dockerfile .
 | 
						|
		`)
 | 
						|
		bakefile := []byte(`
 | 
						|
target "first" {
 | 
						|
	dockerfile = "Dockerfile"
 | 
						|
}
 | 
						|
target "second" {
 | 
						|
	dockerfile = "subdir/Dockerfile"
 | 
						|
}
 | 
						|
target "third" {
 | 
						|
	dockerfile = "subdir/subsubdir/Dockerfile"
 | 
						|
}
 | 
						|
	`)
 | 
						|
		dir := tmpdir(
 | 
						|
			t,
 | 
						|
			fstest.CreateDir("subdir", 0700),
 | 
						|
			fstest.CreateDir("subdir/subsubdir", 0700),
 | 
						|
			fstest.CreateFile("Dockerfile", dockerfile, 0600),
 | 
						|
			fstest.CreateFile("subdir/Dockerfile", dockerfile, 0600),
 | 
						|
			fstest.CreateFile("subdir/subsubdir/Dockerfile", dockerfile, 0600),
 | 
						|
			fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
 | 
						|
		)
 | 
						|
 | 
						|
		dockerfilePathFirst := "Dockerfile"
 | 
						|
		dockerfilePathSecond := filepath.Join("subdir", "Dockerfile")
 | 
						|
		dockerfilePathThird := filepath.Join("subdir", "subsubdir", "Dockerfile")
 | 
						|
 | 
						|
		cmd := buildxCmd(
 | 
						|
			sb,
 | 
						|
			withDir(dir),
 | 
						|
			withArgs("bake", "--call", "check", "first", "second", "third"),
 | 
						|
		)
 | 
						|
		stdout := bytes.Buffer{}
 | 
						|
		stderr := bytes.Buffer{}
 | 
						|
		cmd.Stdout = &stdout
 | 
						|
		cmd.Stderr = &stderr
 | 
						|
		require.Error(t, cmd.Run(), stdout.String(), stderr.String())
 | 
						|
		require.Contains(t, stdout.String(), dockerfilePathFirst+":3")
 | 
						|
		require.Contains(t, stdout.String(), dockerfilePathSecond+":3")
 | 
						|
		require.Contains(t, stdout.String(), dockerfilePathThird+":3")
 | 
						|
	})
 | 
						|
}
 |