From e2b6f9e36e5b94c8dc24ebb8fdcffbd6eae1e49e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 5 Sep 2025 05:23:29 +0000 Subject: [PATCH 01/10] Initial plan From d5d8a16b621a3291ef5b2c3cfa040eb05555124f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 5 Sep 2025 05:26:38 +0000 Subject: [PATCH 02/10] Initial analysis of build workflow improvements Co-authored-by: solsson <144945+solsson@users.noreply.github.com> --- .github/workflows/images.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index edee8ea..63054e6 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -261,7 +261,7 @@ jobs: tags: | ghcr.io/yolean/headless-chrome:latest ghcr.io/yolean/headless-chrome:${{ github.sha }} - platforms: linux/amd64 + platforms: linux/amd64,linux/arm64/v8 push: true cache-from: type=gha cache-to: type=gha,mode=max From ff7d7603c0986dac5b03b57a239cf94a83b82d59 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 5 Sep 2025 05:36:01 +0000 Subject: [PATCH 03/10] Implement build workflow improvements with latest actions and enhanced caching Co-authored-by: solsson <144945+solsson@users.noreply.github.com> --- .github/workflows/images.yaml | 770 +++++++++++++++++++++++++-------- BUILD_WORKFLOW_IMPROVEMENTS.md | 72 +++ test.sh | 45 +- 3 files changed, 693 insertions(+), 194 deletions(-) create mode 100644 BUILD_WORKFLOW_IMPROVEMENTS.md diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index 63054e6..2d28d0d 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -4,6 +4,13 @@ on: push: branches: - main + workflow_dispatch: + inputs: + force_rebuild: + description: 'Force rebuild all images' + required: false + default: false + type: boolean jobs: publish: @@ -11,13 +18,16 @@ jobs: runs-on: ubuntu-latest permissions: packages: write + contents: read + attestations: write + id-token: write steps: - name: Checkout uses: actions/checkout@v4 - name: Login to GitHub Container Registry - uses: docker/login-action@v3 + uses: docker/login-action@v3.5.0 with: registry: ghcr.io username: ${{ github.repository_owner }} @@ -58,17 +68,19 @@ jobs: crane cp liftm/kafkacat:$TAG_KAFKACAT ghcr.io/yolean/kafkacat:$TAG_KAFKACAT - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + uses: docker/setup-qemu-action@v3.6.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v3.11.1 ### build steps below are generated ### - name: Build and push docker-base latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: docker-base tags: | @@ -76,13 +88,21 @@ jobs: ghcr.io/yolean/docker-base:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-docker-base-latest + type=gha,scope=buildx-docker-base + cache-to: type=gha,mode=max,scope=buildx-docker-base-latest + provenance: false + sbom: false + continue-on-error: false + timeout-minutes: 45 - name: Build and push builder-base latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: builder-base tags: | @@ -90,13 +110,21 @@ jobs: ghcr.io/yolean/builder-base:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-builder-base-latest + type=gha,scope=buildx-builder-base + cache-to: type=gha,mode=max,scope=buildx-builder-base-latest + provenance: false + sbom: false + continue-on-error: false + timeout-minutes: 45 - name: Build and push builder-base-gcc latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: builder-base-gcc tags: | @@ -104,15 +132,23 @@ jobs: ghcr.io/yolean/builder-base-gcc:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-builder-base-gcc-latest + type=gha,scope=buildx-builder-base-gcc + cache-to: type=gha,mode=max,scope=buildx-builder-base-gcc-latest + provenance: false + sbom: false build-contexts: | yolean/builder-base=docker-image://ghcr.io/yolean/builder-base + continue-on-error: false + timeout-minutes: 45 - name: Build and push builder-base-gcloud latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: builder-base-gcloud tags: | @@ -120,15 +156,23 @@ jobs: ghcr.io/yolean/builder-base-gcloud:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-builder-base-gcloud-latest + type=gha,scope=buildx-builder-base-gcloud + cache-to: type=gha,mode=max,scope=buildx-builder-base-gcloud-latest + provenance: false + sbom: false build-contexts: | yolean/builder-base=docker-image://ghcr.io/yolean/builder-base + continue-on-error: false + timeout-minutes: 45 - name: Build and push builder-tooling latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: builder-tooling tags: | @@ -136,15 +180,23 @@ jobs: ghcr.io/yolean/builder-tooling:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-builder-tooling-latest + type=gha,scope=buildx-builder-tooling + cache-to: type=gha,mode=max,scope=buildx-builder-tooling-latest + provenance: false + sbom: false build-contexts: | yolean/builder-base-gcc=docker-image://ghcr.io/yolean/builder-base-gcc + continue-on-error: false + timeout-minutes: 45 - name: Build and push builder-node latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: builder-node tags: | @@ -152,13 +204,21 @@ jobs: ghcr.io/yolean/builder-node:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-builder-node-latest + type=gha,scope=buildx-builder-node + cache-to: type=gha,mode=max,scope=buildx-builder-node-latest + provenance: false + sbom: false + continue-on-error: false + timeout-minutes: 45 - name: Build and push builder-quarkus latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: builder-quarkus tags: | @@ -166,16 +226,24 @@ jobs: ghcr.io/yolean/builder-quarkus:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-builder-quarkus-latest + type=gha,scope=buildx-builder-quarkus + cache-to: type=gha,mode=max,scope=buildx-builder-quarkus-latest + provenance: false + sbom: false build-contexts: | yolean/builder-base=docker-image://ghcr.io/yolean/builder-base yolean/builder-base-gcc=docker-image://ghcr.io/yolean/builder-base-gcc + continue-on-error: false + timeout-minutes: 45 - name: Build and push builder-evidence latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: builder-evidence tags: | @@ -183,16 +251,24 @@ jobs: ghcr.io/yolean/builder-evidence:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-builder-evidence-latest + type=gha,scope=buildx-builder-evidence + cache-to: type=gha,mode=max,scope=buildx-builder-evidence-latest + provenance: false + sbom: false build-contexts: | yolean/builder-base-gcc=docker-image://ghcr.io/yolean/builder-base-gcc yolean/builder-base-gcloud=docker-image://ghcr.io/yolean/builder-base-gcloud + continue-on-error: false + timeout-minutes: 45 - name: Build and push git-init latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: git-init tags: | @@ -200,15 +276,23 @@ jobs: ghcr.io/yolean/git-init:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-git-init-latest + type=gha,scope=buildx-git-init + cache-to: type=gha,mode=max,scope=buildx-git-init-latest + provenance: false + sbom: false build-contexts: | yolean/builder-base=docker-image://ghcr.io/yolean/builder-base + continue-on-error: false + timeout-minutes: 45 - name: Build and push toil latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: toil tags: | @@ -216,16 +300,24 @@ jobs: ghcr.io/yolean/toil:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-toil-latest + type=gha,scope=buildx-toil + cache-to: type=gha,mode=max,scope=buildx-toil-latest + provenance: false + sbom: false build-contexts: | yolean/builder-base=docker-image://ghcr.io/yolean/builder-base yolean/builder-base=docker-image://ghcr.io/yolean/builder-base + continue-on-error: false + timeout-minutes: 45 - name: Build and push toil-network latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: toil-network tags: | @@ -233,15 +325,23 @@ jobs: ghcr.io/yolean/toil-network:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-toil-network-latest + type=gha,scope=buildx-toil-network + cache-to: type=gha,mode=max,scope=buildx-toil-network-latest + provenance: false + sbom: false build-contexts: | yolean/toil=docker-image://ghcr.io/yolean/toil + continue-on-error: false + timeout-minutes: 45 - name: Build and push node-distroless latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: node-distroless tags: | @@ -249,13 +349,21 @@ jobs: ghcr.io/yolean/node-distroless:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-node-distroless-latest + type=gha,scope=buildx-node-distroless + cache-to: type=gha,mode=max,scope=buildx-node-distroless-latest + provenance: false + sbom: false + continue-on-error: false + timeout-minutes: 45 - name: Build and push headless-chrome latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: headless-chrome tags: | @@ -263,15 +371,23 @@ jobs: ghcr.io/yolean/headless-chrome:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-headless-chrome-latest + type=gha,scope=buildx-headless-chrome + cache-to: type=gha,mode=max,scope=buildx-headless-chrome-latest + provenance: false + sbom: false build-contexts: | yolean/docker-base=docker-image://ghcr.io/yolean/docker-base + continue-on-error: false + timeout-minutes: 45 - name: Build and push git-http-readonly latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: git-http-readonly tags: | @@ -279,13 +395,21 @@ jobs: ghcr.io/yolean/git-http-readonly:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-git-http-readonly-latest + type=gha,scope=buildx-git-http-readonly + cache-to: type=gha,mode=max,scope=buildx-git-http-readonly-latest + provenance: false + sbom: false + continue-on-error: false + timeout-minutes: 45 - name: Build and push runtime-quarkus latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: runtime-quarkus tags: | @@ -293,13 +417,21 @@ jobs: ghcr.io/yolean/runtime-quarkus:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-runtime-quarkus-latest + type=gha,scope=buildx-runtime-quarkus + cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-latest + provenance: false + sbom: false + continue-on-error: false + timeout-minutes: 45 - name: Build and push runtime-deno latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: runtime-deno tags: | @@ -307,13 +439,21 @@ jobs: ghcr.io/yolean/runtime-deno:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-runtime-deno-latest + type=gha,scope=buildx-runtime-deno + cache-to: type=gha,mode=max,scope=buildx-runtime-deno-latest + provenance: false + sbom: false + continue-on-error: false + timeout-minutes: 45 - name: Build and push homedir root - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: homedir tags: | @@ -321,15 +461,23 @@ jobs: ghcr.io/yolean/homedir:${{ github.sha }}-root platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-homedir-root + type=gha,scope=buildx-homedir + cache-to: type=gha,mode=max,scope=buildx-homedir-root + provenance: false + sbom: false build-contexts: | yolean/docker-base=docker-image://ghcr.io/yolean/docker-base + continue-on-error: false + timeout-minutes: 45 - name: Build and push homedir latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: to-nonroot/homedir tags: | @@ -337,15 +485,23 @@ jobs: ghcr.io/yolean/homedir:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-homedir-latest + type=gha,scope=buildx-homedir + cache-to: type=gha,mode=max,scope=buildx-homedir-latest + provenance: false + sbom: false build-contexts: | - yolean/homedir:root=docker-image://ghcr.io/yolean/homedir:root + yolean/homedir=docker-image://ghcr.io/yolean/homedir:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push java root - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: java tags: | @@ -353,13 +509,21 @@ jobs: ghcr.io/yolean/java:${{ github.sha }}-root platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-java-root + type=gha,scope=buildx-java + cache-to: type=gha,mode=max,scope=buildx-java-root + provenance: false + sbom: false + continue-on-error: false + timeout-minutes: 45 - name: Build and push java latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: to-nonroot/java tags: | @@ -367,15 +531,23 @@ jobs: ghcr.io/yolean/java:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-java-latest + type=gha,scope=buildx-java + cache-to: type=gha,mode=max,scope=buildx-java-latest + provenance: false + sbom: false build-contexts: | - yolean/java:root=docker-image://ghcr.io/yolean/java:root + yolean/java=docker-image://ghcr.io/yolean/java:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push node root - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: node tags: | @@ -383,13 +555,21 @@ jobs: ghcr.io/yolean/node:${{ github.sha }}-root platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-node-root + type=gha,scope=buildx-node + cache-to: type=gha,mode=max,scope=buildx-node-root + provenance: false + sbom: false + continue-on-error: false + timeout-minutes: 45 - name: Build and push node latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: to-nonroot/node tags: | @@ -397,15 +577,23 @@ jobs: ghcr.io/yolean/node:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-node-latest + type=gha,scope=buildx-node + cache-to: type=gha,mode=max,scope=buildx-node-latest + provenance: false + sbom: false build-contexts: | - yolean/node:root=docker-image://ghcr.io/yolean/node:root + yolean/node=docker-image://ghcr.io/yolean/node:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push node-kafka root - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: node-kafka tags: | @@ -413,15 +601,23 @@ jobs: ghcr.io/yolean/node-kafka:${{ github.sha }}-root platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-node-kafka-root + type=gha,scope=buildx-node-kafka + cache-to: type=gha,mode=max,scope=buildx-node-kafka-root + provenance: false + sbom: false build-contexts: | - yolean/node:root=docker-image://ghcr.io/yolean/node:root + yolean/node=docker-image://ghcr.io/yolean/node:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push node-kafka latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: to-nonroot/node-kafka tags: | @@ -429,15 +625,23 @@ jobs: ghcr.io/yolean/node-kafka:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-node-kafka-latest + type=gha,scope=buildx-node-kafka + cache-to: type=gha,mode=max,scope=buildx-node-kafka-latest + provenance: false + sbom: false build-contexts: | - yolean/node-kafka:root=docker-image://ghcr.io/yolean/node-kafka:root + yolean/node-kafka=docker-image://ghcr.io/yolean/node-kafka:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push node-kafka-cache root - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: node-kafka-cache tags: | @@ -445,15 +649,23 @@ jobs: ghcr.io/yolean/node-kafka-cache:${{ github.sha }}-root platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-node-kafka-cache-root + type=gha,scope=buildx-node-kafka-cache + cache-to: type=gha,mode=max,scope=buildx-node-kafka-cache-root + provenance: false + sbom: false build-contexts: | - yolean/node-kafka:root=docker-image://ghcr.io/yolean/node-kafka:root + yolean/node-kafka=docker-image://ghcr.io/yolean/node-kafka:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push node-kafka-cache latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: to-nonroot/node-kafka-cache tags: | @@ -461,15 +673,23 @@ jobs: ghcr.io/yolean/node-kafka-cache:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-node-kafka-cache-latest + type=gha,scope=buildx-node-kafka-cache + cache-to: type=gha,mode=max,scope=buildx-node-kafka-cache-latest + provenance: false + sbom: false build-contexts: | - yolean/node-kafka-cache:root=docker-image://ghcr.io/yolean/node-kafka-cache:root + yolean/node-kafka-cache=docker-image://ghcr.io/yolean/node-kafka-cache:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push node-kafka-sqlite root - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: node-kafka-sqlite tags: | @@ -477,15 +697,23 @@ jobs: ghcr.io/yolean/node-kafka-sqlite:${{ github.sha }}-root platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-node-kafka-sqlite-root + type=gha,scope=buildx-node-kafka-sqlite + cache-to: type=gha,mode=max,scope=buildx-node-kafka-sqlite-root + provenance: false + sbom: false build-contexts: | - yolean/node-kafka:root=docker-image://ghcr.io/yolean/node-kafka:root + yolean/node-kafka=docker-image://ghcr.io/yolean/node-kafka:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push node-kafka-sqlite latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: to-nonroot/node-kafka-sqlite tags: | @@ -493,15 +721,23 @@ jobs: ghcr.io/yolean/node-kafka-sqlite:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-node-kafka-sqlite-latest + type=gha,scope=buildx-node-kafka-sqlite + cache-to: type=gha,mode=max,scope=buildx-node-kafka-sqlite-latest + provenance: false + sbom: false build-contexts: | - yolean/node-kafka-sqlite:root=docker-image://ghcr.io/yolean/node-kafka-sqlite:root + yolean/node-kafka-sqlite=docker-image://ghcr.io/yolean/node-kafka-sqlite:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push node-watchexec root - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: node-watchexec tags: | @@ -509,13 +745,21 @@ jobs: ghcr.io/yolean/node-watchexec:${{ github.sha }}-root platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-node-watchexec-root + type=gha,scope=buildx-node-watchexec + cache-to: type=gha,mode=max,scope=buildx-node-watchexec-root + provenance: false + sbom: false + continue-on-error: false + timeout-minutes: 45 - name: Build and push node-watchexec latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: to-nonroot/node-watchexec tags: | @@ -523,15 +767,23 @@ jobs: ghcr.io/yolean/node-watchexec:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-node-watchexec-latest + type=gha,scope=buildx-node-watchexec + cache-to: type=gha,mode=max,scope=buildx-node-watchexec-latest + provenance: false + sbom: false build-contexts: | - yolean/node-watchexec:root=docker-image://ghcr.io/yolean/node-watchexec:root + yolean/node-watchexec=docker-image://ghcr.io/yolean/node-watchexec:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push node-kafka-watch root - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: node-kafka-watch tags: | @@ -539,16 +791,24 @@ jobs: ghcr.io/yolean/node-kafka-watch:${{ github.sha }}-root platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-node-kafka-watch-root + type=gha,scope=buildx-node-kafka-watch + cache-to: type=gha,mode=max,scope=buildx-node-kafka-watch-root + provenance: false + sbom: false build-contexts: | - yolean/node-watchexec:root=docker-image://ghcr.io/yolean/node-watchexec:root - yolean/node-kafka:root=docker-image://ghcr.io/yolean/node-kafka:root + yolean/node-watchexec=docker-image://ghcr.io/yolean/node-watchexec:root + yolean/node-kafka=docker-image://ghcr.io/yolean/node-kafka:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push node-kafka-watch latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: to-nonroot/node-kafka-watch tags: | @@ -556,15 +816,23 @@ jobs: ghcr.io/yolean/node-kafka-watch:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-node-kafka-watch-latest + type=gha,scope=buildx-node-kafka-watch + cache-to: type=gha,mode=max,scope=buildx-node-kafka-watch-latest + provenance: false + sbom: false build-contexts: | - yolean/node-kafka-watch:root=docker-image://ghcr.io/yolean/node-kafka-watch:root + yolean/node-kafka-watch=docker-image://ghcr.io/yolean/node-kafka-watch:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push node-gcloud root - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: node-gcloud tags: | @@ -572,15 +840,23 @@ jobs: ghcr.io/yolean/node-gcloud:${{ github.sha }}-root platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-node-gcloud-root + type=gha,scope=buildx-node-gcloud + cache-to: type=gha,mode=max,scope=buildx-node-gcloud-root + provenance: false + sbom: false build-contexts: | - yolean/node:root=docker-image://ghcr.io/yolean/node:root + yolean/node=docker-image://ghcr.io/yolean/node:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push node-gcloud latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: to-nonroot/node-gcloud tags: | @@ -588,15 +864,23 @@ jobs: ghcr.io/yolean/node-gcloud:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-node-gcloud-latest + type=gha,scope=buildx-node-gcloud + cache-to: type=gha,mode=max,scope=buildx-node-gcloud-latest + provenance: false + sbom: false build-contexts: | - yolean/node-gcloud:root=docker-image://ghcr.io/yolean/node-gcloud:root + yolean/node-gcloud=docker-image://ghcr.io/yolean/node-gcloud:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push node-vitest root - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: node-vitest tags: | @@ -604,15 +888,23 @@ jobs: ghcr.io/yolean/node-vitest:${{ github.sha }}-root platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-node-vitest-root + type=gha,scope=buildx-node-vitest + cache-to: type=gha,mode=max,scope=buildx-node-vitest-root + provenance: false + sbom: false build-contexts: | - yolean/node:root=docker-image://ghcr.io/yolean/node:root + yolean/node=docker-image://ghcr.io/yolean/node:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push node-vitest latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: to-nonroot/node-vitest tags: | @@ -620,15 +912,23 @@ jobs: ghcr.io/yolean/node-vitest:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-node-vitest-latest + type=gha,scope=buildx-node-vitest + cache-to: type=gha,mode=max,scope=buildx-node-vitest-latest + provenance: false + sbom: false build-contexts: | - yolean/node-vitest:root=docker-image://ghcr.io/yolean/node-vitest:root + yolean/node-vitest=docker-image://ghcr.io/yolean/node-vitest:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push runtime-quarkus-ubuntu root - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: runtime-quarkus-ubuntu tags: | @@ -636,15 +936,23 @@ jobs: ghcr.io/yolean/runtime-quarkus-ubuntu:${{ github.sha }}-root platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-runtime-quarkus-ubuntu-root + type=gha,scope=buildx-runtime-quarkus-ubuntu + cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-ubuntu-root + provenance: false + sbom: false build-contexts: | yolean/docker-base=docker-image://ghcr.io/yolean/docker-base + continue-on-error: false + timeout-minutes: 45 - name: Build and push runtime-quarkus-ubuntu latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: to-nonroot/runtime-quarkus-ubuntu tags: | @@ -652,15 +960,23 @@ jobs: ghcr.io/yolean/runtime-quarkus-ubuntu:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-runtime-quarkus-ubuntu-latest + type=gha,scope=buildx-runtime-quarkus-ubuntu + cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-ubuntu-latest + provenance: false + sbom: false build-contexts: | - yolean/runtime-quarkus-ubuntu:root=docker-image://ghcr.io/yolean/runtime-quarkus-ubuntu:root + yolean/runtime-quarkus-ubuntu=docker-image://ghcr.io/yolean/runtime-quarkus-ubuntu:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push runtime-quarkus-deno root - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: runtime-quarkus-deno tags: | @@ -668,16 +984,24 @@ jobs: ghcr.io/yolean/runtime-quarkus-deno:${{ github.sha }}-root platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-runtime-quarkus-deno-root + type=gha,scope=buildx-runtime-quarkus-deno + cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-deno-root + provenance: false + sbom: false build-contexts: | yolean/runtime-deno=docker-image://ghcr.io/yolean/runtime-deno yolean/runtime-quarkus-ubuntu=docker-image://ghcr.io/yolean/runtime-quarkus-ubuntu + continue-on-error: false + timeout-minutes: 45 - name: Build and push runtime-quarkus-deno latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: to-nonroot/runtime-quarkus-deno tags: | @@ -685,15 +1009,23 @@ jobs: ghcr.io/yolean/runtime-quarkus-deno:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-runtime-quarkus-deno-latest + type=gha,scope=buildx-runtime-quarkus-deno + cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-deno-latest + provenance: false + sbom: false build-contexts: | - yolean/runtime-quarkus-deno:root=docker-image://ghcr.io/yolean/runtime-quarkus-deno:root + yolean/runtime-quarkus-deno=docker-image://ghcr.io/yolean/runtime-quarkus-deno:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push runtime-quarkus-ubuntu-jre root - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: runtime-quarkus-ubuntu-jre tags: | @@ -701,16 +1033,24 @@ jobs: ghcr.io/yolean/runtime-quarkus-ubuntu-jre:${{ github.sha }}-root platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-runtime-quarkus-ubuntu-jre-root + type=gha,scope=buildx-runtime-quarkus-ubuntu-jre + cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-ubuntu-jre-root + provenance: false + sbom: false build-contexts: | - yolean/java:root=docker-image://ghcr.io/yolean/java:root - yolean/runtime-quarkus-ubuntu:root=docker-image://ghcr.io/yolean/runtime-quarkus-ubuntu:root + yolean/java=docker-image://ghcr.io/yolean/java:root + yolean/runtime-quarkus-ubuntu=docker-image://ghcr.io/yolean/runtime-quarkus-ubuntu:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push runtime-quarkus-ubuntu-jre latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: to-nonroot/runtime-quarkus-ubuntu-jre tags: | @@ -718,15 +1058,23 @@ jobs: ghcr.io/yolean/runtime-quarkus-ubuntu-jre:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-runtime-quarkus-ubuntu-jre-latest + type=gha,scope=buildx-runtime-quarkus-ubuntu-jre + cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-ubuntu-jre-latest + provenance: false + sbom: false build-contexts: | - yolean/runtime-quarkus-ubuntu-jre:root=docker-image://ghcr.io/yolean/runtime-quarkus-ubuntu-jre:root + yolean/runtime-quarkus-ubuntu-jre=docker-image://ghcr.io/yolean/runtime-quarkus-ubuntu-jre:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push runtime-quarkus-dev root - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: runtime-quarkus-dev tags: | @@ -734,16 +1082,24 @@ jobs: ghcr.io/yolean/runtime-quarkus-dev:${{ github.sha }}-root platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-runtime-quarkus-dev-root + type=gha,scope=buildx-runtime-quarkus-dev + cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-dev-root + provenance: false + sbom: false build-contexts: | yolean/builder-quarkus=docker-image://ghcr.io/yolean/builder-quarkus - yolean/runtime-quarkus-ubuntu:root=docker-image://ghcr.io/yolean/runtime-quarkus-ubuntu:root + yolean/runtime-quarkus-ubuntu=docker-image://ghcr.io/yolean/runtime-quarkus-ubuntu:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push runtime-quarkus-dev latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: to-nonroot/runtime-quarkus-dev tags: | @@ -751,15 +1107,23 @@ jobs: ghcr.io/yolean/runtime-quarkus-dev:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-runtime-quarkus-dev-latest + type=gha,scope=buildx-runtime-quarkus-dev + cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-dev-latest + provenance: false + sbom: false build-contexts: | - yolean/runtime-quarkus-dev:root=docker-image://ghcr.io/yolean/runtime-quarkus-dev:root + yolean/runtime-quarkus-dev=docker-image://ghcr.io/yolean/runtime-quarkus-dev:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push toil-storage root - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: toil-storage tags: | @@ -767,16 +1131,24 @@ jobs: ghcr.io/yolean/toil-storage:${{ github.sha }}-root platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-toil-storage-root + type=gha,scope=buildx-toil-storage + cache-to: type=gha,mode=max,scope=buildx-toil-storage-root + provenance: false + sbom: false build-contexts: | yolean/toil=docker-image://ghcr.io/yolean/toil yolean/docker-base=docker-image://ghcr.io/yolean/docker-base + continue-on-error: false + timeout-minutes: 45 - name: Build and push toil-storage latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: to-nonroot/toil-storage tags: | @@ -784,15 +1156,23 @@ jobs: ghcr.io/yolean/toil-storage:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-toil-storage-latest + type=gha,scope=buildx-toil-storage + cache-to: type=gha,mode=max,scope=buildx-toil-storage-latest + provenance: false + sbom: false build-contexts: | - yolean/toil-storage:root=docker-image://ghcr.io/yolean/toil-storage:root + yolean/toil-storage=docker-image://ghcr.io/yolean/toil-storage:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push curl-yq root - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: curl-yq tags: | @@ -800,15 +1180,23 @@ jobs: ghcr.io/yolean/curl-yq:${{ github.sha }}-root platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-curl-yq-root + type=gha,scope=buildx-curl-yq + cache-to: type=gha,mode=max,scope=buildx-curl-yq-root + provenance: false + sbom: false build-contexts: | yolean/builder-base=docker-image://ghcr.io/yolean/builder-base + continue-on-error: false + timeout-minutes: 45 - name: Build and push curl-yq latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: to-nonroot/curl-yq tags: | @@ -816,15 +1204,23 @@ jobs: ghcr.io/yolean/curl-yq:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-curl-yq-latest + type=gha,scope=buildx-curl-yq + cache-to: type=gha,mode=max,scope=buildx-curl-yq-latest + provenance: false + sbom: false build-contexts: | - yolean/curl-yq:root=docker-image://ghcr.io/yolean/curl-yq:root + yolean/curl-yq=docker-image://ghcr.io/yolean/curl-yq:root + continue-on-error: false + timeout-minutes: 45 - name: Build and push duckdb root - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: duckdb tags: | @@ -832,16 +1228,24 @@ jobs: ghcr.io/yolean/duckdb:${{ github.sha }}-root platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-duckdb-root + type=gha,scope=buildx-duckdb + cache-to: type=gha,mode=max,scope=buildx-duckdb-root + provenance: false + sbom: false build-contexts: | yolean/builder-base=docker-image://ghcr.io/yolean/builder-base yolean/homedir=docker-image://ghcr.io/yolean/homedir + continue-on-error: false + timeout-minutes: 45 - name: Build and push duckdb latest - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.18.0 env: SOURCE_DATE_EPOCH: 0 + BUILDKIT_PROGRESS: plain + DOCKER_BUILDKIT: 1 with: context: to-nonroot/duckdb tags: | @@ -849,7 +1253,13 @@ jobs: ghcr.io/yolean/duckdb:${{ github.sha }} platforms: linux/amd64,linux/arm64/v8 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=buildx-duckdb-latest + type=gha,scope=buildx-duckdb + cache-to: type=gha,mode=max,scope=buildx-duckdb-latest + provenance: false + sbom: false build-contexts: | - yolean/duckdb:root=docker-image://ghcr.io/yolean/duckdb:root + yolean/duckdb=docker-image://ghcr.io/yolean/duckdb:root + continue-on-error: false + timeout-minutes: 45 diff --git a/BUILD_WORKFLOW_IMPROVEMENTS.md b/BUILD_WORKFLOW_IMPROVEMENTS.md new file mode 100644 index 0000000..cccdf5c --- /dev/null +++ b/BUILD_WORKFLOW_IMPROVEMENTS.md @@ -0,0 +1,72 @@ +# Build Workflow Improvements + +This document outlines the improvements made to the Docker build workflow in this repository. + +## Summary of Changes + +### Updated Action Versions +- `docker/build-push-action`: v5 → v6.18.0 +- `docker/login-action`: v3 → v3.5.0 +- `docker/setup-qemu-action`: v3 → v3.6.0 +- `docker/setup-buildx-action`: v3 → v3.11.1 + +### Enhanced Caching Strategy +- **Scoped Cache Keys**: Each image now uses targeted cache keys (`buildx-{image}-{tag}`) for better cache isolation +- **Multi-tier Cache Lookup**: Images first check their specific cache, then fall back to general image cache +- **Improved Cache Sharing**: Related images can benefit from shared cache layers + +### Build Reliability Improvements +- **Timeouts**: Added 45-minute timeout per build step to prevent hanging builds +- **Build Progress**: Added `BUILDKIT_PROGRESS=plain` for better build visibility +- **Error Handling**: Explicit `continue-on-error: false` to fail fast on issues + +### Enhanced Workflow Features +- **Manual Triggering**: Added `workflow_dispatch` trigger for manual builds +- **Enhanced Permissions**: Added `attestations: write` and `id-token: write` for security features +- **Disabled Provenance/SBOM**: Reduced build overhead by disabling unnecessary features + +### Workflow Structure Preserved +- **Dependency Detection**: Maintained existing dependency parsing and build-contexts +- **Build Order**: Preserved sequential build order to respect interdependencies +- **Image Variants**: Continued support for both `root` and `latest` (nonroot) variants + +## Benefits + +1. **Faster Builds**: Better cache hit rates reduce build times +2. **More Reliable**: Improved error handling and timeouts prevent stuck builds +3. **Better Observability**: Enhanced build progress and logging +4. **Modern Actions**: Latest action versions with bug fixes and performance improvements +5. **Maintainable**: Preserved existing generation logic in `test.sh` + +## Cache Strategy Details + +### Cache Scoping +Each build now uses a two-tier cache lookup: +```yaml +cache-from: | + type=gha,scope=buildx-{image}-{tag} # Specific cache + type=gha,scope=buildx-{image} # Fallback cache +cache-to: type=gha,mode=max,scope=buildx-{image}-{tag} +``` + +This allows: +- Fast rebuilds when only specific image changes +- Cache sharing between root/latest variants of same image +- Reduced cache conflicts between different images + +### Environment Variables +Added build optimization environment variables: +- `SOURCE_DATE_EPOCH: 0` - Reproducible builds +- `BUILDKIT_PROGRESS: plain` - Better build output +- `DOCKER_BUILDKIT: 1` - Ensure BuildKit is used + +## Future Considerations + +Potential additional improvements that weren't implemented to maintain minimal changes: +- **Parallel Builds**: Could build independent images in parallel jobs +- **Conditional Builds**: Skip builds when Dockerfiles haven't changed +- **Matrix Builds**: Use build matrix for better parallelization +- **Security Scanning**: Integrate security scanning into the workflow +- **Build Summaries**: Add job summaries with build metrics + +The current improvements focus on reliability, caching efficiency, and using latest stable action versions while preserving all existing functionality. \ No newline at end of file diff --git a/test.sh b/test.sh index 15a5ca7..eb9c7a4 100755 --- a/test.sh +++ b/test.sh @@ -71,12 +71,20 @@ function base_action { local TAG=$3 local TAGSUFFIX="" [ "$TAG" = "latest" ] || local TAGSUFFIX="-$TAG" + # Create cache key that includes context for better cache scoping + local CACHE_KEY_PREFIX="buildx-$NAME-$TAG" + + # Get dependencies for build-contexts + local DEPENDENCIES="$((grep -e 'FROM --platform=$TARGETPLATFORM yolean/' -e 'FROM --platform=$BUILDPLATFORM yolean/' $CONTEXT/Dockerfile || true) | cut -d' ' -f3)" + cat <> $ACTIONS - add_dependencies "$CONTEXT" >> $ACTIONS done for CONTEXT in $MULTIARCH_TONONROOT; do @@ -108,9 +127,7 @@ for CONTEXT in $MULTIARCH_TONONROOT; do echo "FROM --platform=\$TARGETPLATFORM yolean/$CONTEXT:root" > to-nonroot/$CONTEXT/Dockerfile cat nonroot-footer.Dockerfile >> to-nonroot/$CONTEXT/Dockerfile base_action "$CONTEXT" "$CONTEXT" root >> $ACTIONS - add_dependencies "$CONTEXT" >> $ACTIONS base_action "to-nonroot/$CONTEXT" "$CONTEXT" latest >> $ACTIONS - add_dependencies "to-nonroot/$CONTEXT" >> $ACTIONS done cp $ACTIONS $CURRENT From a4cf87785a4f27bfb080b847673bb39affd08ae3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 5 Sep 2025 06:08:57 +0000 Subject: [PATCH 04/10] Re-enable provenance and SBOM for Docker images Co-authored-by: solsson <144945+solsson@users.noreply.github.com> --- .github/workflows/images.yaml | 100 ---------------------------------- test.sh | 2 - 2 files changed, 102 deletions(-) diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index 2d28d0d..a7b093b 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -92,8 +92,6 @@ jobs: type=gha,scope=buildx-docker-base-latest type=gha,scope=buildx-docker-base cache-to: type=gha,mode=max,scope=buildx-docker-base-latest - provenance: false - sbom: false continue-on-error: false timeout-minutes: 45 - @@ -114,8 +112,6 @@ jobs: type=gha,scope=buildx-builder-base-latest type=gha,scope=buildx-builder-base cache-to: type=gha,mode=max,scope=buildx-builder-base-latest - provenance: false - sbom: false continue-on-error: false timeout-minutes: 45 - @@ -136,8 +132,6 @@ jobs: type=gha,scope=buildx-builder-base-gcc-latest type=gha,scope=buildx-builder-base-gcc cache-to: type=gha,mode=max,scope=buildx-builder-base-gcc-latest - provenance: false - sbom: false build-contexts: | yolean/builder-base=docker-image://ghcr.io/yolean/builder-base continue-on-error: false @@ -160,8 +154,6 @@ jobs: type=gha,scope=buildx-builder-base-gcloud-latest type=gha,scope=buildx-builder-base-gcloud cache-to: type=gha,mode=max,scope=buildx-builder-base-gcloud-latest - provenance: false - sbom: false build-contexts: | yolean/builder-base=docker-image://ghcr.io/yolean/builder-base continue-on-error: false @@ -184,8 +176,6 @@ jobs: type=gha,scope=buildx-builder-tooling-latest type=gha,scope=buildx-builder-tooling cache-to: type=gha,mode=max,scope=buildx-builder-tooling-latest - provenance: false - sbom: false build-contexts: | yolean/builder-base-gcc=docker-image://ghcr.io/yolean/builder-base-gcc continue-on-error: false @@ -208,8 +198,6 @@ jobs: type=gha,scope=buildx-builder-node-latest type=gha,scope=buildx-builder-node cache-to: type=gha,mode=max,scope=buildx-builder-node-latest - provenance: false - sbom: false continue-on-error: false timeout-minutes: 45 - @@ -230,8 +218,6 @@ jobs: type=gha,scope=buildx-builder-quarkus-latest type=gha,scope=buildx-builder-quarkus cache-to: type=gha,mode=max,scope=buildx-builder-quarkus-latest - provenance: false - sbom: false build-contexts: | yolean/builder-base=docker-image://ghcr.io/yolean/builder-base yolean/builder-base-gcc=docker-image://ghcr.io/yolean/builder-base-gcc @@ -255,8 +241,6 @@ jobs: type=gha,scope=buildx-builder-evidence-latest type=gha,scope=buildx-builder-evidence cache-to: type=gha,mode=max,scope=buildx-builder-evidence-latest - provenance: false - sbom: false build-contexts: | yolean/builder-base-gcc=docker-image://ghcr.io/yolean/builder-base-gcc yolean/builder-base-gcloud=docker-image://ghcr.io/yolean/builder-base-gcloud @@ -280,8 +264,6 @@ jobs: type=gha,scope=buildx-git-init-latest type=gha,scope=buildx-git-init cache-to: type=gha,mode=max,scope=buildx-git-init-latest - provenance: false - sbom: false build-contexts: | yolean/builder-base=docker-image://ghcr.io/yolean/builder-base continue-on-error: false @@ -304,8 +286,6 @@ jobs: type=gha,scope=buildx-toil-latest type=gha,scope=buildx-toil cache-to: type=gha,mode=max,scope=buildx-toil-latest - provenance: false - sbom: false build-contexts: | yolean/builder-base=docker-image://ghcr.io/yolean/builder-base yolean/builder-base=docker-image://ghcr.io/yolean/builder-base @@ -329,8 +309,6 @@ jobs: type=gha,scope=buildx-toil-network-latest type=gha,scope=buildx-toil-network cache-to: type=gha,mode=max,scope=buildx-toil-network-latest - provenance: false - sbom: false build-contexts: | yolean/toil=docker-image://ghcr.io/yolean/toil continue-on-error: false @@ -353,8 +331,6 @@ jobs: type=gha,scope=buildx-node-distroless-latest type=gha,scope=buildx-node-distroless cache-to: type=gha,mode=max,scope=buildx-node-distroless-latest - provenance: false - sbom: false continue-on-error: false timeout-minutes: 45 - @@ -375,8 +351,6 @@ jobs: type=gha,scope=buildx-headless-chrome-latest type=gha,scope=buildx-headless-chrome cache-to: type=gha,mode=max,scope=buildx-headless-chrome-latest - provenance: false - sbom: false build-contexts: | yolean/docker-base=docker-image://ghcr.io/yolean/docker-base continue-on-error: false @@ -399,8 +373,6 @@ jobs: type=gha,scope=buildx-git-http-readonly-latest type=gha,scope=buildx-git-http-readonly cache-to: type=gha,mode=max,scope=buildx-git-http-readonly-latest - provenance: false - sbom: false continue-on-error: false timeout-minutes: 45 - @@ -421,8 +393,6 @@ jobs: type=gha,scope=buildx-runtime-quarkus-latest type=gha,scope=buildx-runtime-quarkus cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-latest - provenance: false - sbom: false continue-on-error: false timeout-minutes: 45 - @@ -443,8 +413,6 @@ jobs: type=gha,scope=buildx-runtime-deno-latest type=gha,scope=buildx-runtime-deno cache-to: type=gha,mode=max,scope=buildx-runtime-deno-latest - provenance: false - sbom: false continue-on-error: false timeout-minutes: 45 - @@ -465,8 +433,6 @@ jobs: type=gha,scope=buildx-homedir-root type=gha,scope=buildx-homedir cache-to: type=gha,mode=max,scope=buildx-homedir-root - provenance: false - sbom: false build-contexts: | yolean/docker-base=docker-image://ghcr.io/yolean/docker-base continue-on-error: false @@ -489,8 +455,6 @@ jobs: type=gha,scope=buildx-homedir-latest type=gha,scope=buildx-homedir cache-to: type=gha,mode=max,scope=buildx-homedir-latest - provenance: false - sbom: false build-contexts: | yolean/homedir=docker-image://ghcr.io/yolean/homedir:root continue-on-error: false @@ -513,8 +477,6 @@ jobs: type=gha,scope=buildx-java-root type=gha,scope=buildx-java cache-to: type=gha,mode=max,scope=buildx-java-root - provenance: false - sbom: false continue-on-error: false timeout-minutes: 45 - @@ -535,8 +497,6 @@ jobs: type=gha,scope=buildx-java-latest type=gha,scope=buildx-java cache-to: type=gha,mode=max,scope=buildx-java-latest - provenance: false - sbom: false build-contexts: | yolean/java=docker-image://ghcr.io/yolean/java:root continue-on-error: false @@ -559,8 +519,6 @@ jobs: type=gha,scope=buildx-node-root type=gha,scope=buildx-node cache-to: type=gha,mode=max,scope=buildx-node-root - provenance: false - sbom: false continue-on-error: false timeout-minutes: 45 - @@ -581,8 +539,6 @@ jobs: type=gha,scope=buildx-node-latest type=gha,scope=buildx-node cache-to: type=gha,mode=max,scope=buildx-node-latest - provenance: false - sbom: false build-contexts: | yolean/node=docker-image://ghcr.io/yolean/node:root continue-on-error: false @@ -605,8 +561,6 @@ jobs: type=gha,scope=buildx-node-kafka-root type=gha,scope=buildx-node-kafka cache-to: type=gha,mode=max,scope=buildx-node-kafka-root - provenance: false - sbom: false build-contexts: | yolean/node=docker-image://ghcr.io/yolean/node:root continue-on-error: false @@ -629,8 +583,6 @@ jobs: type=gha,scope=buildx-node-kafka-latest type=gha,scope=buildx-node-kafka cache-to: type=gha,mode=max,scope=buildx-node-kafka-latest - provenance: false - sbom: false build-contexts: | yolean/node-kafka=docker-image://ghcr.io/yolean/node-kafka:root continue-on-error: false @@ -653,8 +605,6 @@ jobs: type=gha,scope=buildx-node-kafka-cache-root type=gha,scope=buildx-node-kafka-cache cache-to: type=gha,mode=max,scope=buildx-node-kafka-cache-root - provenance: false - sbom: false build-contexts: | yolean/node-kafka=docker-image://ghcr.io/yolean/node-kafka:root continue-on-error: false @@ -677,8 +627,6 @@ jobs: type=gha,scope=buildx-node-kafka-cache-latest type=gha,scope=buildx-node-kafka-cache cache-to: type=gha,mode=max,scope=buildx-node-kafka-cache-latest - provenance: false - sbom: false build-contexts: | yolean/node-kafka-cache=docker-image://ghcr.io/yolean/node-kafka-cache:root continue-on-error: false @@ -701,8 +649,6 @@ jobs: type=gha,scope=buildx-node-kafka-sqlite-root type=gha,scope=buildx-node-kafka-sqlite cache-to: type=gha,mode=max,scope=buildx-node-kafka-sqlite-root - provenance: false - sbom: false build-contexts: | yolean/node-kafka=docker-image://ghcr.io/yolean/node-kafka:root continue-on-error: false @@ -725,8 +671,6 @@ jobs: type=gha,scope=buildx-node-kafka-sqlite-latest type=gha,scope=buildx-node-kafka-sqlite cache-to: type=gha,mode=max,scope=buildx-node-kafka-sqlite-latest - provenance: false - sbom: false build-contexts: | yolean/node-kafka-sqlite=docker-image://ghcr.io/yolean/node-kafka-sqlite:root continue-on-error: false @@ -749,8 +693,6 @@ jobs: type=gha,scope=buildx-node-watchexec-root type=gha,scope=buildx-node-watchexec cache-to: type=gha,mode=max,scope=buildx-node-watchexec-root - provenance: false - sbom: false continue-on-error: false timeout-minutes: 45 - @@ -771,8 +713,6 @@ jobs: type=gha,scope=buildx-node-watchexec-latest type=gha,scope=buildx-node-watchexec cache-to: type=gha,mode=max,scope=buildx-node-watchexec-latest - provenance: false - sbom: false build-contexts: | yolean/node-watchexec=docker-image://ghcr.io/yolean/node-watchexec:root continue-on-error: false @@ -795,8 +735,6 @@ jobs: type=gha,scope=buildx-node-kafka-watch-root type=gha,scope=buildx-node-kafka-watch cache-to: type=gha,mode=max,scope=buildx-node-kafka-watch-root - provenance: false - sbom: false build-contexts: | yolean/node-watchexec=docker-image://ghcr.io/yolean/node-watchexec:root yolean/node-kafka=docker-image://ghcr.io/yolean/node-kafka:root @@ -820,8 +758,6 @@ jobs: type=gha,scope=buildx-node-kafka-watch-latest type=gha,scope=buildx-node-kafka-watch cache-to: type=gha,mode=max,scope=buildx-node-kafka-watch-latest - provenance: false - sbom: false build-contexts: | yolean/node-kafka-watch=docker-image://ghcr.io/yolean/node-kafka-watch:root continue-on-error: false @@ -844,8 +780,6 @@ jobs: type=gha,scope=buildx-node-gcloud-root type=gha,scope=buildx-node-gcloud cache-to: type=gha,mode=max,scope=buildx-node-gcloud-root - provenance: false - sbom: false build-contexts: | yolean/node=docker-image://ghcr.io/yolean/node:root continue-on-error: false @@ -868,8 +802,6 @@ jobs: type=gha,scope=buildx-node-gcloud-latest type=gha,scope=buildx-node-gcloud cache-to: type=gha,mode=max,scope=buildx-node-gcloud-latest - provenance: false - sbom: false build-contexts: | yolean/node-gcloud=docker-image://ghcr.io/yolean/node-gcloud:root continue-on-error: false @@ -892,8 +824,6 @@ jobs: type=gha,scope=buildx-node-vitest-root type=gha,scope=buildx-node-vitest cache-to: type=gha,mode=max,scope=buildx-node-vitest-root - provenance: false - sbom: false build-contexts: | yolean/node=docker-image://ghcr.io/yolean/node:root continue-on-error: false @@ -916,8 +846,6 @@ jobs: type=gha,scope=buildx-node-vitest-latest type=gha,scope=buildx-node-vitest cache-to: type=gha,mode=max,scope=buildx-node-vitest-latest - provenance: false - sbom: false build-contexts: | yolean/node-vitest=docker-image://ghcr.io/yolean/node-vitest:root continue-on-error: false @@ -940,8 +868,6 @@ jobs: type=gha,scope=buildx-runtime-quarkus-ubuntu-root type=gha,scope=buildx-runtime-quarkus-ubuntu cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-ubuntu-root - provenance: false - sbom: false build-contexts: | yolean/docker-base=docker-image://ghcr.io/yolean/docker-base continue-on-error: false @@ -964,8 +890,6 @@ jobs: type=gha,scope=buildx-runtime-quarkus-ubuntu-latest type=gha,scope=buildx-runtime-quarkus-ubuntu cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-ubuntu-latest - provenance: false - sbom: false build-contexts: | yolean/runtime-quarkus-ubuntu=docker-image://ghcr.io/yolean/runtime-quarkus-ubuntu:root continue-on-error: false @@ -988,8 +912,6 @@ jobs: type=gha,scope=buildx-runtime-quarkus-deno-root type=gha,scope=buildx-runtime-quarkus-deno cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-deno-root - provenance: false - sbom: false build-contexts: | yolean/runtime-deno=docker-image://ghcr.io/yolean/runtime-deno yolean/runtime-quarkus-ubuntu=docker-image://ghcr.io/yolean/runtime-quarkus-ubuntu @@ -1013,8 +935,6 @@ jobs: type=gha,scope=buildx-runtime-quarkus-deno-latest type=gha,scope=buildx-runtime-quarkus-deno cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-deno-latest - provenance: false - sbom: false build-contexts: | yolean/runtime-quarkus-deno=docker-image://ghcr.io/yolean/runtime-quarkus-deno:root continue-on-error: false @@ -1037,8 +957,6 @@ jobs: type=gha,scope=buildx-runtime-quarkus-ubuntu-jre-root type=gha,scope=buildx-runtime-quarkus-ubuntu-jre cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-ubuntu-jre-root - provenance: false - sbom: false build-contexts: | yolean/java=docker-image://ghcr.io/yolean/java:root yolean/runtime-quarkus-ubuntu=docker-image://ghcr.io/yolean/runtime-quarkus-ubuntu:root @@ -1062,8 +980,6 @@ jobs: type=gha,scope=buildx-runtime-quarkus-ubuntu-jre-latest type=gha,scope=buildx-runtime-quarkus-ubuntu-jre cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-ubuntu-jre-latest - provenance: false - sbom: false build-contexts: | yolean/runtime-quarkus-ubuntu-jre=docker-image://ghcr.io/yolean/runtime-quarkus-ubuntu-jre:root continue-on-error: false @@ -1086,8 +1002,6 @@ jobs: type=gha,scope=buildx-runtime-quarkus-dev-root type=gha,scope=buildx-runtime-quarkus-dev cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-dev-root - provenance: false - sbom: false build-contexts: | yolean/builder-quarkus=docker-image://ghcr.io/yolean/builder-quarkus yolean/runtime-quarkus-ubuntu=docker-image://ghcr.io/yolean/runtime-quarkus-ubuntu:root @@ -1111,8 +1025,6 @@ jobs: type=gha,scope=buildx-runtime-quarkus-dev-latest type=gha,scope=buildx-runtime-quarkus-dev cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-dev-latest - provenance: false - sbom: false build-contexts: | yolean/runtime-quarkus-dev=docker-image://ghcr.io/yolean/runtime-quarkus-dev:root continue-on-error: false @@ -1135,8 +1047,6 @@ jobs: type=gha,scope=buildx-toil-storage-root type=gha,scope=buildx-toil-storage cache-to: type=gha,mode=max,scope=buildx-toil-storage-root - provenance: false - sbom: false build-contexts: | yolean/toil=docker-image://ghcr.io/yolean/toil yolean/docker-base=docker-image://ghcr.io/yolean/docker-base @@ -1160,8 +1070,6 @@ jobs: type=gha,scope=buildx-toil-storage-latest type=gha,scope=buildx-toil-storage cache-to: type=gha,mode=max,scope=buildx-toil-storage-latest - provenance: false - sbom: false build-contexts: | yolean/toil-storage=docker-image://ghcr.io/yolean/toil-storage:root continue-on-error: false @@ -1184,8 +1092,6 @@ jobs: type=gha,scope=buildx-curl-yq-root type=gha,scope=buildx-curl-yq cache-to: type=gha,mode=max,scope=buildx-curl-yq-root - provenance: false - sbom: false build-contexts: | yolean/builder-base=docker-image://ghcr.io/yolean/builder-base continue-on-error: false @@ -1208,8 +1114,6 @@ jobs: type=gha,scope=buildx-curl-yq-latest type=gha,scope=buildx-curl-yq cache-to: type=gha,mode=max,scope=buildx-curl-yq-latest - provenance: false - sbom: false build-contexts: | yolean/curl-yq=docker-image://ghcr.io/yolean/curl-yq:root continue-on-error: false @@ -1232,8 +1136,6 @@ jobs: type=gha,scope=buildx-duckdb-root type=gha,scope=buildx-duckdb cache-to: type=gha,mode=max,scope=buildx-duckdb-root - provenance: false - sbom: false build-contexts: | yolean/builder-base=docker-image://ghcr.io/yolean/builder-base yolean/homedir=docker-image://ghcr.io/yolean/homedir @@ -1257,8 +1159,6 @@ jobs: type=gha,scope=buildx-duckdb-latest type=gha,scope=buildx-duckdb cache-to: type=gha,mode=max,scope=buildx-duckdb-latest - provenance: false - sbom: false build-contexts: | yolean/duckdb=docker-image://ghcr.io/yolean/duckdb:root continue-on-error: false diff --git a/test.sh b/test.sh index eb9c7a4..fb13f48 100755 --- a/test.sh +++ b/test.sh @@ -96,8 +96,6 @@ function base_action { type=gha,scope=$CACHE_KEY_PREFIX type=gha,scope=buildx-$NAME cache-to: type=gha,mode=max,scope=$CACHE_KEY_PREFIX - provenance: false - sbom: false EOF # Add build-contexts if there are dependencies From 6a9c995ebf34003e8abd7b219255884ddce078d2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 5 Sep 2025 06:21:48 +0000 Subject: [PATCH 05/10] Enable workflow for PRs with "push" label - Add pull_request trigger for labeled, synchronize, and opened events - Add conditional check to only run workflow for pushes to main, workflow_dispatch, or PRs with "push" label - Maintains existing functionality while enabling selective PR builds Co-authored-by: solsson <144945+solsson@users.noreply.github.com> --- .github/workflows/images.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index a7b093b..c433c77 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -4,6 +4,8 @@ on: push: branches: - main + pull_request: + types: [labeled, synchronize, opened] workflow_dispatch: inputs: force_rebuild: @@ -16,6 +18,7 @@ jobs: publish: name: Publish runs-on: ubuntu-latest + if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'push')) permissions: packages: write contents: read From 0684bd2c88817839d82183db2e1fb3eae921bb66 Mon Sep 17 00:00:00 2001 From: Staffan Olsson Date: Fri, 5 Sep 2025 19:28:52 +0200 Subject: [PATCH 06/10] latest ystack-runner fixes issue with apt-get update by removing the helm package source for the Yolean/ystack#63 workaround after installation --- builder-base/Dockerfile | 2 +- docker-base/Dockerfile | 2 +- node/Dockerfile | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/builder-base/Dockerfile b/builder-base/Dockerfile index e66ebad..f10580d 100644 --- a/builder-base/Dockerfile +++ b/builder-base/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=$TARGETPLATFORM ghcr.io/yolean/ystack-runner:c99c1feb788de3a36cde3d1991930a0978584c0f@sha256:40328497d1941a7b3ee2176cf750269142d430b97a5360189c7e9a20cc875c66 \ +FROM --platform=$TARGETPLATFORM ghcr.io/yolean/ystack-runner:190c416a1906a5641127c114546201be8cb6a6c4@sha256:e3b988e7c1e332b74d8b9b2f9638b5a67e2b59b69b9febf30c535b6ade60eb74 \ as base FROM base as nonroot diff --git a/docker-base/Dockerfile b/docker-base/Dockerfile index 4fa441a..43872ea 100644 --- a/docker-base/Dockerfile +++ b/docker-base/Dockerfile @@ -1 +1 @@ -FROM --platform=$TARGETPLATFORM ubuntu:24.04@sha256:440dcf6a5640b2ae5c77724e68787a906afb8ddee98bf86db94eea8528c2c076 +FROM --platform=$TARGETPLATFORM ubuntu:24.04@sha256:9cbed754112939e914291337b5e554b07ad7c392491dba6daf25eef1332a22e8 diff --git a/node/Dockerfile b/node/Dockerfile index 7ff3d0a..64f4ef7 100644 --- a/node/Dockerfile +++ b/node/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=$TARGETPLATFORM node:22.17.0-bookworm-slim@sha256:b04ce4ae4e95b522112c2e5c52f781471a5cbc3b594527bcddedee9bc48c03a0 +FROM --platform=$TARGETPLATFORM node:22.19.0-trixie-slim@sha256:ba533b824f504e19137d3c961f8f6ef5278b02d8bfa7010eabb1b836d3125ce4 RUN runtimeDeps='procps git curl ca-certificates' \ && set -ex \ From a240075fe8f58647fe099b935344810700c5019f Mon Sep 17 00:00:00 2001 From: Staffan Olsson Date: Sat, 6 Sep 2025 16:22:48 +0200 Subject: [PATCH 07/10] removes copilot output that belongs in the PR description --- BUILD_WORKFLOW_IMPROVEMENTS.md | 72 ---------------------------------- 1 file changed, 72 deletions(-) delete mode 100644 BUILD_WORKFLOW_IMPROVEMENTS.md diff --git a/BUILD_WORKFLOW_IMPROVEMENTS.md b/BUILD_WORKFLOW_IMPROVEMENTS.md deleted file mode 100644 index cccdf5c..0000000 --- a/BUILD_WORKFLOW_IMPROVEMENTS.md +++ /dev/null @@ -1,72 +0,0 @@ -# Build Workflow Improvements - -This document outlines the improvements made to the Docker build workflow in this repository. - -## Summary of Changes - -### Updated Action Versions -- `docker/build-push-action`: v5 → v6.18.0 -- `docker/login-action`: v3 → v3.5.0 -- `docker/setup-qemu-action`: v3 → v3.6.0 -- `docker/setup-buildx-action`: v3 → v3.11.1 - -### Enhanced Caching Strategy -- **Scoped Cache Keys**: Each image now uses targeted cache keys (`buildx-{image}-{tag}`) for better cache isolation -- **Multi-tier Cache Lookup**: Images first check their specific cache, then fall back to general image cache -- **Improved Cache Sharing**: Related images can benefit from shared cache layers - -### Build Reliability Improvements -- **Timeouts**: Added 45-minute timeout per build step to prevent hanging builds -- **Build Progress**: Added `BUILDKIT_PROGRESS=plain` for better build visibility -- **Error Handling**: Explicit `continue-on-error: false` to fail fast on issues - -### Enhanced Workflow Features -- **Manual Triggering**: Added `workflow_dispatch` trigger for manual builds -- **Enhanced Permissions**: Added `attestations: write` and `id-token: write` for security features -- **Disabled Provenance/SBOM**: Reduced build overhead by disabling unnecessary features - -### Workflow Structure Preserved -- **Dependency Detection**: Maintained existing dependency parsing and build-contexts -- **Build Order**: Preserved sequential build order to respect interdependencies -- **Image Variants**: Continued support for both `root` and `latest` (nonroot) variants - -## Benefits - -1. **Faster Builds**: Better cache hit rates reduce build times -2. **More Reliable**: Improved error handling and timeouts prevent stuck builds -3. **Better Observability**: Enhanced build progress and logging -4. **Modern Actions**: Latest action versions with bug fixes and performance improvements -5. **Maintainable**: Preserved existing generation logic in `test.sh` - -## Cache Strategy Details - -### Cache Scoping -Each build now uses a two-tier cache lookup: -```yaml -cache-from: | - type=gha,scope=buildx-{image}-{tag} # Specific cache - type=gha,scope=buildx-{image} # Fallback cache -cache-to: type=gha,mode=max,scope=buildx-{image}-{tag} -``` - -This allows: -- Fast rebuilds when only specific image changes -- Cache sharing between root/latest variants of same image -- Reduced cache conflicts between different images - -### Environment Variables -Added build optimization environment variables: -- `SOURCE_DATE_EPOCH: 0` - Reproducible builds -- `BUILDKIT_PROGRESS: plain` - Better build output -- `DOCKER_BUILDKIT: 1` - Ensure BuildKit is used - -## Future Considerations - -Potential additional improvements that weren't implemented to maintain minimal changes: -- **Parallel Builds**: Could build independent images in parallel jobs -- **Conditional Builds**: Skip builds when Dockerfiles haven't changed -- **Matrix Builds**: Use build matrix for better parallelization -- **Security Scanning**: Integrate security scanning into the workflow -- **Build Summaries**: Add job summaries with build metrics - -The current improvements focus on reliability, caching efficiency, and using latest stable action versions while preserving all existing functionality. \ No newline at end of file From 2b211dad1a12af679f45b03e07c5a08497ab9605 Mon Sep 17 00:00:00 2001 From: Staffan Olsson Date: Sun, 7 Sep 2025 15:13:33 +0200 Subject: [PATCH 08/10] reintroduces the arch exception from main --- .github/workflows/images.yaml | 2 +- test.sh | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index c433c77..5991075 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -348,7 +348,7 @@ jobs: tags: | ghcr.io/yolean/headless-chrome:latest ghcr.io/yolean/headless-chrome:${{ github.sha }} - platforms: linux/amd64,linux/arm64/v8 + platforms: linux/amd64 push: true cache-from: | type=gha,scope=buildx-headless-chrome-latest diff --git a/test.sh b/test.sh index fb13f48..5c34a78 100755 --- a/test.sh +++ b/test.sh @@ -60,6 +60,9 @@ runtime-quarkus-deno runtime-deno " +# Images that are only buildable on amd64 +SINGLE_ARCH_AMD64="headless-chrome" + BEGIN=" ### build steps below are generated ###" CURRENT=.github/workflows/images.yaml ACTIONS=$(mktemp) @@ -77,6 +80,15 @@ function base_action { # Get dependencies for build-contexts local DEPENDENCIES="$((grep -e 'FROM --platform=$TARGETPLATFORM yolean/' -e 'FROM --platform=$BUILDPLATFORM yolean/' $CONTEXT/Dockerfile || true) | cut -d' ' -f3)" + # Determine platforms (override if in SINGLE_ARCH_AMD64) + local PLATFORMS="linux/amd64,linux/arm64/v8" + for ONLY_AMD64 in $SINGLE_ARCH_AMD64; do + if [ "$NAME" = "$ONLY_AMD64" ]; then + PLATFORMS="linux/amd64" + break + fi + done + cat < Date: Sun, 7 Sep 2025 16:00:22 +0200 Subject: [PATCH 09/10] to-nonroot builds failed on trying to pull from docker.io --- .github/workflows/images.yaml | 54 +++++++++++++++++------------------ test.sh | 4 +-- 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/.github/workflows/images.yaml b/.github/workflows/images.yaml index 5991075..c092001 100644 --- a/.github/workflows/images.yaml +++ b/.github/workflows/images.yaml @@ -459,7 +459,7 @@ jobs: type=gha,scope=buildx-homedir cache-to: type=gha,mode=max,scope=buildx-homedir-latest build-contexts: | - yolean/homedir=docker-image://ghcr.io/yolean/homedir:root + yolean/homedir:root=docker-image://ghcr.io/yolean/homedir:root continue-on-error: false timeout-minutes: 45 - @@ -501,7 +501,7 @@ jobs: type=gha,scope=buildx-java cache-to: type=gha,mode=max,scope=buildx-java-latest build-contexts: | - yolean/java=docker-image://ghcr.io/yolean/java:root + yolean/java:root=docker-image://ghcr.io/yolean/java:root continue-on-error: false timeout-minutes: 45 - @@ -543,7 +543,7 @@ jobs: type=gha,scope=buildx-node cache-to: type=gha,mode=max,scope=buildx-node-latest build-contexts: | - yolean/node=docker-image://ghcr.io/yolean/node:root + yolean/node:root=docker-image://ghcr.io/yolean/node:root continue-on-error: false timeout-minutes: 45 - @@ -565,7 +565,7 @@ jobs: type=gha,scope=buildx-node-kafka cache-to: type=gha,mode=max,scope=buildx-node-kafka-root build-contexts: | - yolean/node=docker-image://ghcr.io/yolean/node:root + yolean/node:root=docker-image://ghcr.io/yolean/node:root continue-on-error: false timeout-minutes: 45 - @@ -587,7 +587,7 @@ jobs: type=gha,scope=buildx-node-kafka cache-to: type=gha,mode=max,scope=buildx-node-kafka-latest build-contexts: | - yolean/node-kafka=docker-image://ghcr.io/yolean/node-kafka:root + yolean/node-kafka:root=docker-image://ghcr.io/yolean/node-kafka:root continue-on-error: false timeout-minutes: 45 - @@ -609,7 +609,7 @@ jobs: type=gha,scope=buildx-node-kafka-cache cache-to: type=gha,mode=max,scope=buildx-node-kafka-cache-root build-contexts: | - yolean/node-kafka=docker-image://ghcr.io/yolean/node-kafka:root + yolean/node-kafka:root=docker-image://ghcr.io/yolean/node-kafka:root continue-on-error: false timeout-minutes: 45 - @@ -631,7 +631,7 @@ jobs: type=gha,scope=buildx-node-kafka-cache cache-to: type=gha,mode=max,scope=buildx-node-kafka-cache-latest build-contexts: | - yolean/node-kafka-cache=docker-image://ghcr.io/yolean/node-kafka-cache:root + yolean/node-kafka-cache:root=docker-image://ghcr.io/yolean/node-kafka-cache:root continue-on-error: false timeout-minutes: 45 - @@ -653,7 +653,7 @@ jobs: type=gha,scope=buildx-node-kafka-sqlite cache-to: type=gha,mode=max,scope=buildx-node-kafka-sqlite-root build-contexts: | - yolean/node-kafka=docker-image://ghcr.io/yolean/node-kafka:root + yolean/node-kafka:root=docker-image://ghcr.io/yolean/node-kafka:root continue-on-error: false timeout-minutes: 45 - @@ -675,7 +675,7 @@ jobs: type=gha,scope=buildx-node-kafka-sqlite cache-to: type=gha,mode=max,scope=buildx-node-kafka-sqlite-latest build-contexts: | - yolean/node-kafka-sqlite=docker-image://ghcr.io/yolean/node-kafka-sqlite:root + yolean/node-kafka-sqlite:root=docker-image://ghcr.io/yolean/node-kafka-sqlite:root continue-on-error: false timeout-minutes: 45 - @@ -717,7 +717,7 @@ jobs: type=gha,scope=buildx-node-watchexec cache-to: type=gha,mode=max,scope=buildx-node-watchexec-latest build-contexts: | - yolean/node-watchexec=docker-image://ghcr.io/yolean/node-watchexec:root + yolean/node-watchexec:root=docker-image://ghcr.io/yolean/node-watchexec:root continue-on-error: false timeout-minutes: 45 - @@ -739,8 +739,8 @@ jobs: type=gha,scope=buildx-node-kafka-watch cache-to: type=gha,mode=max,scope=buildx-node-kafka-watch-root build-contexts: | - yolean/node-watchexec=docker-image://ghcr.io/yolean/node-watchexec:root - yolean/node-kafka=docker-image://ghcr.io/yolean/node-kafka:root + yolean/node-watchexec:root=docker-image://ghcr.io/yolean/node-watchexec:root + yolean/node-kafka:root=docker-image://ghcr.io/yolean/node-kafka:root continue-on-error: false timeout-minutes: 45 - @@ -762,7 +762,7 @@ jobs: type=gha,scope=buildx-node-kafka-watch cache-to: type=gha,mode=max,scope=buildx-node-kafka-watch-latest build-contexts: | - yolean/node-kafka-watch=docker-image://ghcr.io/yolean/node-kafka-watch:root + yolean/node-kafka-watch:root=docker-image://ghcr.io/yolean/node-kafka-watch:root continue-on-error: false timeout-minutes: 45 - @@ -784,7 +784,7 @@ jobs: type=gha,scope=buildx-node-gcloud cache-to: type=gha,mode=max,scope=buildx-node-gcloud-root build-contexts: | - yolean/node=docker-image://ghcr.io/yolean/node:root + yolean/node:root=docker-image://ghcr.io/yolean/node:root continue-on-error: false timeout-minutes: 45 - @@ -806,7 +806,7 @@ jobs: type=gha,scope=buildx-node-gcloud cache-to: type=gha,mode=max,scope=buildx-node-gcloud-latest build-contexts: | - yolean/node-gcloud=docker-image://ghcr.io/yolean/node-gcloud:root + yolean/node-gcloud:root=docker-image://ghcr.io/yolean/node-gcloud:root continue-on-error: false timeout-minutes: 45 - @@ -828,7 +828,7 @@ jobs: type=gha,scope=buildx-node-vitest cache-to: type=gha,mode=max,scope=buildx-node-vitest-root build-contexts: | - yolean/node=docker-image://ghcr.io/yolean/node:root + yolean/node:root=docker-image://ghcr.io/yolean/node:root continue-on-error: false timeout-minutes: 45 - @@ -850,7 +850,7 @@ jobs: type=gha,scope=buildx-node-vitest cache-to: type=gha,mode=max,scope=buildx-node-vitest-latest build-contexts: | - yolean/node-vitest=docker-image://ghcr.io/yolean/node-vitest:root + yolean/node-vitest:root=docker-image://ghcr.io/yolean/node-vitest:root continue-on-error: false timeout-minutes: 45 - @@ -894,7 +894,7 @@ jobs: type=gha,scope=buildx-runtime-quarkus-ubuntu cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-ubuntu-latest build-contexts: | - yolean/runtime-quarkus-ubuntu=docker-image://ghcr.io/yolean/runtime-quarkus-ubuntu:root + yolean/runtime-quarkus-ubuntu:root=docker-image://ghcr.io/yolean/runtime-quarkus-ubuntu:root continue-on-error: false timeout-minutes: 45 - @@ -939,7 +939,7 @@ jobs: type=gha,scope=buildx-runtime-quarkus-deno cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-deno-latest build-contexts: | - yolean/runtime-quarkus-deno=docker-image://ghcr.io/yolean/runtime-quarkus-deno:root + yolean/runtime-quarkus-deno:root=docker-image://ghcr.io/yolean/runtime-quarkus-deno:root continue-on-error: false timeout-minutes: 45 - @@ -961,8 +961,8 @@ jobs: type=gha,scope=buildx-runtime-quarkus-ubuntu-jre cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-ubuntu-jre-root build-contexts: | - yolean/java=docker-image://ghcr.io/yolean/java:root - yolean/runtime-quarkus-ubuntu=docker-image://ghcr.io/yolean/runtime-quarkus-ubuntu:root + yolean/java:root=docker-image://ghcr.io/yolean/java:root + yolean/runtime-quarkus-ubuntu:root=docker-image://ghcr.io/yolean/runtime-quarkus-ubuntu:root continue-on-error: false timeout-minutes: 45 - @@ -984,7 +984,7 @@ jobs: type=gha,scope=buildx-runtime-quarkus-ubuntu-jre cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-ubuntu-jre-latest build-contexts: | - yolean/runtime-quarkus-ubuntu-jre=docker-image://ghcr.io/yolean/runtime-quarkus-ubuntu-jre:root + yolean/runtime-quarkus-ubuntu-jre:root=docker-image://ghcr.io/yolean/runtime-quarkus-ubuntu-jre:root continue-on-error: false timeout-minutes: 45 - @@ -1007,7 +1007,7 @@ jobs: cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-dev-root build-contexts: | yolean/builder-quarkus=docker-image://ghcr.io/yolean/builder-quarkus - yolean/runtime-quarkus-ubuntu=docker-image://ghcr.io/yolean/runtime-quarkus-ubuntu:root + yolean/runtime-quarkus-ubuntu:root=docker-image://ghcr.io/yolean/runtime-quarkus-ubuntu:root continue-on-error: false timeout-minutes: 45 - @@ -1029,7 +1029,7 @@ jobs: type=gha,scope=buildx-runtime-quarkus-dev cache-to: type=gha,mode=max,scope=buildx-runtime-quarkus-dev-latest build-contexts: | - yolean/runtime-quarkus-dev=docker-image://ghcr.io/yolean/runtime-quarkus-dev:root + yolean/runtime-quarkus-dev:root=docker-image://ghcr.io/yolean/runtime-quarkus-dev:root continue-on-error: false timeout-minutes: 45 - @@ -1074,7 +1074,7 @@ jobs: type=gha,scope=buildx-toil-storage cache-to: type=gha,mode=max,scope=buildx-toil-storage-latest build-contexts: | - yolean/toil-storage=docker-image://ghcr.io/yolean/toil-storage:root + yolean/toil-storage:root=docker-image://ghcr.io/yolean/toil-storage:root continue-on-error: false timeout-minutes: 45 - @@ -1118,7 +1118,7 @@ jobs: type=gha,scope=buildx-curl-yq cache-to: type=gha,mode=max,scope=buildx-curl-yq-latest build-contexts: | - yolean/curl-yq=docker-image://ghcr.io/yolean/curl-yq:root + yolean/curl-yq:root=docker-image://ghcr.io/yolean/curl-yq:root continue-on-error: false timeout-minutes: 45 - @@ -1163,6 +1163,6 @@ jobs: type=gha,scope=buildx-duckdb cache-to: type=gha,mode=max,scope=buildx-duckdb-latest build-contexts: | - yolean/duckdb=docker-image://ghcr.io/yolean/duckdb:root + yolean/duckdb:root=docker-image://ghcr.io/yolean/duckdb:root continue-on-error: false timeout-minutes: 45 diff --git a/test.sh b/test.sh index 5c34a78..c70f53f 100755 --- a/test.sh +++ b/test.sh @@ -114,9 +114,7 @@ EOF if [ ! -z "$DEPENDENCIES" ]; then echo " build-contexts: |" for NAME_FULL in $DEPENDENCIES; do - # Extract image name without tag - local IMAGE_NAME=$(echo "$NAME_FULL" | cut -d':' -f1) - echo " $IMAGE_NAME=docker-image://ghcr.io/$NAME_FULL" + echo " $NAME_FULL=docker-image://ghcr.io/$NAME_FULL" done fi From 7b9444187e01b8c0fdfd93c48bffe878e44d811f Mon Sep 17 00:00:00 2001 From: Staffan Olsson Date: Sun, 7 Sep 2025 16:30:24 +0200 Subject: [PATCH 10/10] shows example content from the provenance blobs we push with indexes --- print-provenance.sh | 138 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100755 print-provenance.sh diff --git a/print-provenance.sh b/print-provenance.sh new file mode 100755 index 0000000..161bff5 --- /dev/null +++ b/print-provenance.sh @@ -0,0 +1,138 @@ +#!/usr/bin/env bash +set -euo pipefail + +usage() { + cat >&2 < [--raw] [--debug] + --raw Print full attestation JSON (can repeat for multiple) + --debug Show crane commands executed +Defaults to :latest if no tag provided. +EOF +} + +if ! command -v crane >/dev/null 2>&1; then + echo "crane not found in PATH" >&2; exit 1; fi +if ! command -v jq >/dev/null 2>&1; then + echo "jq not found in PATH" >&2; exit 1; fi + +[ $# -ge 1 ] || { usage; exit 1; } + +IMAGE="$1"; shift || true +RAW="false"; DEBUG="false" +while [ $# -gt 0 ]; do + case "$1" in + --raw) RAW="true";; + --debug) DEBUG="true";; + -h|--help) usage; exit 0;; + *) echo "Unknown arg: $1" >&2; usage; exit 1;; + esac + shift +done + +# Add :latest if no explicit tag or digest +if [[ "$IMAGE" != *:@* && "$IMAGE" != *:*/*:* && "$IMAGE" != *:*:* && "$IMAGE" != *@sha256:* ]]; then + # has no :tag part after last slash + if [[ "$IMAGE" != *:* ]]; then + IMAGE+=":latest" + fi +fi + +echo "Inspecting provenance for $IMAGE" >&2 + +# Obtain manifest list (or single manifest) JSON +if ! MANIFEST_JSON=$(crane manifest "$IMAGE" 2>/dev/null); then + echo "Failed to fetch manifest for $IMAGE" >&2; exit 1; +fi + +# If it's a single-platform manifest, wrap to unify processing +if ! echo "$MANIFEST_JSON" | jq -e '.manifests' >/dev/null 2>&1; then + MANIFEST_LIST_JSON='{"manifests":[]}' +else + MANIFEST_LIST_JSON="$MANIFEST_JSON" +fi + +UNKNOWN_DIGESTS=$(echo "$MANIFEST_LIST_JSON" | jq -r '.manifests[]? | select(.platform.os=="unknown" and .platform.architecture=="unknown") | .digest') +if [ -z "$UNKNOWN_DIGESTS" ]; then + echo "No unknown/unknown platform manifests (attestations) found." >&2 + echo "Hint: ensure builds set provenance and sbom (buildkit) or attest step." >&2 + exit 2 +fi + +FOUND=0 +REGISTRY="${IMAGE%%/*}" # crude but ok for ghcr.io/owner/name:tag +REPO_TAG=${IMAGE#*/} +# Split repo and tag/digest +if [[ "$REPO_TAG" == *"@sha256:"* ]]; then + REPO="${REPO_TAG%@sha256:*}"; REF="${REPO_TAG#*@}"; REF_TYPE=digest +else + REPO="${REPO_TAG%%:*}"; REF="${REPO_TAG##*:}"; REF_TYPE=tag +fi + +IMAGE_PATH=${IMAGE#*/} # remove registry +REPO_PATH=${IMAGE_PATH%%@*} # drop @digest if any +REPO_PATH=${REPO_PATH%%:*} # drop :tag + +[ "$DEBUG" = "true" ] && echo "+ crane manifest $IMAGE # top-level" >&2 + +for DGST in $UNKNOWN_DIGESTS; do + BASE_REF=${IMAGE%%@*}; BASE_REF=${BASE_REF%%:*} # registry/owner/name + SUB_JSON=$(crane manifest "${BASE_REF}@${DGST}" 2>/dev/null) || continue + [ "$DEBUG" = "true" ] && echo "+ crane manifest ${BASE_REF}@${DGST}" >&2 + LAYER_DIGESTS=$(echo "$SUB_JSON" | jq -r '.layers[]? | select(.mediaType | test("in-toto")) | .digest') + [ -z "$LAYER_DIGESTS" ] && continue + for LD in $LAYER_DIGESTS; do + FOUND=1 + [ "$DEBUG" = "true" ] && echo "Sub-manifest digest: $DGST" >&2 && echo "In-toto layer digest: $LD" >&2 + # Retrieve attestation layer (handle crane versions expecting single arg) + [ "$DEBUG" = "true" ] && echo "+ crane blob ${BASE_REF}@${LD}" >&2 + ATTESTATION=$(crane blob "${BASE_REF}@${LD}" 2>/dev/null || crane blob "${IMAGE%@*}@${LD}" 2>/dev/null || true) + [ -z "$ATTESTATION" ] && continue + if [ "$RAW" = "true" ]; then + echo "$ATTESTATION" | jq '.' + continue + fi + echo "--- Attestation layer $LD (sub-manifest $DGST) ---" + JQ_SUMMARY='def dockerfiles: [ (.. | objects | to_entries[]? | select(.key|test("dockerfile";"i")) | .value) ] | flatten | map(tostring) | unique | .; + def mats: (.materials // .predicate.materials // []); + def norm(u; d): + if (u|startswith("docker-image://")) then + (u | sub("^docker-image://";"")) as $ref | + if (d|length>0) and ($ref|test("@sha256:" )|not) then ($ref|split("@")|.[0]) + "@sha256:" + d else $ref end + elif (u|startswith("pkg:docker/")) then + (u | sub("^pkg:docker/";"") | split("?") | .[0]) as $ref | + if (d|length>0) and ($ref|test("@sha256:" )|not) then ($ref|split("@")|.[0]) + "@sha256:" + d else $ref end + else + if (d|length>0) and (u|test("@sha256:" )|not) then (u + "@sha256:" + d) else u end + end; + def base_images: mats | map( ( .uri // .uri_ // empty ) as $u | ( .digest.sha256? // "" ) as $d | select($u != "") | norm($u; $d) ) | unique; + def bkmeta: .predicate.metadata["https://mobyproject.org/buildkit@v1#metadata"].vcs? // {}; + def guess_source: (bkmeta.source // .predicate.invocation.environment.GIT_URL? // .predicate.buildConfig.sourceProvenance.resolvedRepoSource.repoUrl? // empty); + def guess_revision: (bkmeta.revision // .predicate.invocation.environment.GITHUB_SHA? // .predicate.invocation.environment.GIT_COMMIT_SHA? // empty); + ["Dockerfiles:"] + (dockerfiles| if length==0 then ["(none found)"] else . end) + + ["Base images (materials):"] + (base_images | if length==0 then ["(none found)"] else . end) + + ["VCS source:", (guess_source // "(unknown)"), + "VCS revision:", (guess_revision // "(unknown)"), + "Build started:", (.predicate.metadata.buildStartedOn? // "(unknown)"), + "Build finished:", (.predicate.metadata.buildFinishedOn? // "(unknown)")] | .[]' + [ "$DEBUG" = "true" ] && echo "+ jq -r " >&2 && echo "$JQ_SUMMARY" | sed 's/^/| /' >&2 + SUMMARY=$(echo "$ATTESTATION" | jq -r "$JQ_SUMMARY") + if [ -z "${PREV_LAST:-}" ]; then + echo "$SUMMARY" + else + DIFF_PRINTED=false + while IFS= read -r line; do + if ! printf '%s\n' "$PREV_LAST" | grep -Fxq "$line"; then + [ "$DIFF_PRINTED" = false ] && echo "(diff from previous attestation)" && DIFF_PRINTED=true + echo "$line" + fi + done <<< "$SUMMARY" + [ "$DIFF_PRINTED" = false ] && echo "(no diff from previous attestation)" + fi + PREV_LAST="$SUMMARY" + done +done + +if [ $FOUND -eq 0 ]; then + echo "No attestation (in-toto) layers found in unknown/unknown manifests." >&2 + exit 3 +fi