Skip to content

bake: overriding attest per-target when target inherit a base target already defining attest #3599

@nuxwin

Description

@nuxwin

Contributing guidelines

I've found a bug and checked that ...

  • ... the documentation does not mention anything about my problem
  • ... there are no open or closed issues that are related to my problem

Description

Good morning,

Right now, it seem that we cannot override attest on per-target basis when those target inherit from a base target which already define attest:

For any target (final) that is not runtime (name), attest should be empty but actually, i get something like :

docker buildx bake --file .docker/docker-bake.hcl --print publica-negotia-ci

[+] Building 0.0s (1/1) FINISHED                                                                                                                                                 
 => [internal] load local bake definitions                                                                                                                                  0.0s
 => => reading .docker/docker-bake.hcl 11.34kB / 11.34kB                                                                                                                    0.0s
{
  "group": {
    "default": {
      "targets": [
        "publica-negotia-ci"
      ]
    }
  },
  "target": {
    "publica-negotia-ci": {
      "annotations": [
        "index:org.opencontainers.image.source=https://git.konzeptplus.ch/agon/solution/publica-negotia/publica-negotia",
        "index:org.opencontainers.image.licenses=Proprietary",
        "index:org.opencontainers.image.vendor=Agon Partners Innovation",
        "index,manifest:org.opencontainers.image.created=2026-01-15T10:54:34Z",
        "index,manifest:org.opencontainers.image.revision=NoSet",
        "index:org.opencontainers.image.version=NoSet",
        "index:org.opencontainers.image.title=publica-negotia",
        "index:org.opencontainers.image.description=Publica Negotia – Application image"
      ],
      "attest": [
        {
          "mode": "max",
          "type": "provenance"
        },
        {
          "type": "sbom"
        }
      ],
      "context": ".",
      "dockerfile": ".docker/application/Dockerfile",
      "labels": {
        "org.opencontainers.image.authors": "Laurent Declercq \u003cl.declercq@agon-innovation.ch\u003e",
        "org.opencontainers.image.created": "2026-01-15T10:54:34Z",
        "org.opencontainers.image.licenses": "proprietary",
        "org.opencontainers.image.maintainer": "Laurent Declercq \u003cl.declercq@agon-innovation.ch\u003e",
        "org.opencontainers.image.revision": "NoSet",
        "org.opencontainers.image.source": "https://git.konzeptplus.ch/agon/solution/publica-negotia/publica-negotia",
        "org.opencontainers.image.vendor": "Agon Partners Innovation",
        "org.opencontainers.image.version": "NoSet"
      },
      "tags": [
        "hub.agon-partners-innovation.ch/agon/solution/publica-negotia/publica-negotia:ci"
      ],
      "cache-from": [
        {
          "ref": "hub.agon-partners-innovation.ch/agon/solution/publica-negotia/cache/publica-negotia:ci",
          "type": "registry"
        }
      ],
      "cache-to": [
        {
          "compression": "zstd",
          "image-manifest": "true",
          "mode": "max",
          "oci-mediatypes": "true",
          "ref": "hub.agon-partners-innovation.ch/agon/solution/publica-negotia/cache/publica-negotia:ci",
          "type": "registry"
        }
      ],
      "target": "ci",
      "secret": [
        {
          "id": "ci_deploy_user",
          "env": "CI_DEPLOY_USER"
        },
        {
          "id": "ci_deploy_token",
          "env": "CI_DEPLOY_PASSWORD"
        }
      ],
      "platforms": [
        "linux/amd64",
        "linux/arm64"
      ],
      "output": [
        {
          "type": "registry"
        }
      ],
      "pull": true
    }
  }
}

Expected behaviour

      "attest": [],

Actual behaviour

      "attest": [
        {
          "mode": "max",
          "type": "provenance"
        },
        {
          "type": "sbom"
        }
      ],

Buildx version

github.com/docker/buildx v0.30.1-desktop.1 792b8327a475a5d8c9d5f4ea6ce866e7da39ae8b

Docker info

