diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml
index b0d3ac43..484e20fc 100644
--- a/.github/workflows/e2e.yml
+++ b/.github/workflows/e2e.yml
@@ -84,6 +84,8 @@ jobs:
endpoint: tcp://localhost:1234
- driver: docker-container
metadata-provenance: max
+ - driver: docker-container
+ metadata-warnings: true
exclude:
- driver: docker
multi-node: mnode-true
@@ -134,6 +136,9 @@ jobs:
if [ -n "${{ matrix.metadata-provenance }}" ]; then
echo "BUILDX_METADATA_PROVENANCE=${{ matrix.metadata-provenance }}" >> $GITHUB_ENV
fi
+ if [ -n "${{ matrix.metadata-warnings }}" ]; then
+ echo "BUILDX_METADATA_WARNINGS=${{ matrix.metadata-warnings }}" >> $GITHUB_ENV
+ fi
-
name: Install k3s
if: matrix.driver == 'kubernetes'
diff --git a/commands/bake.go b/commands/bake.go
index 6c5a02e2..a8805eb9 100644
--- a/commands/bake.go
+++ b/commands/bake.go
@@ -22,6 +22,7 @@ import (
"github.com/docker/buildx/util/progress"
"github.com/docker/buildx/util/tracing"
"github.com/docker/cli/cli/command"
+ "github.com/moby/buildkit/client"
"github.com/moby/buildkit/identity"
"github.com/moby/buildkit/util/progress/progressui"
"github.com/pkg/errors"
@@ -130,15 +131,30 @@ func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in ba
return err
}
+ var resp map[string]*client.SolveResponse
+
defer func() {
if printer != nil {
err1 := printer.Wait()
if err == nil {
err = err1
}
- if err == nil && progressMode != progressui.QuietMode && progressMode != progressui.RawJSONMode {
+ if err != nil {
+ return
+ }
+ if progressMode != progressui.QuietMode && progressMode != progressui.RawJSONMode {
desktop.PrintBuildDetails(os.Stderr, printer.BuildRefs(), term)
}
+ if resp != nil && len(in.metadataFile) > 0 {
+ dt := make(map[string]interface{})
+ for t, r := range resp {
+ dt[t] = decodeExporterResponse(r.ExporterResponse)
+ }
+ if warnings := printer.Warnings(); len(warnings) > 0 && confutil.MetadataWarningsEnabled() {
+ dt["buildx.build.warnings"] = warnings
+ }
+ err = writeMetadataFile(in.metadataFile, dt)
+ }
}
}()
@@ -229,22 +245,12 @@ func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in ba
return err
}
- resp, err := build.Build(ctx, nodes, bo, dockerutil.NewClient(dockerCli), confutil.ConfigDir(dockerCli), printer)
+ resp, err = build.Build(ctx, nodes, bo, dockerutil.NewClient(dockerCli), confutil.ConfigDir(dockerCli), printer)
if err != nil {
return wrapBuildError(err, true)
}
- if len(in.metadataFile) > 0 {
- dt := make(map[string]interface{})
- for t, r := range resp {
- dt[t] = decodeExporterResponse(r.ExporterResponse)
- }
- if err := writeMetadataFile(in.metadataFile, dt); err != nil {
- return err
- }
- }
-
- return err
+ return
}
func bakeCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
diff --git a/commands/build.go b/commands/build.go
index 7301e1cc..c3b40bd7 100644
--- a/commands/build.go
+++ b/commands/build.go
@@ -374,7 +374,11 @@ func runBuild(ctx context.Context, dockerCli command.Cli, options buildOptions)
return err
}
} else if options.metadataFile != "" {
- if err := writeMetadataFile(options.metadataFile, decodeExporterResponse(resp.ExporterResponse)); err != nil {
+ dt := decodeExporterResponse(resp.ExporterResponse)
+ if warnings := printer.Warnings(); len(warnings) > 0 && confutil.MetadataWarningsEnabled() {
+ dt["buildx.build.warnings"] = warnings
+ }
+ if err := writeMetadataFile(options.metadataFile, dt); err != nil {
return err
}
}
diff --git a/docs/reference/buildx_bake.md b/docs/reference/buildx_bake.md
index d50b8f77..cc21e523 100644
--- a/docs/reference/buildx_bake.md
+++ b/docs/reference/buildx_bake.md
@@ -119,6 +119,7 @@ $ cat metadata.json
```json
{
+ "buildx.build.warnings": {},
"db": {
"buildx.build.provenance": {},
"buildx.build.ref": "mybuilder/mybuilder0/0fjb6ubs52xx3vygf6fgdl611",
@@ -161,6 +162,12 @@ $ cat metadata.json
> * `max` sets full provenance.
> * `disabled`, `false` or `0` does not set any provenance.
+> **Note**
+>
+> Build warnings (`buildx.build.warnings`) are not included by default. Set the
+> `BUILDX_METADATA_WARNINGS` environment variable to `1` or `true` to
+> include them.
+
### Don't use cache when building the image (--no-cache)
Same as `build --no-cache`. Don't use cache when building the image.
diff --git a/docs/reference/buildx_build.md b/docs/reference/buildx_build.md
index 3196de92..ea74ea20 100644
--- a/docs/reference/buildx_build.md
+++ b/docs/reference/buildx_build.md
@@ -330,6 +330,7 @@ $ cat metadata.json
{
"buildx.build.provenance": {},
"buildx.build.ref": "mybuilder/mybuilder0/0fjb6ubs52xx3vygf6fgdl611",
+ "buildx.build.warnings": {},
"containerimage.config.digest": "sha256:2937f66a9722f7f4a2df583de2f8cb97fc9196059a410e7f00072fc918930e66",
"containerimage.descriptor": {
"annotations": {
@@ -353,6 +354,12 @@ $ cat metadata.json
> * `max` sets full provenance.
> * `disabled`, `false` or `0` does not set any provenance.
+> **Note**
+>
+> Build warnings (`buildx.build.warnings`) are not included by default. Set the
+> `BUILDX_METADATA_WARNINGS` environment variable to `1` or `true` to
+> include them.
+
### Ignore build cache for specific stages (--no-cache-filter)
The `--no-cache-filter` lets you specify one or more stages of a multi-stage
diff --git a/hack/test-driver b/hack/test-driver
index 42659592..5d244a9e 100755
--- a/hack/test-driver
+++ b/hack/test-driver
@@ -109,21 +109,21 @@ buildxCmd inspect --bootstrap --builder="${builderName}"
# create dockerfile
cat > "${dockerfile}" < /log
-FROM busybox AS log
+FROM busybox As log
COPY --from=build /log /log
RUN cat /log
RUN uname -a
-FROM busybox AS hello
+FROm busybox AS hello
RUN echo hello > /hello
FROM scratch
-COPY --from=log /log /log
+CoPY --from=log /log /log
COPY --from=hello /hello /hello
EOL
diff --git a/tests/bake.go b/tests/bake.go
index 3b3591fe..bca99b0c 100644
--- a/tests/bake.go
+++ b/tests/bake.go
@@ -9,6 +9,7 @@ import (
"github.com/containerd/continuity/fs/fstest"
"github.com/docker/buildx/util/gitutil"
+ "github.com/moby/buildkit/client"
"github.com/moby/buildkit/identity"
provenancetypes "github.com/moby/buildkit/solver/llbsolver/provenance/types"
"github.com/moby/buildkit/util/contentutil"
@@ -42,7 +43,8 @@ var bakeTests = []func(t *testing.T, sb integration.Sandbox){
testBakeEmpty,
testBakeShmSize,
testBakeUlimits,
- testBakeMetadata,
+ testBakeMetadataProvenance,
+ testBakeMetadataWarnings,
testBakeMultiExporters,
testBakeLoadPush,
}
@@ -633,19 +635,22 @@ target "default" {
require.Contains(t, string(dt), `1024`)
}
-func testBakeMetadata(t *testing.T, sb integration.Sandbox) {
+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) {
- bakeMetadata(t, sb, "max")
+ bakeMetadataProvenance(t, sb, "max")
})
t.Run("min", func(t *testing.T) {
- bakeMetadata(t, sb, "min")
+ bakeMetadataProvenance(t, sb, "min")
})
t.Run("disabled", func(t *testing.T) {
- bakeMetadata(t, sb, "disabled")
+ bakeMetadataProvenance(t, sb, "disabled")
})
}
-func bakeMetadata(t *testing.T, sb integration.Sandbox, metadataMode string) {
+func bakeMetadataProvenance(t *testing.T, sb integration.Sandbox, metadataMode string) {
dockerfile := []byte(`
FROM scratch
COPY foo /foo
@@ -676,7 +681,7 @@ target "default" {
withEnv("BUILDX_METADATA_PROVENANCE="+metadataMode),
)
out, err := cmd.CombinedOutput()
- require.NoError(t, err, out)
+ require.NoError(t, err, string(out))
dt, err := os.ReadFile(filepath.Join(dirDest, "md.json"))
require.NoError(t, err)
@@ -706,6 +711,71 @@ target "default" {
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 testBakeMultiExporters(t *testing.T, sb integration.Sandbox) {
if !isDockerContainerWorker(sb) {
t.Skip("only testing with docker-container worker")
diff --git a/tests/build.go b/tests/build.go
index c79b2228..7d586a15 100644
--- a/tests/build.go
+++ b/tests/build.go
@@ -16,6 +16,7 @@ import (
"github.com/containerd/containerd/platforms"
"github.com/containerd/continuity/fs/fstest"
"github.com/creack/pty"
+ "github.com/moby/buildkit/client"
"github.com/moby/buildkit/frontend/subrequests/lint"
"github.com/moby/buildkit/frontend/subrequests/outline"
"github.com/moby/buildkit/frontend/subrequests/targets"
@@ -59,7 +60,8 @@ var buildTests = []func(t *testing.T, sb integration.Sandbox){
testBuildNetworkModeBridge,
testBuildShmSize,
testBuildUlimit,
- testBuildMetadata,
+ testBuildMetadataProvenance,
+ testBuildMetadataWarnings,
testBuildMultiExporters,
testBuildLoadPush,
testBuildSecret,
@@ -560,19 +562,22 @@ COPY --from=build /ulimit /
require.Contains(t, string(dt), `1024`)
}
-func testBuildMetadata(t *testing.T, sb integration.Sandbox) {
+func testBuildMetadataProvenance(t *testing.T, sb integration.Sandbox) {
+ t.Run("default", func(t *testing.T) {
+ buildMetadataProvenance(t, sb, "")
+ })
t.Run("max", func(t *testing.T) {
- buildMetadata(t, sb, "max")
+ buildMetadataProvenance(t, sb, "max")
})
t.Run("min", func(t *testing.T) {
- buildMetadata(t, sb, "min")
+ buildMetadataProvenance(t, sb, "min")
})
t.Run("disabled", func(t *testing.T) {
- buildMetadata(t, sb, "disabled")
+ buildMetadataProvenance(t, sb, "disabled")
})
}
-func buildMetadata(t *testing.T, sb integration.Sandbox, metadataMode string) {
+func buildMetadataProvenance(t *testing.T, sb integration.Sandbox, metadataMode string) {
dir := createTestProject(t)
dirDest := t.TempDir()
@@ -616,6 +621,61 @@ func buildMetadata(t *testing.T, sb integration.Sandbox, metadataMode string) {
require.Equal(t, provenancetypes.BuildKitBuildType, prv.BuildType)
}
+func testBuildMetadataWarnings(t *testing.T, sb integration.Sandbox) {
+ t.Run("default", func(t *testing.T) {
+ buildMetadataWarnings(t, sb, "")
+ })
+ t.Run("true", func(t *testing.T) {
+ buildMetadataWarnings(t, sb, "true")
+ })
+ t.Run("false", func(t *testing.T) {
+ buildMetadataWarnings(t, sb, "false")
+ })
+}
+
+func buildMetadataWarnings(t *testing.T, sb integration.Sandbox, mode string) {
+ dockerfile := []byte(`
+frOM busybox as base
+cOpy Dockerfile .
+from scratch
+COPy --from=base \
+ /Dockerfile \
+ /
+ `)
+ dir := tmpdir(
+ t,
+ fstest.CreateFile("Dockerfile", dockerfile, 0600),
+ )
+
+ cmd := buildxCmd(
+ sb,
+ withArgs("build", "--metadata-file", filepath.Join(dir, "md.json"), dir),
+ withEnv("BUILDX_METADATA_WARNINGS="+mode),
+ )
+ out, err := cmd.CombinedOutput()
+ require.NoError(t, err, string(out))
+
+ dt, err := os.ReadFile(filepath.Join(dir, "md.json"))
+ require.NoError(t, err)
+
+ type mdT struct {
+ BuildRef string `json:"buildx.build.ref"`
+ BuildWarnings []client.VertexWarning `json:"buildx.build.warnings"`
+ }
+ var md mdT
+ err = json.Unmarshal(dt, &md)
+ require.NoError(t, err, string(dt))
+
+ require.NotEmpty(t, md.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 testBuildMultiExporters(t *testing.T, sb integration.Sandbox) {
if !isDockerContainerWorker(sb) {
t.Skip("only testing with docker-container worker")
diff --git a/util/confutil/metadata.go b/util/confutil/metadata.go
index a655eec8..b30a7b26 100644
--- a/util/confutil/metadata.go
+++ b/util/confutil/metadata.go
@@ -39,3 +39,12 @@ func ParseMetadataProvenance(inp string) MetadataProvenanceMode {
}
return MetadataProvenanceModeMin
}
+
+// MetadataWarningsEnabled returns whether metadata warnings are enabled from
+// BUILDX_METADATA_WARNINGS environment variable (default false)
+func MetadataWarningsEnabled() bool {
+ if ok, err := strconv.ParseBool(os.Getenv("BUILDX_METADATA_WARNINGS")); err == nil {
+ return ok
+ }
+ return false
+}