build: add OCI artifact default opt-out

Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
(cherry picked from commit 6ee129a76c8f588d19f43845396c4fe5814d6fbf)
This commit is contained in:
CrazyMax
2026-08-04 12:04:04 +02:00
parent df28b0a0b6
commit 094ba58ad3
3 changed files with 114 additions and 3 deletions
+23 -3
View File
@@ -65,6 +65,11 @@ var sendGitQueryAsInput = sync.OnceValue(func() bool {
return false
})
const (
noDefaultAttestationsEnv = "BUILDX_NO_DEFAULT_ATTESTATIONS"
noDefaultOCIArtifactEnv = "BUILDX_NO_DEFAULT_OCI_ARTIFACT"
)
// policyExplicitlyDisabled reports whether the user passed `--policy
// disabled=true`, which suppresses both user-defined and builtin default
// policies.
@@ -355,12 +360,11 @@ func toSolveOpt(ctx context.Context, np *noderesolver.ResolvedNode, multiDriver
}
if _, ok := opt.Attests["provenance"]; !ok && supportAttestations {
const noAttestEnv = "BUILDX_NO_DEFAULT_ATTESTATIONS"
var noProv bool
if v, ok := os.LookupEnv(noAttestEnv); ok {
if v, ok := os.LookupEnv(noDefaultAttestationsEnv); ok {
noProv, err = strconv.ParseBool(v)
if err != nil {
return nil, nil, errors.Wrap(err, "invalid "+noAttestEnv)
return nil, nil, errors.Wrap(err, "invalid "+noDefaultAttestationsEnv)
}
}
if !noProv {
@@ -436,6 +440,14 @@ func toSolveOpt(ctx context.Context, np *noderesolver.ResolvedNode, multiDriver
}
opt.Exports = exports
var noDefaultOCIArtifact bool
if v, ok := os.LookupEnv(noDefaultOCIArtifactEnv); ok {
noDefaultOCIArtifact, err = strconv.ParseBool(v)
if err != nil {
return nil, nil, errors.Wrap(err, "invalid "+noDefaultOCIArtifactEnv)
}
}
// set up exporters
for i, e := range opt.Exports {
if e.Type == "oci" && !nodeDriver.Features(ctx)[driver.OCIExporter] {
@@ -497,6 +509,14 @@ func toSolveOpt(ctx context.Context, np *noderesolver.ResolvedNode, multiDriver
opt.Exports[i].Attrs["buildinfo-attrs"] = v
}
}
if noDefaultOCIArtifact && supportAttestations {
switch opt.Exports[i].Type {
case client.ExporterImage, client.ExporterOCI, "moby":
if _, ok := opt.Exports[i].Attrs[string(exptypes.OptKeyOCIArtifact)]; !ok {
opt.Exports[i].Attrs[string(exptypes.OptKeyOCIArtifact)] = "false"
}
}
}
}
so.Exports = opt.Exports
+36
View File
@@ -79,6 +79,7 @@ var bakeTests = []func(t *testing.T, sb integration.Sandbox){
testBakeMetadataWarningsDedup,
testBakeMultiExporters,
testBakeLoadPush,
testBakeNoDefaultOCIArtifact,
testBakeListTargets,
testBakeListVariables,
testBakeListTypedVariables,
@@ -2232,6 +2233,41 @@ target "default" {
// TODO: test metadata file when supported by multi exporters https://github.com/docker/buildx/issues/2181
}
func testBakeNoDefaultOCIArtifact(t *testing.T, sb integration.Sandbox) {
if isMobyWorker(sb) {
t.Skip("attestations are not supported by the docker worker")
}
registry, err := sb.NewRegistry()
if errors.Is(err, integration.ErrRequirements) {
t.Skip(err.Error())
}
require.NoError(t, err)
target := registry + "/buildx/bake-no-default-oci-artifact:latest"
dockerfile := []byte(`
FROM scratch
COPY foo /foo
`)
bakefile := fmt.Appendf(nil, `
target "default" {
output = ["type=image,name=%s,push=true"]
attest = ["type=provenance"]
}
`, target)
dir := tmpdir(
t,
fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("foo", []byte("foo"), 0600),
)
out, err := bakeCmd(sb, withDir(dir), withEnv("BUILDX_NO_DEFAULT_OCI_ARTIFACT=true"))
require.NoError(t, err, string(out))
requireLegacyAttestationStorage(t, sb, target)
}
func testBakeLoadPush(t *testing.T, sb integration.Sandbox) {
if !isDockerContainerWorker(sb) {
t.Skip("only testing with docker-container worker")
+55
View File
@@ -66,6 +66,7 @@ var buildTests = []func(t *testing.T, sb integration.Sandbox){
testBuildLocalExportDeleteMode,
testBuildRegistryExport,
testBuildRegistryExportAttestations,
testBuildRegistryExportNoDefaultOCIArtifact,
testBuildTarExport,
testBuildMobyFromLocalImage,
testBuildDetailsLink,
@@ -633,6 +634,60 @@ func testBuildRegistryExportAttestations(t *testing.T, sb integration.Sandbox) {
require.Len(t, att.Layers, 1)
}
func testBuildRegistryExportNoDefaultOCIArtifact(t *testing.T, sb integration.Sandbox) {
if isMobyWorker(sb) {
t.Skip("attestations are not supported by the docker worker")
}
dir := createTestProject(t)
registry, err := sb.NewRegistry()
if errors.Is(err, integration.ErrRequirements) {
t.Skip(err.Error())
}
require.NoError(t, err)
target := registry + "/buildx/registry-no-default-oci-artifact:latest"
out, err := buildCmd(sb,
withEnv("BUILDX_NO_DEFAULT_OCI_ARTIFACT=true"),
withArgs(fmt.Sprintf("--output=type=image,name=%s,push=true", target), "--provenance=true", dir),
)
require.NoError(t, err, string(out))
requireLegacyAttestationStorage(t, sb, target)
}
func requireLegacyAttestationStorage(t *testing.T, sb integration.Sandbox, ref string) {
t.Helper()
cmd := buildxCmd(sb, withArgs("imagetools", "inspect", ref, "--raw"))
dt, err := cmd.CombinedOutput()
require.NoError(t, err, string(dt))
var idx ocispecs.Index
err = json.Unmarshal(dt, &idx)
require.NoError(t, err)
var attestation ocispecs.Descriptor
for _, desc := range idx.Manifests {
if desc.Annotations["vnd.docker.reference.type"] == "attestation-manifest" {
attestation = desc
break
}
}
require.NotEmpty(t, attestation.Digest)
cmd = buildxCmd(sb, withArgs("imagetools", "inspect", ref+"@"+attestation.Digest.String(), "--raw"))
dt, err = cmd.CombinedOutput()
require.NoError(t, err, string(dt))
var mfst ocispecs.Manifest
err = json.Unmarshal(dt, &mfst)
require.NoError(t, err)
require.Nil(t, mfst.Subject)
require.NotEmpty(t, mfst.Layers)
}
func testImageIDOutput(t *testing.T, sb integration.Sandbox) {
dockerfile := []byte(`FROM busybox:latest`)