Client:
 Version:    29.1.3
 Context:    desktop-linux
 Debug Mode: false
 Plugins:
  ai: Docker AI Agent - Ask Gordon (Docker Inc.)
    Version:  v1.17.1
    Path:     /Users/laurentd/.docker/cli-plugins/docker-ai
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.30.1-desktop.1
    Path:     /Users/laurentd/.docker/cli-plugins/docker-buildx
  compose: Docker Compose (Docker Inc.)
    Version:  v5.0.0-desktop.1
    Path:     /Users/laurentd/.docker/cli-plugins/docker-compose
  debug: Get a shell into any image or container (Docker Inc.)
    Version:  0.0.46
    Path:     /Users/laurentd/.docker/cli-plugins/docker-debug
  desktop: Docker Desktop commands (Docker Inc.)
    Version:  v0.2.0
    Path:     /Users/laurentd/.docker/cli-plugins/docker-desktop
  extension: Manages Docker extensions (Docker Inc.)
    Version:  v0.2.31
    Path:     /Users/laurentd/.docker/cli-plugins/docker-extension
  init: Creates Docker-related starter files for your project (Docker Inc.)
    Version:  v1.4.0
    Path:     /Users/laurentd/.docker/cli-plugins/docker-init
  mcp: Docker MCP Plugin (Docker Inc.)
    Version:  v0.35.0
    Path:     /Users/laurentd/.docker/cli-plugins/docker-mcp
  model: Docker Model Runner (Docker Inc.)
    Version:  v1.0.6
    Path:     /Users/laurentd/.docker/cli-plugins/docker-model
  offload: Docker Offload (Docker Inc.)
    Version:  v0.5.38
    Path:     /Users/laurentd/.docker/cli-plugins/docker-offload
  pass: Docker Pass Secrets Manager Plugin (beta) (Docker Inc.)
    Version:  v0.0.22
    Path:     /Users/laurentd/.docker/cli-plugins/docker-pass
  sandbox: Docker Sandbox (Docker Inc.)
    Version:  v0.6.0
    Path:     /Users/laurentd/.docker/cli-plugins/docker-sandbox
  sbom: View the packaged-based Software Bill Of Materials (SBOM) for an image (Anchore Inc.)
    Version:  0.6.0
    Path:     /Users/laurentd/.docker/cli-plugins/docker-sbom
  scout: Docker Scout (Docker Inc.)
    Version:  v1.19.0
    Path:     /Users/laurentd/.docker/cli-plugins/docker-scout

Server:
 Containers: 2
  Running: 2
  Paused: 0
  Stopped: 0
 Images: 10
 Server Version: 29.1.3
 Storage Driver: overlayfs
  driver-type: io.containerd.snapshotter.v1
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
 CDI spec directories:
  /etc/cdi
  /var/run/cdi
 Discovered Devices:
  cdi: docker.com/gpu=webgpu
 Swarm: inactive
 Runtimes: runc io.containerd.runc.v2
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: dea7da592f5d1d2b7755e3a161be07f43fad8f75
 runc version: v1.3.4-0-gd6d73eb8
 init version: de40ad0
 Security Options:
  seccomp
   Profile: builtin
  cgroupns
 Kernel Version: 6.12.54-linuxkit
 Operating System: Docker Desktop
 OSType: linux
 Architecture: aarch64
 CPUs: 14
 Total Memory: 7.75GiB
 Name: docker-desktop
 ID: 7df16ec3-c53c-4865-9c33-22e75a096db8
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 HTTP Proxy: http.docker.internal:3128
 HTTPS Proxy: http.docker.internal:3128
 No Proxy: hubproxy.docker.internal
 Labels:
  com.docker.desktop.address=unix:///Users/laurentd/Library/Containers/com.docker.docker/Data/docker-cli.sock
 Experimental: false
 Insecure Registries:
  hubproxy.docker.internal:5555
  ::1/128
  127.0.0.0/8
 Live Restore Enabled: false
 Firewall Backend: iptables

Builders list

(publica-negotia) laurentd@MacBook-Pro-de-Laurent publica-negotia % docker buildx ls
NAME/NODE           DRIVER/ENDPOINT     STATUS    BUILDKIT   PLATFORMS
nuxwin*             docker-container                         
 \_ nuxwin0          \_ desktop-linux   running   v0.26.3    linux/amd64 (+2), linux/arm64, linux/arm (+2), linux/ppc64le, (3 more)
default             docker                                   
 \_ default          \_ default         running   v0.26.2    linux/amd64 (+2), linux/arm64, linux/ppc64le, linux/s390x, (2 more)
desktop-linux       docker                                   
 \_ desktop-linux    \_ desktop-linux   running   v0.26.2    linux/amd64 (+2), linux/arm64, linux/ppc64le, linux/s390x, (2 more)

Configuration

Base target

