From bfc74cf338aa1da2f63b9297eaddb396e0ed3632 Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Wed, 8 Jan 2025 15:28:06 +0100 Subject: [PATCH] bake: composable attributes for attestations support Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- __tests__/.fixtures/bake-03-default.json | 10 +++++++ __tests__/.fixtures/bake-03.hcl | 4 +++ src/buildx/bake.ts | 35 +++++++++++++++++++++++- src/types/buildx/bake.ts | 7 ++++- 4 files changed, 54 insertions(+), 2 deletions(-) diff --git a/__tests__/.fixtures/bake-03-default.json b/__tests__/.fixtures/bake-03-default.json index 00de99f..b251fa7 100644 --- a/__tests__/.fixtures/bake-03-default.json +++ b/__tests__/.fixtures/bake-03-default.json @@ -3,6 +3,16 @@ "default": { "context": ".", "dockerfile": "Dockerfile", + "attest": [ + { + "mode": "max", + "type": "provenance" + }, + { + "disabled": "true", + "type": "sbom" + } + ], "cache-from": [ { "scope": "build", diff --git a/__tests__/.fixtures/bake-03.hcl b/__tests__/.fixtures/bake-03.hcl index 20140d5..260da75 100644 --- a/__tests__/.fixtures/bake-03.hcl +++ b/__tests__/.fixtures/bake-03.hcl @@ -13,6 +13,10 @@ // limitations under the License. target "default" { + attest = [ + "type=provenance,mode=max", + "type=sbom,disabled=true", + ] cache-from = [ "type=gha,scope=build", "user/repo:cache", diff --git a/src/buildx/bake.ts b/src/buildx/bake.ts index 00e4c59..7a5efdd 100644 --- a/src/buildx/bake.ts +++ b/src/buildx/bake.ts @@ -24,7 +24,7 @@ import {Exec} from '../exec'; import {Util} from '../util'; import {ExecOptions} from '@actions/exec'; -import {BakeDefinition, CacheEntry, ExportEntry, SecretEntry, SSHEntry} from '../types/buildx/bake'; +import {AttestEntry, BakeDefinition, CacheEntry, ExportEntry, SecretEntry, SSHEntry} from '../types/buildx/bake'; import {BuildMetadata} from '../types/buildx/build'; import {VertexWarning} from '../types/buildkit/client'; @@ -183,6 +183,11 @@ export class Bake { // convert to composable attributes: https://github.com/docker/buildx/pull/2758 for (const name in definition.target) { const target = definition.target[name]; + if (target['attest'] && Array.isArray(target['attest'])) { + target['attest'] = target['attest'].map((item: string | AttestEntry): AttestEntry => { + return Bake.parseAttestEntry(item); + }); + } if (target['cache-from'] && Array.isArray(target['cache-from'])) { target['cache-from'] = target['cache-from'].map((item: string | CacheEntry): CacheEntry => { return Bake.parseCacheEntry(item); @@ -213,6 +218,34 @@ export class Bake { return definition; } + private static parseAttestEntry(item: AttestEntry | string): AttestEntry { + if (typeof item !== 'string') { + return item; + } + + const attestEntry: AttestEntry = {type: ''}; + const fields = parse(item, { + relaxColumnCount: true, + skipEmptyLines: true + })[0]; + + for (const field of fields) { + const [key, value] = field + .toString() + .split(/(?<=^[^=]+?)=/) + .map((item: string) => item.trim()); + switch (key) { + case 'type': + attestEntry.type = value; + break; + default: + attestEntry[key] = value; + } + } + + return attestEntry; + } + private static parseCacheEntry(item: CacheEntry | string): CacheEntry { if (typeof item !== 'string') { return item; diff --git a/src/types/buildx/bake.ts b/src/types/buildx/bake.ts index b6ec047..9f647c0 100644 --- a/src/types/buildx/bake.ts +++ b/src/types/buildx/bake.ts @@ -27,7 +27,7 @@ export interface Group { export interface Target { description?: string; args?: Record; - attest?: Array; + attest?: Array | Array; 'cache-from'?: Array | Array; 'cache-to'?: Array | Array; call?: string; @@ -50,6 +50,11 @@ export interface Target { ulimits?: Array; } +export interface AttestEntry { + type: string; + [key: string]: string; +} + export interface CacheEntry { type: string; [key: string]: string;