diff --git a/.github/workflows/bake.yml b/.github/workflows/bake.yml index 9917eb0..74733b9 100644 --- a/.github/workflows/bake.yml +++ b/.github/workflows/bake.yml @@ -138,6 +138,9 @@ on: artifact-name: description: "Name of the uploaded artifact (for local output)" value: ${{ jobs.finalize.outputs.artifact-name }} + image-digest: + description: "Digest of the built image (for image output if pushed)" + value: ${{ jobs.finalize.outputs.image-digest }} output-type: description: "Build output type" value: ${{ jobs.finalize.outputs.output-type }} @@ -146,11 +149,11 @@ on: value: ${{ jobs.finalize.outputs.signed }} env: - BUILDX_VERSION: "v0.31.1" - BUILDKIT_IMAGE: "moby/buildkit:v0.27.1" + BUILDX_VERSION: "v0.32.1" + BUILDKIT_IMAGE: "moby/buildkit:v0.28.0" SBOM_IMAGE: "docker/buildkit-syft-scanner:1.10.0" BINFMT_IMAGE: "tonistiigi/binfmt:qemu-v10.2.1-65" - DOCKER_ACTIONS_TOOLKIT_MODULE: "@docker/actions-toolkit@0.76.0" + DOCKER_ACTIONS_TOOLKIT_MODULE: "@docker/actions-toolkit@0.80.0" COSIGN_VERSION: "v3.0.2" LOCAL_EXPORT_DIR: "/tmp/buildx-output" MATRIX_SIZE_LIMIT: "20" @@ -250,7 +253,7 @@ jobs: script: | const os = require('os'); const { Bake } = require('@docker/actions-toolkit/lib/buildx/bake'); - const { GitHub } = require('@docker/actions-toolkit/lib/github'); + const { GitHub } = require('@docker/actions-toolkit/lib/github/github'); const { Util } = require('@docker/actions-toolkit/lib/util'); const inpSbomImage = core.getInput('sbom-image'); @@ -617,7 +620,7 @@ jobs: script: | const os = require('os'); const { Build } = require('@docker/actions-toolkit/lib/buildx/build'); - const { GitHub } = require('@docker/actions-toolkit/lib/github'); + const { GitHub } = require('@docker/actions-toolkit/lib/github/github'); const { Util } = require('@docker/actions-toolkit/lib/util'); const inpPlatform = core.getInput('platform'); @@ -904,12 +907,21 @@ jobs: cosign-version: ${{ env.COSIGN_VERSION }} cosign-verify-commands: ${{ steps.set.outputs.cosign-verify-commands }} artifact-name: ${{ inputs.artifact-upload && inputs.artifact-name || '' }} + image-digest: ${{ steps.manifest.outputs.digest }} output-type: ${{ inputs.output }} signed: ${{ needs.prepare.outputs.sign }} needs: - prepare - build steps: + - + name: Install @docker/actions-toolkit + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + env: + INPUT_DAT-MODULE: ${{ env.DOCKER_ACTIONS_TOOLKIT_MODULE }} + with: + script: | + await exec.exec('npm', ['install', '--prefer-offline', '--ignore-scripts', core.getInput('dat-module')]); - name: Docker meta id: meta @@ -941,6 +953,7 @@ jobs: cache-binary: false - name: Create manifest + id: manifest if: ${{ inputs.output == 'image' }} uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: @@ -950,6 +963,8 @@ jobs: INPUT_BUILD-OUTPUTS: ${{ toJSON(needs.build.outputs) }} with: script: | + const { ImageTools } = require('@docker/actions-toolkit/lib/buildx/imagetools'); + const inpPush = core.getBooleanInput('push'); const inpImageNames = core.getMultilineInput('image-names'); const inpTagNames = core.getMultilineInput('tag-names'); @@ -967,22 +982,33 @@ jobs: return; } + let digest; for (const imageName of inpImageNames) { - let createArgs = ['buildx', 'imagetools', 'create']; + const tags = []; for (const tag of inpTagNames) { - createArgs.push('-t', `${imageName}:${tag}`); - } - for (const digest of digests) { - createArgs.push(digest); + tags.push(`${imageName}:${tag}`); } if (inpPush) { - await exec.exec('docker', createArgs); - } else { - await core.group(`Generated imagetools create command for ${imageName}`, async () => { - core.info(`docker ${createArgs.join(' ')}`); + const result = await new ImageTools().create({ + sources: digests, + tags: tags }); + core.info(`Created manifest with digest: ${result.digest}`); + digest = result.digest; + } else { + let createArgs = ['buildx', 'imagetools', 'create']; + for (const tag of tags) { + createArgs.push('-t', tag); + } + for (const digest of digests) { + createArgs.push(digest); + } + core.info(`Generated command for ${imageName}: docker ${createArgs.join(' ')}`); } } + if (digest) { + core.setOutput('digest', digest); + } - name: Merge artifacts if: ${{ inputs.output == 'local' && inputs.artifact-upload }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0d1eac3..fcc5de2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -141,6 +141,9 @@ on: artifact-name: description: "Name of the uploaded artifact (for local output)" value: ${{ jobs.finalize.outputs.artifact-name }} + image-digest: + description: "Digest of the built image (for image output if pushed)" + value: ${{ jobs.finalize.outputs.image-digest }} output-type: description: "Build output type" value: ${{ jobs.finalize.outputs.output-type }} @@ -149,11 +152,11 @@ on: value: ${{ jobs.finalize.outputs.signed }} env: - BUILDX_VERSION: "v0.31.1" - BUILDKIT_IMAGE: "moby/buildkit:v0.27.1" + BUILDX_VERSION: "v0.32.1" + BUILDKIT_IMAGE: "moby/buildkit:v0.28.0" SBOM_IMAGE: "docker/buildkit-syft-scanner:1.10.0" BINFMT_IMAGE: "tonistiigi/binfmt:qemu-v10.2.1-65" - DOCKER_ACTIONS_TOOLKIT_MODULE: "@docker/actions-toolkit@0.76.0" + DOCKER_ACTIONS_TOOLKIT_MODULE: "@docker/actions-toolkit@0.80.0" COSIGN_VERSION: "v3.0.2" LOCAL_EXPORT_DIR: "/tmp/buildx-output" MATRIX_SIZE_LIMIT: "20" @@ -245,7 +248,7 @@ jobs: INPUT_SIGN: ${{ inputs.sign }} with: script: | - const { GitHub } = require('@docker/actions-toolkit/lib/github'); + const { GitHub } = require('@docker/actions-toolkit/lib/github/github'); const { Util } = require('@docker/actions-toolkit/lib/util'); const inpMatrixSizeLimit = parseInt(core.getInput('matrix-size-limit'), 10); @@ -516,7 +519,7 @@ jobs: with: script: | const { Build } = require('@docker/actions-toolkit/lib/buildx/build'); - const { GitHub } = require('@docker/actions-toolkit/lib/github'); + const { GitHub } = require('@docker/actions-toolkit/lib/github/github'); const inpPlatform = core.getInput('platform'); const platformPairSuffix = inpPlatform ? `-${inpPlatform.replace(/\//g, '-')}` : ''; @@ -758,12 +761,21 @@ jobs: cosign-version: ${{ env.COSIGN_VERSION }} cosign-verify-commands: ${{ steps.set.outputs.cosign-verify-commands }} artifact-name: ${{ inputs.artifact-upload && inputs.artifact-name || '' }} + image-digest: ${{ steps.manifest.outputs.digest }} output-type: ${{ inputs.output }} signed: ${{ needs.prepare.outputs.sign }} needs: - prepare - build steps: + - + name: Install @docker/actions-toolkit + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + env: + INPUT_DAT-MODULE: ${{ env.DOCKER_ACTIONS_TOOLKIT_MODULE }} + with: + script: | + await exec.exec('npm', ['install', '--prefer-offline', '--ignore-scripts', core.getInput('dat-module')]); - name: Docker meta id: meta @@ -794,6 +806,7 @@ jobs: cache-binary: false - name: Create manifest + id: manifest if: ${{ inputs.output == 'image' }} uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: @@ -803,6 +816,8 @@ jobs: INPUT_BUILD-OUTPUTS: ${{ toJSON(needs.build.outputs) }} with: script: | + const { ImageTools } = require('@docker/actions-toolkit/lib/buildx/imagetools'); + const inpPush = core.getBooleanInput('push'); const inpImageNames = core.getMultilineInput('image-names'); const inpTagNames = core.getMultilineInput('tag-names'); @@ -820,22 +835,33 @@ jobs: return; } + let digest; for (const imageName of inpImageNames) { - let createArgs = ['buildx', 'imagetools', 'create']; + const tags = []; for (const tag of inpTagNames) { - createArgs.push('-t', `${imageName}:${tag}`); - } - for (const digest of digests) { - createArgs.push(digest); + tags.push(`${imageName}:${tag}`); } if (inpPush) { - await exec.exec('docker', createArgs); - } else { - await core.group(`Generated imagetools create command for ${imageName}`, async () => { - core.info(`docker ${createArgs.join(' ')}`); + const result = await new ImageTools().create({ + sources: digests, + tags: tags }); + core.info(`Created manifest with digest: ${result.digest}`); + digest = result.digest; + } else { + let createArgs = ['buildx', 'imagetools', 'create']; + for (const tag of tags) { + createArgs.push('-t', tag); + } + for (const digest of digests) { + createArgs.push(digest); + } + core.info(`Generated command for ${imageName}: docker ${createArgs.join(' ')}`); } } + if (digest) { + core.setOutput('digest', digest); + } - name: Merge artifacts if: ${{ inputs.output == 'local' && inputs.artifact-upload }}