@@ -10,30 +10,6 @@ branding:
1010 icon : package
1111 color : blue
1212
13- outputs :
14- built-image :
15- description : |
16- Built image data.
17- Example:
18- ```json
19- {
20- "name": "application",
21- "registry": "ghcr.io",
22- "repository": "my-org/my-repo/application",
23- "digest": "sha256:d31aa93410434ac9dcfc9179cac2cb1fd4d7c27f11527addc40299c7c675f49d",
24- "image": "ghcr.io/my-org/my-repo/application@sha256:d31aa93410434ac9dcfc9179cac2cb1fd4d7c27f11527addc40299c7c675f49d",
25- "tags": [
26- "pr-63-5222075",
27- "pr-63"
28- ],
29- "annotations": {
30- "org.opencontainers.image.created": "2021-09-30T14:00:00Z",
31- "org.opencontainers.image.description": "Application image"
32- }
33- }
34- ```
35- value : ${{ steps.get-built-image.outputs.built-image }}
36-
3713inputs :
3814 oci-registry :
3915 description : " OCI registry where to pull and push images"
@@ -70,7 +46,7 @@ inputs:
7046 required : false
7147 platform :
7248 description : |
73- Platform to build for.
49+ Platform to build for. Example: `linux/amd64`.
7450 See https://github.com/docker/build-push-action#inputs.
7551 required : true
7652 context :
@@ -112,6 +88,31 @@ inputs:
11288 default : " gha"
11389 required : false
11490
91+ outputs :
92+ built-image :
93+ description : |
94+ Built image data.
95+ Example:
96+ ```json
97+ {
98+ "name": "application",
99+ "registry": "ghcr.io",
100+ "repository": "my-org/my-repo/application",
101+ "digest": "sha256:d31aa93410434ac9dcfc9179cac2cb1fd4d7c27f11527addc40299c7c675f49d",
102+ "image": "ghcr.io/my-org/my-repo/application@sha256:d31aa93410434ac9dcfc9179cac2cb1fd4d7c27f11527addc40299c7c675f49d",
103+ "tags": [
104+ "pr-63-5222075",
105+ "pr-63"
106+ ],
107+ "annotations": {
108+ "org.opencontainers.image.created": "2021-09-30T14:00:00Z",
109+ "org.opencontainers.image.description": "Application image"
110+ },
111+ "platform": "linux/amd64"
112+ }
113+ ```
114+ value : ${{ steps.get-built-image.outputs.built-image }}
115+
115116runs :
116117 using : " composite"
117118 steps :
@@ -142,6 +143,14 @@ runs:
142143 - id : get-docker-config
143144 shell : bash
144145 run : |
146+ DOCKERFILE_PATH="${{ github.workspace }}/${{ inputs.context }}/${{ inputs.dockerfile }}"
147+ if [ ! -f "$DOCKERFILE_PATH" ]; then
148+ echo "::error::Dockerfile not found at path: $DOCKERFILE_PATH"
149+ exit 1
150+ fi
151+ DOCKERFILE_PATH=$(realpath "$DOCKERFILE_PATH")
152+ echo "dockerfile-path=$DOCKERFILE_PATH" >> "$GITHUB_OUTPUT"
153+
145154 TAG_SUFFIX="-${{ steps.slugify-platform.outputs.result }}"
146155
147156 # Add tag suffix flavor
@@ -201,7 +210,24 @@ runs:
201210 fi
202211 fi
203212
204- - id : cache
213+ - if : steps.get-docker-config.outputs.docker-exists != 'true'
214+ uses : docker/setup-docker-action@b60f85385d03ac8acfca6d9996982511d8620a19 # v4.3.0
215+
216+ - if : steps.get-docker-config.outputs.platform-exists != 'true'
217+ uses : docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
218+ with :
219+ platforms : ${{ inputs.platform }}
220+
221+ - uses : docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
222+ with :
223+ # FIXME: upgrade version when available (https://github.com/docker/buildx/releases)
224+ version : v0.29.1
225+ # FIXME: upgrade version when available (https://hub.docker.com/r/moby/buildkit)
226+ driver-opts : |
227+ image=moby/buildkit:v0.25.1
228+
229+ # Caching setup
230+ - id : cache-arguments
205231 uses : int128/docker-build-cache-config-action@b3744816a5ba1ad9885b634d530b35ca90ece622 # v1.39.0
206232 with :
207233 image : ${{ steps.get-docker-config.outputs.cache-image }}
@@ -216,8 +242,8 @@ runs:
216242 uses : actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
217243 with :
218244 script : |
219- const cacheFrom = `${{ steps.cache.outputs.cache-from }}`;
220- const cacheTo = `${{ steps.cache.outputs.cache-to }}`;
245+ const cacheFrom = `${{ steps.cache-arguments .outputs.cache-from }}`;
246+ const cacheTo = `${{ steps.cache-arguments .outputs.cache-to }}`;
221247
222248 core.info(`Original cache-from: ${cacheFrom}`);
223249 core.info(`Original cache-to: ${cacheTo}`);
@@ -234,21 +260,19 @@ runs:
234260 core.setOutput('cache-from', transformedCacheFrom);
235261 core.setOutput('cache-to', transformedCacheTo);
236262
237- - if : steps.get-docker-config.outputs.docker-exists != 'true'
238- uses : docker/setup-docker-action@b60f85385d03ac8acfca6d9996982511d8620a19 # v4.3.0
239-
240- - if : steps.get-docker-config.outputs.platform-exists != 'true'
241- uses : docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
263+ - uses : actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
264+ id : cache
242265 with :
243- platforms : ${{ inputs.platform }}
266+ path : cache-mount
267+ key : cache-mount-${{ hashFiles(steps.get-docker-config.outputs.dockerfile-path) }}
244268
245- - uses : docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
269+ - name : Restore Docker cache mounts
270+ uses : reproducible-containers/buildkit-cache-dance@5b81f4d29dc8397a7d341dba3aeecc7ec54d6361 # v3.3.0
246271 with :
247- # FIXME: upgrade version when available (https://github.com/docker/buildx/releases)
248- version : v0.27.0
249- # FIXME: upgrade version when available (https://hub.docker.com/r/moby/buildkit)
250- driver-opts : |
251- image=moby/buildkit:v0.23.2
272+ builder : ${{ steps.setup-buildx.outputs.name }}
273+ cache-dir : cache-mount
274+ dockerfile : ${{ steps.get-docker-config.outputs.dockerfile-path }}
275+ skip-extraction : ${{ steps.cache.outputs.cache-hit }}
252276
253277 - uses : docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
254278 with :
@@ -262,19 +286,20 @@ runs:
262286 context : ${{ inputs.context }}
263287 build-args : ${{ inputs.build-args }}
264288 target : ${{ inputs.target }}
265- file : ${{ github.workspace }}/${{ inputs.context }}/${{ inputs .dockerfile }}
289+ file : ${{ steps.get-docker-config.outputs .dockerfile-path }}
266290 secrets : ${{ inputs.secrets }}
267291 secret-envs : ${{ inputs.secret-envs }}
268292 platforms : ${{ inputs.platform }}
269293 # FIXME: Remove 'inputs.cache-type == 'gha' && steps.transform-cache-gha.outputs.cache-from ||'
270294 # when https://github.com/int128/docker-build-cache-config-action/pull/1213 is merged
271- cache-from : ${{ inputs.cache-type == 'gha' && steps.transform-cache-gha.outputs.cache-from || steps.cache.outputs.cache-from }}
295+ cache-from : ${{ inputs.cache-type == 'gha' && steps.transform-cache-gha.outputs.cache-from || steps.cache-arguments .outputs.cache-from }}
272296 # FIXME: Remove 'inputs.cache-type == 'gha' && steps.transform-cache-gha.outputs.cache-to ||'
273297 # when https://github.com/int128/docker-build-cache-config-action/pull/1213 is merged
274- cache-to : ${{ inputs.cache-type == 'gha' && steps.transform-cache-gha.outputs.cache-to || steps.cache.outputs.cache-to }}
275- outputs : " type=image,push=true,push-by-digest=true,name-canonical=true,name=${{ steps.metadata.outputs.image }} "
298+ cache-to : ${{ inputs.cache-type == 'gha' && steps.transform-cache-gha.outputs.cache-to || steps.cache-arguments .outputs.cache-to }}
299+ outputs : " type=image,push=true,push-by-digest=true,name-canonical=true"
276300 labels : ${{ steps.metadata.outputs.labels }}
277301 annotations : ${{ steps.metadata.outputs.annotations }}
302+ tags : ${{ steps.metadata.outputs.image }}
278303
279304 - id : get-built-image
280305 uses : actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
@@ -286,10 +311,6 @@ runs:
286311 return;
287312 }
288313
289- if (builtMetadata["containerimage.digest"] === undefined) {
290- return core.setFailed('Given "metadata"."containerimage.digest" output is undefined.');
291- }
292-
293314 const name = `${{ inputs.image }}`;
294315 const image = `${{ steps.metadata.outputs.image }}`;
295316 const registryMatch = image.match(/^([^\/]+)\/.*/);
@@ -302,6 +323,37 @@ runs:
302323 .map(tag => tag.replace(/[^\/]+\/[^:]+:(.+)/,'$1').trim())
303324 .filter(tag => tag !== "");
304325
326+ let platform;
327+
328+ const buildxProvenance = builtMetadata?.["buildx.build.provenance"];
329+ if (buildxProvenance !== undefined) {
330+ platform = buildxProvenance.invocation?.environment?.platform;
331+ if (platform === undefined) {
332+ return core.setFailed('Given "metadata"."buildx.build.provenance"."invocation"."environment"."platform" output is undefined.');
333+ }
334+ if (typeof platform !== "string") {
335+ return core.setFailed('Given "metadata"."buildx.build.provenance"."invocation"."environment"."platform" is not a string.');
336+ }
337+ platform = platform.trim();
338+ if (platform === "") {
339+ return core.setFailed('Given "metadata"."buildx.build.provenance"."invocation"."environment"."platform" is empty.');
340+ }
341+ } else {
342+ const descriptor = builtMetadata?.["containerimage.descriptor"];
343+ if (descriptor?.["platform"] === undefined) {
344+ return core.setFailed('Given "metadata"."containerimage.descriptor"."platform" output is undefined.');
345+ }
346+ const platformData = descriptor["platform"];
347+ if (typeof platformData !== 'object' || platformData.os === undefined || platformData.architecture === undefined) {
348+ return core.setFailed('Given "metadata"."containerimage.descriptor"."platform" does not contain required "os" and "architecture" fields.');
349+ }
350+ platform = `${platformData.os}/${platformData.architecture}${platformData.variant ? `/${platformData.variant}` : ''}`;
351+ }
352+
353+ if (builtMetadata?.["containerimage.digest"] === undefined) {
354+ return core.setFailed('Given "metadata"."containerimage.digest" output is undefined.');
355+ }
356+
305357 const digests = builtMetadata["containerimage.digest"]
306358 .split(",")
307359 .map(digest => {
@@ -344,7 +396,8 @@ runs:
344396 registry,
345397 repository,
346398 image: imageWithDigest,
347- digest
399+ digest,
400+ platform
348401 };
349402
350403 core.setOutput("built-image", JSON.stringify(builtImage));
0 commit comments