From eca82fcdf7a01bfd73dfd239b4b5f45326a65c80 Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Fri, 14 Nov 2025 10:56:40 +0100 Subject: [PATCH 1/5] ci(test): test local single platform Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- .github/workflows/.test.yml | 86 +++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/.github/workflows/.test.yml b/.github/workflows/.test.yml index a66a7de..cce8c6a 100644 --- a/.github/workflows/.test.yml +++ b/.github/workflows/.test.yml @@ -223,6 +223,18 @@ jobs: await exec.exec(cmd); } + build-local-single: + uses: ./.github/workflows/build.yml + permissions: + contents: read + packages: write + id-token: write + with: + output: ${{ github.event_name != 'pull_request' && 'local' || 'cacheonly' }} + artifact-name: build-output-single + build-file: test/hello.Dockerfile + build-sbom: true + bake-aws: uses: ./.github/workflows/bake.yml permissions: @@ -279,6 +291,66 @@ jobs: await exec.exec(cmd); } + bake-ghcr-and-aws: + uses: ./.github/workflows/bake.yml + permissions: + contents: read + packages: write + id-token: write + with: + context: test + target: hello-cross + output: ${{ github.event_name != 'pull_request' && 'registry' || 'cacheonly' }} + cache: true + cache-scope: bake-aws + meta-images: | + ghcr.io/docker/github-builder-test + public.ecr.aws/q3b5f1u4/test-docker-action + meta-tags: | + type=raw,value=${{ github.run_id }},prefix=bake-ghcr-and-aws- + bake-sbom: true + secrets: + registry-auths: | + - registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - registry: public.ecr.aws + username: ${{ secrets.AWS_ACCESS_KEY_ID }} + password: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + + bake-ghcr-and-aws-verify: + runs-on: ubuntu-latest + if: ${{ github.event_name != 'pull_request' }} + needs: + - bake-ghcr-and-aws + steps: + - + name: Install Cosign + uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 + with: + cosign-release: ${{ needs.bake-ghcr-and-aws.outputs.cosign-version }} + - + name: Login to registry + uses: docker/login-action@v3 + with: + registry: public.ecr.aws + username: ${{ secrets.AWS_ACCESS_KEY_ID }} + password: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + - + name: Verify signatures + uses: actions/github-script@v8 + env: + INPUT_COSIGN-VERSION: ${{ needs.bake-ghcr-and-aws.outputs.cosign-version }} + INPUT_COSIGN-VERIFY-COMMANDS: ${{ needs.bake-ghcr-and-aws.outputs.cosign-verify-commands }} + with: + script: | + const cosignVersion = core.getInput('cosign-version'); + core.info(`Cosign version used by Docker GitHub Builder: ${cosignVersion}`); + const cosignVerifyCommands = core.getMultilineInput('cosign-verify-commands'); + for (const cmd of cosignVerifyCommands) { + await exec.exec(cmd); + } + bake-local: uses: ./.github/workflows/bake.yml permissions: @@ -323,3 +395,17 @@ jobs: for (const cmd of cosignVerifyCommands) { await exec.exec(cmd); } + + bake-local-single: + uses: ./.github/workflows/bake.yml + permissions: + contents: read + packages: write + id-token: write + with: + context: test + target: hello + output: ${{ github.event_name != 'pull_request' && 'local' || 'cacheonly' }} + cache: true + artifact-name: bake-output-single + bake-sbom: true From 5c7981904f7bd16bc379d23629b17117007b16c4 Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Fri, 14 Nov 2025 10:56:40 +0100 Subject: [PATCH 2/5] bake: distributed builds Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- .github/workflows/.test.yml | 5 +- .github/workflows/bake.yml | 300 ++++++++++++++++++++++++++++++++---- 2 files changed, 277 insertions(+), 28 deletions(-) diff --git a/.github/workflows/.test.yml b/.github/workflows/.test.yml index cce8c6a..b175ad8 100644 --- a/.github/workflows/.test.yml +++ b/.github/workflows/.test.yml @@ -377,10 +377,11 @@ jobs: with: cosign-release: ${{ needs.bake-local.outputs.cosign-version }} - - name: Download artifact + name: Download artifacts uses: actions/download-artifact@v5 with: - name: ${{ needs.bake-local.outputs.artifact-name }} + pattern: ${{ needs.bake-local.outputs.artifact-name }}* + merge-multiple: true - name: Verify signatures uses: actions/github-script@v8 diff --git a/.github/workflows/bake.yml b/.github/workflows/bake.yml index 37e59cd..6437585 100644 --- a/.github/workflows/bake.yml +++ b/.github/workflows/bake.yml @@ -3,6 +3,11 @@ name: bake on: workflow_call: inputs: + runner: + type: string + description: "Runner instance" + required: false + default: 'auto' context: type: string description: "Context to build from, defaults to repository root" @@ -118,30 +123,169 @@ on: outputs: cosign-version: description: Cosign version used for verification - value: ${{ jobs.build.outputs.cosign-version }} + value: ${{ jobs.post.outputs.cosign-version }} cosign-verify-commands: description: Cosign verify commands - value: ${{ jobs.build.outputs.cosign-verify-commands }} + value: ${{ jobs.post.outputs.cosign-verify-commands }} artifact-name: description: Name of the uploaded artifact (for local output) - value: ${{ jobs.build.outputs.artifact-name }} + value: ${{ jobs.post.outputs.artifact-name }} env: DOCKER_ACTIONS_TOOLKIT_MODULE: "@docker/actions-toolkit@0.67.0" COSIGN_VERSION: "v3.0.2" LOCAL_EXPORT_DIR: "/tmp/buildx-output" + MATRIX_SIZE_LIMIT: 20 jobs: - build: - runs-on: ubuntu-latest + prepare: + runs-on: ${{ inputs.runner == 'auto' && 'ubuntu-latest' || inputs.runner }} outputs: - cosign-version: ${{ env.COSIGN_VERSION }} - cosign-verify-commands: ${{ steps.signing-attestation-manifests.outputs.verify-commands || steps.signing-local-artifacts.outputs.verify-commands }} - artifact-name: ${{ inputs.artifact-name }} + includes: ${{ steps.set.outputs.includes }} + steps: + - + name: Environment variables + uses: actions/github-script@v8 + env: + INPUT_ENVS: ${{ inputs.envs }} + with: + script: | + for (const env of core.getMultilineInput('envs')) { + core.info(env); + const [key, value] = env.split('=', 2); + core.exportVariable(key, value); + } + - + name: Install @docker/actions-toolkit + uses: actions/github-script@v8 + env: + INPUT_DAT-MODULE: ${{ env.DOCKER_ACTIONS_TOOLKIT_MODULE }} + with: + script: | + await exec.exec('npm', ['install', '--prefer-offline', '--no-audit', core.getInput('dat-module')]); + - + name: Set includes + id: set + uses: actions/github-script@v8 + env: + INPUT_MATRIX-SIZE-LIMIT: ${{ env.MATRIX_SIZE_LIMIT }} + INPUT_RUNNER: ${{ inputs.runner }} + INPUT_CONTEXT: ${{ inputs.context }} + INPUT_TARGET: ${{ inputs.target }} + INPUT_BAKE-ALLOW: ${{ inputs.bake-allow }} + INPUT_BAKE-FILES: ${{ inputs.bake-files }} + INPUT_BAKE-PULL: ${{ inputs.bake-pull }} + INPUT_BAKE-SBOM: ${{ inputs.bake-sbom }} + INPUT_BAKE-SET: ${{ inputs.bake-set }} + INPUT_GITHUB-TOKEN: ${{ secrets.github-token || github.token }} + with: + script: | + const os = require('os'); + const { Bake } = require('@docker/actions-toolkit/lib/buildx/bake'); + const { Util } = require('@docker/actions-toolkit/lib/util'); + + const inpMatrixSizeLimit = parseInt(core.getInput('matrix-size-limit'), 10); + + const inpRunner = core.getInput('runner'); + const inpContext = core.getInput('context'); + const inpTarget = core.getInput('target'); + const inpBakeAllow = core.getInput('bake-allow'); + const inpBakeFiles = Util.getInputList('bake-files'); + const inpBakePull = core.getBooleanInput('bake-pull'); + const inpBakeSbom = core.getInput('bake-sbom'); + const inpBakeSet = Util.getInputList('bake-set', {ignoreComma: true, quote: false}); + const inpGitHubToken = core.getInput('github-token'); + + const bakeSource = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}.git#${process.env.GITHUB_REF}:${inpContext}`; + await core.group(`Set bake source`, async () => { + core.info(bakeSource); + }); + + let def; + let target; + await core.group(`Validating definition`, async () => { + const bake = new Bake(); + def = await bake.getDefinition({ + allow: inpBakeAllow, + files: inpBakeFiles, + overrides: inpBakeSet, + sbom: inpBakeSbom, + source: bakeSource, + targets: [inpTarget], + githubToken: inpGitHubToken + }); + if (!def) { + throw new Error('Bake definition not set'); + } + const targets = Object.keys(def.target); + if (targets.length > 1) { + throw new Error(`Only one target can be built at once, found: ${targets.join(', ')}`); + } + target = targets[0]; + }); + + await core.group(`Set includes`, async () => { + let includes = []; + const platforms = def.target[target].platforms || []; + if (platforms.length > inpMatrixSizeLimit) { + throw new Error(`Platforms to build exceed matrix size limit of ${inpMatrixSizeLimit}`); + } else if (platforms.length === 0) { + includes.push({ + index: 0, + runner: inpRunner === 'auto' ? 'ubuntu-latest' : inpRunner + }); + } else { + platforms.forEach((platform, index) => { + let runner = inpRunner; + if (runner === 'auto') { + runner = platform.startsWith('linux/arm') ? 'ubuntu-24.04-arm' : 'ubuntu-latest'; + } + includes.push({ + index: index, + platform: platform, + runner: runner + }); + }); + } + core.info(JSON.stringify(includes, null, 2)); + core.setOutput('includes', JSON.stringify(includes)); + }); + + build: + runs-on: ${{ matrix.runner }} + needs: + - prepare permissions: contents: read id-token: write # needed for signing the images with GitHub OIDC Token packages: write # needed to push images to GitHub Container Registry + strategy: + fail-fast: false + matrix: + include: ${{ fromJson(needs.prepare.outputs.includes) }} + outputs: + # needs predefined outputs as we can't use dynamic ones atm: https://github.com/actions/runner/pull/2477 + # 20 is the maximum number of platforms supported by our matrix strategy + result_0: ${{ steps.result.outputs.result_0 }} + result_1: ${{ steps.result.outputs.result_1 }} + result_2: ${{ steps.result.outputs.result_2 }} + result_3: ${{ steps.result.outputs.result_3 }} + result_4: ${{ steps.result.outputs.result_4 }} + result_5: ${{ steps.result.outputs.result_5 }} + result_6: ${{ steps.result.outputs.result_6 }} + result_7: ${{ steps.result.outputs.result_7 }} + result_8: ${{ steps.result.outputs.result_8 }} + result_9: ${{ steps.result.outputs.result_9 }} + result_10: ${{ steps.result.outputs.result_10 }} + result_11: ${{ steps.result.outputs.result_11 }} + result_12: ${{ steps.result.outputs.result_12 }} + result_13: ${{ steps.result.outputs.result_13 }} + result_14: ${{ steps.result.outputs.result_14 }} + result_15: ${{ steps.result.outputs.result_15 }} + result_16: ${{ steps.result.outputs.result_16 }} + result_17: ${{ steps.result.outputs.result_17 }} + result_18: ${{ steps.result.outputs.result_18 }} + result_19: ${{ steps.result.outputs.result_19 }} steps: - name: Environment variables @@ -192,6 +336,7 @@ jobs: id: prepare uses: actions/github-script@v8 env: + INPUT_PLATFORM: ${{ matrix.platform }} INPUT_LOCAL-EXPORT-DIR: ${{ env.LOCAL_EXPORT_DIR }} INPUT_CONTEXT: ${{ inputs.context }} INPUT_TARGET: ${{ inputs.target }} @@ -217,7 +362,12 @@ jobs: const { Bake } = require('@docker/actions-toolkit/lib/buildx/bake'); const { Util } = require('@docker/actions-toolkit/lib/util'); + const inpPlatform = core.getInput('platform'); + const platformPairSuffix = inpPlatform ? `-${inpPlatform.replace(/\//g, '-')}` : ''; + core.setOutput('platform-pair-suffix', platformPairSuffix); + const inpLocalExportDir = core.getInput('local-export-dir'); + const inpContext = core.getInput('context'); const inpTarget = core.getInput('target'); const inpOutput = core.getInput('output'); @@ -297,7 +447,7 @@ jobs: outputOverride = `*.output=type=registry,"name=${inpMetaImages.join(',')}",oci-artifact=true,push-by-digest=true,name-canonical=true`; break; case 'local': - outputOverride = `*.output=type=local,dest=${inpLocalExportDir}`; + outputOverride = `*.output=type=local,platform-split=true,dest=${inpLocalExportDir}`; break; default: core.setFailed(`Invalid output: ${inpOutput}`); @@ -306,9 +456,12 @@ jobs: let bakeOverrides = [...inpBakeSet, outputOverride]; await core.group(`Set bake overrides`, async () => { bakeOverrides.push('*.attest=type=provenance,mode=max,version=v1', '*.tags='); + if (inpPlatform) { + bakeOverrides.push(`*.platform=${inpPlatform}`); + } if (inpCache) { - bakeOverrides.push(`*.cache-from=type=gha,scope=${inpCacheScope || target}`); - bakeOverrides.push(`*.cache-to=type=gha,scope=${inpCacheScope || target},mode=${inpCacheMode}`); + bakeOverrides.push(`*.cache-from=type=gha,scope=${inpCacheScope || target}${platformPairSuffix}`); + bakeOverrides.push(`*.cache-to=type=gha,scope=${inpCacheScope || target}${platformPairSuffix},mode=${inpCacheMode}`); } core.info(JSON.stringify(bakeOverrides, null, 2)); core.setOutput('overrides', bakeOverrides.join(os.EOL)); @@ -434,6 +587,79 @@ jobs: } core.setOutput('verify-commands', verifyCommands.join('\n')); }); + - + name: List local output + if: ${{ inputs.output == 'local' }} + run: | + tree -nh ${{ env.LOCAL_EXPORT_DIR }} + - + name: Upload artifact + if: ${{ inputs.output == 'local' }} + uses: actions/upload-artifact@v5 + with: + name: ${{ inputs.artifact-name }}${{ steps.prepare.outputs.platform-pair-suffix }} + path: ${{ env.LOCAL_EXPORT_DIR }} + if-no-files-found: error + - + name: Set result output + id: result + uses: actions/github-script@v8 + env: + INPUT_INDEX: ${{ matrix.index }} + INPUT_VERIFY-COMMANDS: ${{ steps.signing-attestation-manifests.outputs.verify-commands || steps.signing-local-artifacts.outputs.verify-commands }} + INPUT_IMAGE-DIGEST: ${{ steps.get-image-digest.outputs.digest }} + INPUT_ARTIFACT-NAME: ${{ inputs.artifact-name }}${{ steps.prepare.outputs.platform-pair-suffix }} + with: + script: | + const inpIndex = core.getInput('index'); + const inpVerifyCommands = core.getInput('verify-commands'); + const inpImageDigest = core.getInput('image-digest'); + const inpArtifactName = core.getInput('artifact-name'); + + const result = { + verifyCommands: inpVerifyCommands, + imageDigest: inpImageDigest, + artifactName: inpArtifactName + } + core.info(JSON.stringify(result, null, 2)); + + core.setOutput(`result_${inpIndex}`, JSON.stringify(result)); + + post: + runs-on: ubuntu-latest + outputs: + cosign-version: ${{ env.COSIGN_VERSION }} + cosign-verify-commands: ${{ steps.set.outputs.cosign-verify-commands }} + artifact-name: ${{ inputs.artifact-name }} + needs: + - build + steps: + - + name: Docker meta + id: meta + if: ${{ inputs.output == 'registry' }} + uses: docker/metadata-action@v5 + with: + images: ${{ inputs.meta-images }} + tags: ${{ inputs.meta-tags }} + flavor: ${{ inputs.meta-flavor }} + labels: ${{ inputs.meta-labels }} + annotations: ${{ inputs.meta-annotations }} + bake-target: ${{ inputs.meta-bake-target }} + - + name: Login to registry + if: ${{ inputs.output == 'registry' }} + # TODO: switch to docker/login-action when OIDC is supported + uses: crazy-max/docker-login-action@dockerhub-oidc + with: + registry-auth: ${{ secrets.registry-auths }} + - + name: Set up Docker Buildx + if: ${{ inputs.output == 'registry' }} + uses: docker/setup-buildx-action@v3 + with: + version: latest + buildkitd-flags: --debug - name: Create manifest if: ${{ inputs.output == 'registry' }} @@ -441,15 +667,32 @@ jobs: env: INPUT_IMAGE-NAMES: ${{ inputs.meta-images }} INPUT_TAG-NAMES: ${{ steps.meta.outputs.tag-names }} - INPUT_IMAGE-DIGEST: ${{ steps.get-image-digest.outputs.digest }} + INPUT_BUILD-OUTPUTS: ${{ toJSON(needs.build.outputs) }} with: script: | - for (const imageName of core.getMultilineInput('image-names')) { + const inpImageNames = core.getMultilineInput('image-names'); + const inpTagNames = core.getMultilineInput('tag-names'); + const inpBuildOutputs = JSON.parse(core.getInput('build-outputs')); + + const digests = []; + for (const key of Object.keys(inpBuildOutputs)) { + const output = JSON.parse(inpBuildOutputs[key]); + if (output.imageDigest) { + digests.push(output.imageDigest); + } + } + if (digests.length === 0) { + throw new Error('No image digests found from build outputs'); + } + + for (const imageName of inpImageNames) { let createArgs = ['buildx', 'imagetools', 'create']; - for (const tag of core.getMultilineInput('tag-names')) { + for (const tag of inpTagNames) { createArgs.push('-t', `${imageName}:${tag}`); } - createArgs.push(core.getInput('image-digest')); + for (const digest of digests) { + createArgs.push(digest); + } await exec.getExecOutput('docker', createArgs, { ignoreReturnCode: true }).then(res => { @@ -459,15 +702,20 @@ jobs: }); } - - name: List local output - if: ${{ inputs.output == 'local' }} - run: | - tree -nh ${{ env.LOCAL_EXPORT_DIR }} - - - name: Upload artifact - if: ${{ inputs.output == 'local' }} - uses: actions/upload-artifact@v5 + name: Set outputs + id: set + if: ${{ inputs.output != 'cacheonly' }} + uses: actions/github-script@v8 + env: + INPUT_BUILD-OUTPUTS: ${{ toJSON(needs.build.outputs) }} with: - name: ${{ inputs.artifact-name }} - path: ${{ env.LOCAL_EXPORT_DIR }} - if-no-files-found: error + script: | + const inpBuildOutputs = JSON.parse(core.getInput('build-outputs')); + const verifyCommands = []; + for (const key of Object.keys(inpBuildOutputs)) { + const output = JSON.parse(inpBuildOutputs[key]); + if (output.verifyCommands) { + verifyCommands.push(output.verifyCommands); + } + } + core.setOutput('cosign-verify-commands', verifyCommands.join('\n')); From d7db7279b3da4eb7c2d3b2693bbdd34ed8698305 Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Fri, 14 Nov 2025 14:52:18 +0100 Subject: [PATCH 3/5] bake: rename runner input to runs-on and defaults to empty Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- .github/workflows/bake.yml | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/.github/workflows/bake.yml b/.github/workflows/bake.yml index 6437585..8449c32 100644 --- a/.github/workflows/bake.yml +++ b/.github/workflows/bake.yml @@ -3,14 +3,13 @@ name: bake on: workflow_call: inputs: - runner: + runs-on: type: string - description: "Runner instance" + description: "Type of machine to run the jobs on similar to jobs..runs-on (defaults to best matching runner depending on target platform)" required: false - default: 'auto' context: type: string - description: "Context to build from, defaults to repository root" + description: "Context to build from (defaults to repository root)" required: false default: . target: @@ -39,7 +38,7 @@ on: default: false cache-scope: type: string - description: "Which scope cache object belongs to if cache enabled (default is target name)" + description: "Which scope cache object belongs to if cache enabled (defaults to target name)" required: false cache-mode: type: string @@ -84,7 +83,7 @@ on: required: false meta-bake-target: type: string - description: "Bake target name for metadata (default is docker-metadata-action)" + description: "Bake target name for metadata (defaults to docker-metadata-action)" required: false # same as docker/setup-qemu-action inputs (minus platforms, cache-image) qemu-image: @@ -98,7 +97,7 @@ on: required: false bake-files: type: string - description: "List of bake definition files (default: docker-bake.hcl)" + description: "List of bake definition files (defaults to docker-bake.hcl)" required: false bake-pull: type: boolean @@ -135,11 +134,11 @@ env: DOCKER_ACTIONS_TOOLKIT_MODULE: "@docker/actions-toolkit@0.67.0" COSIGN_VERSION: "v3.0.2" LOCAL_EXPORT_DIR: "/tmp/buildx-output" - MATRIX_SIZE_LIMIT: 20 + MATRIX_SIZE_LIMIT: "20" jobs: prepare: - runs-on: ${{ inputs.runner == 'auto' && 'ubuntu-latest' || inputs.runner }} + runs-on: ${{ inputs.runs-on || 'ubuntu-latest' }} outputs: includes: ${{ steps.set.outputs.includes }} steps: @@ -169,7 +168,7 @@ jobs: uses: actions/github-script@v8 env: INPUT_MATRIX-SIZE-LIMIT: ${{ env.MATRIX_SIZE_LIMIT }} - INPUT_RUNNER: ${{ inputs.runner }} + INPUT_RUNS-ON: ${{ inputs.runs-on || 'ubuntu-latest' }} INPUT_CONTEXT: ${{ inputs.context }} INPUT_TARGET: ${{ inputs.target }} INPUT_BAKE-ALLOW: ${{ inputs.bake-allow }} @@ -185,8 +184,8 @@ jobs: const { Util } = require('@docker/actions-toolkit/lib/util'); const inpMatrixSizeLimit = parseInt(core.getInput('matrix-size-limit'), 10); - - const inpRunner = core.getInput('runner'); + + const inpRunsOn = core.getInput('runs-on'); const inpContext = core.getInput('context'); const inpTarget = core.getInput('target'); const inpBakeAllow = core.getInput('bake-allow'); @@ -232,18 +231,18 @@ jobs: } else if (platforms.length === 0) { includes.push({ index: 0, - runner: inpRunner === 'auto' ? 'ubuntu-latest' : inpRunner + 'runs-on': inpRunsOn }); } else { platforms.forEach((platform, index) => { - let runner = inpRunner; - if (runner === 'auto') { - runner = platform.startsWith('linux/arm') ? 'ubuntu-24.04-arm' : 'ubuntu-latest'; + let runsOn = inpRunsOn; + if (!runsOn) { + runsOn = platform.startsWith('linux/arm') ? 'ubuntu-24.04-arm' : 'ubuntu-latest'; } includes.push({ index: index, platform: platform, - runner: runner + 'runs-on': runsOn }); }); } @@ -252,7 +251,7 @@ jobs: }); build: - runs-on: ${{ matrix.runner }} + runs-on: ${{ matrix.runs-on }} needs: - prepare permissions: @@ -626,7 +625,7 @@ jobs: core.setOutput(`result_${inpIndex}`, JSON.stringify(result)); post: - runs-on: ubuntu-latest + runs-on: ${{ inputs.runs-on || 'ubuntu-latest' }} outputs: cosign-version: ${{ env.COSIGN_VERSION }} cosign-verify-commands: ${{ steps.set.outputs.cosign-verify-commands }} From 9d004f0644947cd3666cb5ba6da2a0958c330616 Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Fri, 14 Nov 2025 16:43:56 +0100 Subject: [PATCH 4/5] bake: update workflow permissions Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- .github/workflows/bake.yml | 9 +++++++-- .github/workflows/build.yml | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/bake.yml b/.github/workflows/bake.yml index 8449c32..14f3b01 100644 --- a/.github/workflows/bake.yml +++ b/.github/workflows/bake.yml @@ -139,6 +139,8 @@ env: jobs: prepare: runs-on: ${{ inputs.runs-on || 'ubuntu-latest' }} + permissions: + contents: read outputs: includes: ${{ steps.set.outputs.includes }} steps: @@ -256,8 +258,8 @@ jobs: - prepare permissions: contents: read - id-token: write # needed for signing the images with GitHub OIDC Token - packages: write # needed to push images to GitHub Container Registry + id-token: write # for signing attestation manifests with GitHub OIDC Token + packages: write # only used if pushing to GHCR but needs to be defined as caller must provide permissions ≥ to those used in the reusable workflow strategy: fail-fast: false matrix: @@ -626,6 +628,9 @@ jobs: post: runs-on: ${{ inputs.runs-on || 'ubuntu-latest' }} + permissions: + contents: read + packages: write # only used if pushing to GHCR but needs to be defined as caller must provide permissions ≥ to those used in the reusable workflow outputs: cosign-version: ${{ env.COSIGN_VERSION }} cosign-verify-commands: ${{ steps.set.outputs.cosign-verify-commands }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index aa3fb03..6fa628f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -142,8 +142,8 @@ jobs: artifact-name: ${{ inputs.artifact-name }} permissions: contents: read - id-token: write # needed for signing the images with GitHub OIDC Token - packages: write # needed to push images to GitHub Container Registry + id-token: write # for signing attestation manifests with GitHub OIDC Token + packages: write # only used if pushing to GHCR but needs to be defined as caller must provide permissions ≥ to those used in the reusable workflow steps: - name: Docker meta From f74a6b71d0a561ca851ff83b713636a26ab49c53 Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Fri, 14 Nov 2025 18:00:43 +0100 Subject: [PATCH 5/5] bake: rename post job to finalize Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- .github/workflows/bake.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/bake.yml b/.github/workflows/bake.yml index 14f3b01..9a3a7e3 100644 --- a/.github/workflows/bake.yml +++ b/.github/workflows/bake.yml @@ -122,13 +122,13 @@ on: outputs: cosign-version: description: Cosign version used for verification - value: ${{ jobs.post.outputs.cosign-version }} + value: ${{ jobs.finalize.outputs.cosign-version }} cosign-verify-commands: description: Cosign verify commands - value: ${{ jobs.post.outputs.cosign-verify-commands }} + value: ${{ jobs.finalize.outputs.cosign-verify-commands }} artifact-name: description: Name of the uploaded artifact (for local output) - value: ${{ jobs.post.outputs.artifact-name }} + value: ${{ jobs.finalize.outputs.artifact-name }} env: DOCKER_ACTIONS_TOOLKIT_MODULE: "@docker/actions-toolkit@0.67.0" @@ -626,7 +626,7 @@ jobs: core.setOutput(`result_${inpIndex}`, JSON.stringify(result)); - post: + finalize: runs-on: ${{ inputs.runs-on || 'ubuntu-latest' }} permissions: contents: read