target "_base" {
    # Build multi-platform image (amd64 and arm64).
    platforms = ["linux/amd64", "linux/arm64"]

    # Runtime metadata (image configuration, visible at runtime).
    labels = {
        "org.opencontainers.image.version"    = CI_COMMIT_TAG
        "org.opencontainers.image.revision"   = CI_COMMIT_SHA
        "org.opencontainers.image.created"    = BUILD_DATE
        "org.opencontainers.image.source"     = "https://git.konzeptplus.ch/agon/solution/publica-negotia/publica-negotia"
        "org.opencontainers.image.vendor"     = "Agon Partners Innovation"
        "org.opencontainers.image.licenses"   = "proprietary"
        "org.opencontainers.image.maintainer" = "Laurent Declercq <l.declercq@agon-innovation.ch>"
        "org.opencontainers.image.authors"    = "Laurent Declercq <l.declercq@agon-innovation.ch>"
    }

    # OCI annotations (index / manifest metadata).
    annotations = [
        (notequal("NoSet", CI_COMMIT_TAG) ? "index:org.opencontainers.image.ref.name=${CI_COMMIT_TAG}" : ""),
        "index:org.opencontainers.image.source=https://git.konzeptplus.ch/agon/solution/publica-negotia/publica-negotia",
        "index:org.opencontainers.image.licenses=Proprietary",
        "index:org.opencontainers.image.vendor=Agon Partners Innovation",
        "index,manifest:org.opencontainers.image.created=${BUILD_DATE}",
        "index,manifest:org.opencontainers.image.revision=${CI_COMMIT_SHA}",
        "index:org.opencontainers.image.version=${CI_COMMIT_TAG}",
    ]

    # Supply-chain metadata (OCI artifacts).
    attest = [
        # SLSA provenance (recommended default).
        {
            type = "provenance"
            mode = "max"
        },
        # SBOM (SPDX JSON, OCI-native).
        {
            type = "sbom"
        }
    ]

    # Always attempt to pull a newer version of the base image.
    pull = true

    # Output
    output = [
        # Push the built image to the registry.
        {
            type = "registry"
        }
    ]
}

Target that inherit the base target

target "publica-negotia" {
    inherits = ["_base"]
    dockerfile = ".docker/application/Dockerfile"
    name       = "publica-negotia-${item.name}"
    annotations = [
        "index:org.opencontainers.image.title=publica-negotia",
        "index:org.opencontainers.image.description=Publica Negotia – Application image"
    ]
    matrix = {
        item = [
            # Production build (for production environments). Technically deployable artifact for production use.
            {
                name   = "runtime"
                target = "runtime"
                tags = ["production", "latest"]
            },
            # Preview build (for staging environments). Technically deployable artifact, but not intended for production
            # use.
            {
                name   = "staging"
                target = "runtime"
                tags = ["preview"]

            },
            # CI build (for linting/testing in CI pipelines). Not a deployable artifact.
            {
                name   = "ci"
                target = "ci"
                tags = concat(["ci"], (notequal("NoSet", CI_COMMIT_SHA) ? ["ci-${CI_COMMIT_SHA}"] : []))

            },
            # Development build (for developers). Not a deployable artifact.
            {
                name   = "dev"
                target = "dev"
                tags = ["dev"]
            },
            # Nightly build (Scheduled pipeline): Technically deployable artifact, but not intended for production use.
            {
                name   = "nightly"
                target = "runtime"
                tags = ["nightly"]
            }
        ]
    }
    tags = concat(
        # Tags based on the item tags (production, preview, ci, dev, nightly).
        [for tag in item.tags : "${HARBOR_URL}/${HARBOR_PROJECT}/publica-negotia:${tag}"],
        # Only deployable artifacts must be tagged with the commit tag.
        (
            notequal("NoSet", CI_COMMIT_TAG) && equal("runtime", item.name)
            ? ["${HARBOR_URL}/${HARBOR_PROJECT}/publica-negotia:${CI_COMMIT_TAG}"]
            : []
        ),
        # Only deployable artifacts must be tagged with the commit SHA.
        (
            notequal("NoSet", CI_COMMIT_SHA) && equal("runtime", item.name)
            ? ["${HARBOR_URL}/${HARBOR_PROJECT}/publica-negotia:${CI_COMMIT_SHA}"]
            : []
        )
    )
    target = item.target
    attest = equal("runtime", item.name) ? target._base.attest : []
    cache-to = [
        {
            type                  = "registry"
            ref                     = "${HARBOR_URL}/${HARBOR_PROJECT}/cache/publica-negotia:${item.name}"
            compression     = "zstd"
            mode                 = "max"
            oci-mediatypes = true
            image-manifest = true
        }
    ]
    cache-from = [
        {
            type = "registry"
            ref  = "${HARBOR_URL}/${HARBOR_PROJECT}/cache/publica-negotia:${item.name}"
        }
    ]
    secret = [
        {
            id  = "ci_deploy_user"
            env = "CI_DEPLOY_USER"
        },
        {
            id  = "ci_deploy_token"
            env = "CI_DEPLOY_PASSWORD"
        }
    ]
}

Build logs


Additional info

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions