From 3e4e4b69c16544645713519ed7bf7e10c0d028f6 Mon Sep 17 00:00:00 2001 From: Sylwester Piskozub Date: Fri, 24 Oct 2025 12:58:36 +0200 Subject: [PATCH 1/6] support multiple tools for cdx Signed-off-by: Sylwester Piskozub --- .../crafter/materials/cyclonedxjson.go | 14 +++++++ .../crafter/materials/cyclonedxjson_test.go | 17 ++++++++ .../sbom.cyclonedx-1.5-multiple-tools.json | 41 +++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 pkg/attestation/crafter/materials/testdata/sbom.cyclonedx-1.5-multiple-tools.json diff --git a/pkg/attestation/crafter/materials/cyclonedxjson.go b/pkg/attestation/crafter/materials/cyclonedxjson.go index 28d928565..514ade874 100644 --- a/pkg/attestation/crafter/materials/cyclonedxjson.go +++ b/pkg/attestation/crafter/materials/cyclonedxjson.go @@ -166,6 +166,13 @@ func (i *CyclonedxJSONCrafter) extractMetadata(m *api.Attestation_Material, meta i.logger.Debug().Err(err).Msg("error extracting main component from sbom, skipping...") } + // Extract all tools from the array + for idx, tool := range meta.Tools { + m.Annotations[fmt.Sprintf("chainloop.material.tool.%d.name", idx)] = tool.Name + m.Annotations[fmt.Sprintf("chainloop.material.tool.%d.version", idx)] = tool.Version + } + + // Maintain backward compatibility - keep legacy non-indexed keys for the first tool if len(meta.Tools) > 0 { m.Annotations[AnnotationToolNameKey] = meta.Tools[0].Name m.Annotations[AnnotationToolVersionKey] = meta.Tools[0].Version @@ -175,6 +182,13 @@ func (i *CyclonedxJSONCrafter) extractMetadata(m *api.Attestation_Material, meta i.logger.Debug().Err(err).Msg("error extracting main component from sbom, skipping...") } + // Extract all tools from the array + for idx, tool := range meta.Tools.Components { + m.Annotations[fmt.Sprintf("chainloop.material.tool.%d.name", idx)] = tool.Name + m.Annotations[fmt.Sprintf("chainloop.material.tool.%d.version", idx)] = tool.Version + } + + // Maintain backward compatibility - keep legacy non-indexed keys for the first tool if len(meta.Tools.Components) > 0 { m.Annotations[AnnotationToolNameKey] = meta.Tools.Components[0].Name m.Annotations[AnnotationToolVersionKey] = meta.Tools.Components[0].Version diff --git a/pkg/attestation/crafter/materials/cyclonedxjson_test.go b/pkg/attestation/crafter/materials/cyclonedxjson_test.go index 1cd0ef6b5..91e9e2a9c 100644 --- a/pkg/attestation/crafter/materials/cyclonedxjson_test.go +++ b/pkg/attestation/crafter/materials/cyclonedxjson_test.go @@ -156,6 +156,23 @@ func TestCyclonedxJSONCraft(t *testing.T) { "chainloop.material.sbom.vulnerabilities_report": "true", }, }, + { + name: "1.5 version with multiple tools", + filePath: "./testdata/sbom.cyclonedx-1.5-multiple-tools.json", + wantDigest: "sha256:56f82c99fb4740f952296705ceb2ee0c5c3c6a3309b35373d542d58878d65cd3", + wantFilename: "sbom.cyclonedx-1.5-multiple-tools.json", + wantMainComponent: "test-app", + wantMainComponentKind: "application", + wantMainComponentVersion: "1.0.0", + annotations: map[string]string{ + "chainloop.material.tool.name": "Hub", + "chainloop.material.tool.version": "2025.4.2", + "chainloop.material.tool.0.name": "Hub", + "chainloop.material.tool.0.version": "2025.4.2", + "chainloop.material.tool.1.name": "cyclonedx-core-java", + "chainloop.material.tool.1.version": "5.0.5", + }, + }, } schema := &contractAPI.CraftingSchema_Material{ diff --git a/pkg/attestation/crafter/materials/testdata/sbom.cyclonedx-1.5-multiple-tools.json b/pkg/attestation/crafter/materials/testdata/sbom.cyclonedx-1.5-multiple-tools.json new file mode 100644 index 000000000..06bd1010f --- /dev/null +++ b/pkg/attestation/crafter/materials/testdata/sbom.cyclonedx-1.5-multiple-tools.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.5", + "serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79", + "version": 1, + "metadata": { + "timestamp": "2025-09-28T07:00:46Z", + "tools": { + "components": [ + { + "type": "application", + "author": "Black Duck", + "name": "Hub", + "version": "2025.4.2" + }, + { + "type": "library", + "author": "CycloneDX", + "name": "cyclonedx-core-java", + "version": "5.0.5" + } + ] + }, + "component": { + "bom-ref": "test-component", + "type": "application", + "name": "test-app", + "version": "1.0.0" + } + }, + "components": [ + { + "bom-ref": "pkg:golang/example.com/test@v1.0.0", + "type": "library", + "name": "example.com/test", + "version": "v1.0.0", + "purl": "pkg:golang/example.com/test@v1.0.0" + } + ] +} From e0a81b0d5b7a07fff9289f689856a6a9d08bf6a2 Mon Sep 17 00:00:00 2001 From: Sylwester Piskozub Date: Fri, 24 Oct 2025 16:04:58 +0200 Subject: [PATCH 2/6] add support for spdx Signed-off-by: Sylwester Piskozub --- .../crafter/materials/cyclonedxjson.go | 8 ++-- .../crafter/materials/materials.go | 10 ++++ pkg/attestation/crafter/materials/spdxjson.go | 31 +++++++++---- .../crafter/materials/spdxjson_test.go | 46 ++++++++++++++++--- 4 files changed, 76 insertions(+), 19 deletions(-) diff --git a/pkg/attestation/crafter/materials/cyclonedxjson.go b/pkg/attestation/crafter/materials/cyclonedxjson.go index 514ade874..8bc581680 100644 --- a/pkg/attestation/crafter/materials/cyclonedxjson.go +++ b/pkg/attestation/crafter/materials/cyclonedxjson.go @@ -168,8 +168,8 @@ func (i *CyclonedxJSONCrafter) extractMetadata(m *api.Attestation_Material, meta // Extract all tools from the array for idx, tool := range meta.Tools { - m.Annotations[fmt.Sprintf("chainloop.material.tool.%d.name", idx)] = tool.Name - m.Annotations[fmt.Sprintf("chainloop.material.tool.%d.version", idx)] = tool.Version + m.Annotations[AnnotationToolIndexedName(idx)] = tool.Name + m.Annotations[AnnotationToolIndexedVersion(idx)] = tool.Version } // Maintain backward compatibility - keep legacy non-indexed keys for the first tool @@ -184,8 +184,8 @@ func (i *CyclonedxJSONCrafter) extractMetadata(m *api.Attestation_Material, meta // Extract all tools from the array for idx, tool := range meta.Tools.Components { - m.Annotations[fmt.Sprintf("chainloop.material.tool.%d.name", idx)] = tool.Name - m.Annotations[fmt.Sprintf("chainloop.material.tool.%d.version", idx)] = tool.Version + m.Annotations[AnnotationToolIndexedName(idx)] = tool.Name + m.Annotations[AnnotationToolIndexedVersion(idx)] = tool.Version } // Maintain backward compatibility - keep legacy non-indexed keys for the first tool diff --git a/pkg/attestation/crafter/materials/materials.go b/pkg/attestation/crafter/materials/materials.go index 3d0941683..bf895049b 100644 --- a/pkg/attestation/crafter/materials/materials.go +++ b/pkg/attestation/crafter/materials/materials.go @@ -37,6 +37,16 @@ import ( const AnnotationToolNameKey = "chainloop.material.tool.name" const AnnotationToolVersionKey = "chainloop.material.tool.version" +// AnnotationToolIndexedName returns the annotation key for an indexed tool name +func AnnotationToolIndexedName(idx int) string { + return fmt.Sprintf("chainloop.material.tool.%d.name", idx) +} + +// AnnotationToolIndexedVersion returns the annotation key for an indexed tool version +func AnnotationToolIndexedVersion(idx int) string { + return fmt.Sprintf("chainloop.material.tool.%d.version", idx) +} + var ( // ErrInvalidMaterialType is returned when the provided material type // is not from the kind we are expecting diff --git a/pkg/attestation/crafter/materials/spdxjson.go b/pkg/attestation/crafter/materials/spdxjson.go index 1809e134b..c01f1c043 100644 --- a/pkg/attestation/crafter/materials/spdxjson.go +++ b/pkg/attestation/crafter/materials/spdxjson.go @@ -71,19 +71,34 @@ func (i *SPDXJSONCrafter) Craft(ctx context.Context, filePath string) (*api.Atte } func (i *SPDXJSONCrafter) injectAnnotations(m *api.Attestation_Material, doc *spdx.Document) { + m.Annotations = make(map[string]string) + + // Extract all tools from the creators array + toolIdx := 0 for _, c := range doc.CreationInfo.Creators { if c.CreatorType == "Tool" { - m.Annotations = make(map[string]string) - m.Annotations[AnnotationToolNameKey] = c.Creator - // try to extract the tool name and version // e.g. "myTool-1.0.0" - parts := strings.SplitN(c.Creator, "-", 2) - if len(parts) == 2 { - m.Annotations[AnnotationToolNameKey] = parts[0] - m.Annotations[AnnotationToolVersionKey] = parts[1] + name, version := c.Creator, "" + if parts := strings.SplitN(c.Creator, "-", 2); len(parts) == 2 { + name, version = parts[0], parts[1] + } + + // Store indexed annotations for all tools + m.Annotations[AnnotationToolIndexedName(toolIdx)] = name + if version != "" { + m.Annotations[AnnotationToolIndexedVersion(toolIdx)] = version } - break + + // Maintain backward compatibility - legacy keys for first tool + if toolIdx == 0 { + m.Annotations[AnnotationToolNameKey] = name + if version != "" { + m.Annotations[AnnotationToolVersionKey] = version + } + } + + toolIdx++ } } } diff --git a/pkg/attestation/crafter/materials/spdxjson_test.go b/pkg/attestation/crafter/materials/spdxjson_test.go index 7882d7fa7..9b077cf29 100644 --- a/pkg/attestation/crafter/materials/spdxjson_test.go +++ b/pkg/attestation/crafter/materials/spdxjson_test.go @@ -66,9 +66,12 @@ func TestNewSPDXJSONCrafter(t *testing.T) { func TestSPDXJSONCraft(t *testing.T) { testCases := []struct { - name string - filePath string - wantErr string + name string + filePath string + wantErr string + wantDigest string + wantFilename string + annotations map[string]string }{ { name: "invalid sbom format", @@ -86,8 +89,30 @@ func TestSPDXJSONCraft(t *testing.T) { wantErr: "unexpected material type", }, { - name: "valid artifact type", - filePath: "./testdata/sbom-spdx.json", + name: "valid artifact type", + filePath: "./testdata/sbom-spdx.json", + wantDigest: "sha256:fe2636fb6c698a29a315278b762b2000efd5959afe776ee4f79f1ed523365a33", + wantFilename: "sbom-spdx.json", + annotations: map[string]string{ + "chainloop.material.tool.name": "syft", + "chainloop.material.tool.version": "0.73.0", + "chainloop.material.tool.0.name": "syft", + "chainloop.material.tool.0.version": "0.73.0", + }, + }, + { + name: "multiple tools", + filePath: "./testdata/sbom-spdx-multiple-tools.json", + wantDigest: "sha256:c1a61566c7c0224ac02ad9cd21d90234e5a71de26971e33df2205c1a2eb319fc", + wantFilename: "sbom-spdx-multiple-tools.json", + annotations: map[string]string{ + "chainloop.material.tool.name": "spdxgen", + "chainloop.material.tool.version": "1.0.0", + "chainloop.material.tool.0.name": "spdxgen", + "chainloop.material.tool.0.version": "1.0.0", + "chainloop.material.tool.1.name": "scanner", + "chainloop.material.tool.1.version": "2.1.5", + }, }, } @@ -123,10 +148,17 @@ func TestSPDXJSONCraft(t *testing.T) { assert.Equal(contractAPI.CraftingSchema_Material_SBOM_SPDX_JSON.String(), got.MaterialType.String()) assert.True(got.UploadedToCas) - // // The result includes the digest reference + // The result includes the digest reference assert.Equal(got.GetArtifact(), &attestationApi.Attestation_Material_Artifact{ - Id: "test", Digest: "sha256:fe2636fb6c698a29a315278b762b2000efd5959afe776ee4f79f1ed523365a33", Name: "sbom-spdx.json", + Id: "test", Digest: tc.wantDigest, Name: tc.wantFilename, }) + + // Validate annotations if specified + if tc.annotations != nil { + for k, v := range tc.annotations { + assert.Equal(v, got.Annotations[k]) + } + } }) } } From 483c2d31856804c5c6344573b5286e617f76ebd8 Mon Sep 17 00:00:00 2001 From: Sylwester Piskozub Date: Fri, 24 Oct 2025 16:10:02 +0200 Subject: [PATCH 3/6] missing test file Signed-off-by: Sylwester Piskozub --- .../testdata/sbom-spdx-multiple-tools.json | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 pkg/attestation/crafter/materials/testdata/sbom-spdx-multiple-tools.json diff --git a/pkg/attestation/crafter/materials/testdata/sbom-spdx-multiple-tools.json b/pkg/attestation/crafter/materials/testdata/sbom-spdx-multiple-tools.json new file mode 100644 index 000000000..8f9e2a44a --- /dev/null +++ b/pkg/attestation/crafter/materials/testdata/sbom-spdx-multiple-tools.json @@ -0,0 +1,27 @@ +{ + "spdxVersion": "SPDX-2.3", + "dataLicense": "CC0-1.0", + "SPDXID": "SPDXRef-DOCUMENT", + "name": "test-multiple-tools", + "documentNamespace": "https://example.com/test/multiple-tools", + "creationInfo": { + "licenseListVersion": "3.20", + "creators": [ + "Organization: Example Corp", + "Tool: spdxgen-1.0.0", + "Tool: scanner-2.1.5" + ], + "created": "2024-01-01T10:00:00Z" + }, + "packages": [ + { + "name": "example-package", + "SPDXID": "SPDXRef-Package-example", + "versionInfo": "1.0.0", + "downloadLocation": "NOASSERTION", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION" + } + ] +} From ff320da80cca0090905d48aec93c22326d4d807c Mon Sep 17 00:00:00 2001 From: Sylwester Piskozub Date: Mon, 27 Oct 2025 13:10:10 +0100 Subject: [PATCH 4/6] use array for versions Signed-off-by: Sylwester Piskozub --- .../crafter/materials/cyclonedxjson.go | 36 ++++++++++--------- .../crafter/materials/cyclonedxjson_test.go | 9 ++--- .../crafter/materials/materials.go | 32 +++++++++++++---- pkg/attestation/crafter/materials/spdxjson.go | 25 +++++-------- .../crafter/materials/spdxjson_test.go | 16 ++++----- 5 files changed, 64 insertions(+), 54 deletions(-) diff --git a/pkg/attestation/crafter/materials/cyclonedxjson.go b/pkg/attestation/crafter/materials/cyclonedxjson.go index 8bc581680..658d516cb 100644 --- a/pkg/attestation/crafter/materials/cyclonedxjson.go +++ b/pkg/attestation/crafter/materials/cyclonedxjson.go @@ -166,33 +166,37 @@ func (i *CyclonedxJSONCrafter) extractMetadata(m *api.Attestation_Material, meta i.logger.Debug().Err(err).Msg("error extracting main component from sbom, skipping...") } - // Extract all tools from the array - for idx, tool := range meta.Tools { - m.Annotations[AnnotationToolIndexedName(idx)] = tool.Name - m.Annotations[AnnotationToolIndexedVersion(idx)] = tool.Version + // Extract all tools and set annotations + var tools []Tool + for _, tool := range meta.Tools { + tools = append(tools, Tool{Name: tool.Name, Version: tool.Version}) } + SetToolsAnnotation(m, tools) - // Maintain backward compatibility - keep legacy non-indexed keys for the first tool - if len(meta.Tools) > 0 { - m.Annotations[AnnotationToolNameKey] = meta.Tools[0].Name - m.Annotations[AnnotationToolVersionKey] = meta.Tools[0].Version + // Maintain backward compatibility - keep legacy keys for the first tool + if len(tools) > 0 { + m.Annotations[AnnotationToolNameKey] = tools[0].Name + m.Annotations[AnnotationToolVersionKey] = tools[0].Version } + case *cyclonedxMetadataV15: if err := i.extractMainComponent(m, &meta.Component); err != nil { i.logger.Debug().Err(err).Msg("error extracting main component from sbom, skipping...") } - // Extract all tools from the array - for idx, tool := range meta.Tools.Components { - m.Annotations[AnnotationToolIndexedName(idx)] = tool.Name - m.Annotations[AnnotationToolIndexedVersion(idx)] = tool.Version + // Extract all tools and set annotations + var tools []Tool + for _, tool := range meta.Tools.Components { + tools = append(tools, Tool{Name: tool.Name, Version: tool.Version}) } + SetToolsAnnotation(m, tools) - // Maintain backward compatibility - keep legacy non-indexed keys for the first tool - if len(meta.Tools.Components) > 0 { - m.Annotations[AnnotationToolNameKey] = meta.Tools.Components[0].Name - m.Annotations[AnnotationToolVersionKey] = meta.Tools.Components[0].Version + // Maintain backward compatibility - keep legacy keys for the first tool + if len(tools) > 0 { + m.Annotations[AnnotationToolNameKey] = tools[0].Name + m.Annotations[AnnotationToolVersionKey] = tools[0].Version } + default: i.logger.Debug().Msg("unknown metadata version") } diff --git a/pkg/attestation/crafter/materials/cyclonedxjson_test.go b/pkg/attestation/crafter/materials/cyclonedxjson_test.go index 91e9e2a9c..401fb8a29 100644 --- a/pkg/attestation/crafter/materials/cyclonedxjson_test.go +++ b/pkg/attestation/crafter/materials/cyclonedxjson_test.go @@ -165,12 +165,9 @@ func TestCyclonedxJSONCraft(t *testing.T) { wantMainComponentKind: "application", wantMainComponentVersion: "1.0.0", annotations: map[string]string{ - "chainloop.material.tool.name": "Hub", - "chainloop.material.tool.version": "2025.4.2", - "chainloop.material.tool.0.name": "Hub", - "chainloop.material.tool.0.version": "2025.4.2", - "chainloop.material.tool.1.name": "cyclonedx-core-java", - "chainloop.material.tool.1.version": "5.0.5", + "chainloop.material.tool.name": "Hub", + "chainloop.material.tool.version": "2025.4.2", + "chainloop.material.tools": `["Hub@2025.4.2","cyclonedx-core-java@5.0.5"]`, }, }, } diff --git a/pkg/attestation/crafter/materials/materials.go b/pkg/attestation/crafter/materials/materials.go index bf895049b..eca1fdf1f 100644 --- a/pkg/attestation/crafter/materials/materials.go +++ b/pkg/attestation/crafter/materials/materials.go @@ -17,6 +17,7 @@ package materials import ( "context" + "encoding/json" "errors" "fmt" "io" @@ -36,15 +37,34 @@ import ( const AnnotationToolNameKey = "chainloop.material.tool.name" const AnnotationToolVersionKey = "chainloop.material.tool.version" +const AnnotationToolsKey = "chainloop.material.tools" -// AnnotationToolIndexedName returns the annotation key for an indexed tool name -func AnnotationToolIndexedName(idx int) string { - return fmt.Sprintf("chainloop.material.tool.%d.name", idx) +// Tool represents a tool with name and version +type Tool struct { + Name string + Version string } -// AnnotationToolIndexedVersion returns the annotation key for an indexed tool version -func AnnotationToolIndexedVersion(idx int) string { - return fmt.Sprintf("chainloop.material.tool.%d.version", idx) +// SetToolsAnnotations sets the tools annotation as a JSON array in "name@version" format +func SetToolsAnnotation(m *api.Attestation_Material, tools []Tool) { + if len(tools) == 0 { + return + } + + // Build array of "name@version" strings + var toolStrings []string + for _, tool := range tools { + toolStr := tool.Name + if tool.Version != "" { + toolStr = fmt.Sprintf("%s@%s", tool.Name, tool.Version) + } + toolStrings = append(toolStrings, toolStr) + } + + // Marshal to JSON array + if toolsJSON, err := json.Marshal(toolStrings); err == nil { + m.Annotations[AnnotationToolsKey] = string(toolsJSON) + } } var ( diff --git a/pkg/attestation/crafter/materials/spdxjson.go b/pkg/attestation/crafter/materials/spdxjson.go index c01f1c043..c359b4ce5 100644 --- a/pkg/attestation/crafter/materials/spdxjson.go +++ b/pkg/attestation/crafter/materials/spdxjson.go @@ -74,7 +74,7 @@ func (i *SPDXJSONCrafter) injectAnnotations(m *api.Attestation_Material, doc *sp m.Annotations = make(map[string]string) // Extract all tools from the creators array - toolIdx := 0 + var tools []Tool for _, c := range doc.CreationInfo.Creators { if c.CreatorType == "Tool" { // try to extract the tool name and version @@ -83,22 +83,15 @@ func (i *SPDXJSONCrafter) injectAnnotations(m *api.Attestation_Material, doc *sp if parts := strings.SplitN(c.Creator, "-", 2); len(parts) == 2 { name, version = parts[0], parts[1] } + tools = append(tools, Tool{Name: name, Version: version}) + } + } - // Store indexed annotations for all tools - m.Annotations[AnnotationToolIndexedName(toolIdx)] = name - if version != "" { - m.Annotations[AnnotationToolIndexedVersion(toolIdx)] = version - } - - // Maintain backward compatibility - legacy keys for first tool - if toolIdx == 0 { - m.Annotations[AnnotationToolNameKey] = name - if version != "" { - m.Annotations[AnnotationToolVersionKey] = version - } - } + SetToolsAnnotation(m, tools) - toolIdx++ - } + // Maintain backward compatibility - keep legacy keys for the first tool + if len(tools) > 0 { + m.Annotations[AnnotationToolNameKey] = tools[0].Name + m.Annotations[AnnotationToolVersionKey] = tools[0].Version } } diff --git a/pkg/attestation/crafter/materials/spdxjson_test.go b/pkg/attestation/crafter/materials/spdxjson_test.go index 9b077cf29..66c55ebae 100644 --- a/pkg/attestation/crafter/materials/spdxjson_test.go +++ b/pkg/attestation/crafter/materials/spdxjson_test.go @@ -94,10 +94,9 @@ func TestSPDXJSONCraft(t *testing.T) { wantDigest: "sha256:fe2636fb6c698a29a315278b762b2000efd5959afe776ee4f79f1ed523365a33", wantFilename: "sbom-spdx.json", annotations: map[string]string{ - "chainloop.material.tool.name": "syft", - "chainloop.material.tool.version": "0.73.0", - "chainloop.material.tool.0.name": "syft", - "chainloop.material.tool.0.version": "0.73.0", + "chainloop.material.tool.name": "syft", + "chainloop.material.tool.version": "0.73.0", + "chainloop.material.tools": `["syft@0.73.0"]`, }, }, { @@ -106,12 +105,9 @@ func TestSPDXJSONCraft(t *testing.T) { wantDigest: "sha256:c1a61566c7c0224ac02ad9cd21d90234e5a71de26971e33df2205c1a2eb319fc", wantFilename: "sbom-spdx-multiple-tools.json", annotations: map[string]string{ - "chainloop.material.tool.name": "spdxgen", - "chainloop.material.tool.version": "1.0.0", - "chainloop.material.tool.0.name": "spdxgen", - "chainloop.material.tool.0.version": "1.0.0", - "chainloop.material.tool.1.name": "scanner", - "chainloop.material.tool.1.version": "2.1.5", + "chainloop.material.tool.name": "spdxgen", + "chainloop.material.tool.version": "1.0.0", + "chainloop.material.tools": `["spdxgen@1.0.0","scanner@2.1.5"]`, }, }, } From 29aa93ed273951d9ccf765fcfc1193334852d9c8 Mon Sep 17 00:00:00 2001 From: Sylwester Piskozub Date: Mon, 27 Oct 2025 13:15:48 +0100 Subject: [PATCH 5/6] lint Signed-off-by: Sylwester Piskozub --- pkg/attestation/crafter/materials/materials.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/attestation/crafter/materials/materials.go b/pkg/attestation/crafter/materials/materials.go index eca1fdf1f..370212a06 100644 --- a/pkg/attestation/crafter/materials/materials.go +++ b/pkg/attestation/crafter/materials/materials.go @@ -52,7 +52,7 @@ func SetToolsAnnotation(m *api.Attestation_Material, tools []Tool) { } // Build array of "name@version" strings - var toolStrings []string + toolStrings := make([]string, 0, len(tools)) for _, tool := range tools { toolStr := tool.Name if tool.Version != "" { From fe354c7828c8acc6b9c8c4c7aaf11e6f36d1f21d Mon Sep 17 00:00:00 2001 From: Sylwester Piskozub Date: Mon, 27 Oct 2025 15:49:15 +0100 Subject: [PATCH 6/6] hide legacy tool annotations from output Signed-off-by: Sylwester Piskozub --- app/cli/cmd/attestation_add.go | 4 ++++ app/cli/cmd/attestation_status.go | 7 +++++++ pkg/attestation/crafter/materials/materials.go | 5 +++++ 3 files changed, 16 insertions(+) diff --git a/app/cli/cmd/attestation_add.go b/app/cli/cmd/attestation_add.go index f08b4f24a..5b223376e 100644 --- a/app/cli/cmd/attestation_add.go +++ b/app/cli/cmd/attestation_add.go @@ -29,6 +29,7 @@ import ( "github.com/chainloop-dev/chainloop/app/cli/cmd/output" "github.com/chainloop-dev/chainloop/app/cli/pkg/action" schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" + "github.com/chainloop-dev/chainloop/pkg/attestation/crafter/materials" "github.com/chainloop-dev/chainloop/pkg/resourceloader" ) @@ -194,6 +195,9 @@ func displayMaterialInfo(status *action.AttestationStatusMaterial, policyEvaluat if len(status.Material.Annotations) > 0 { mt.AppendRow(table.Row{"Annotations", "------"}) for _, a := range status.Material.Annotations { + if materials.IsLegacyAnnotation(a.Name) { + continue + } value := a.Value if value == "" { value = NotSet diff --git a/app/cli/cmd/attestation_status.go b/app/cli/cmd/attestation_status.go index af57f3904..9dc88df94 100644 --- a/app/cli/cmd/attestation_status.go +++ b/app/cli/cmd/attestation_status.go @@ -30,6 +30,7 @@ import ( "github.com/chainloop-dev/chainloop/app/cli/cmd/output" "github.com/chainloop-dev/chainloop/app/cli/pkg/action" + "github.com/chainloop-dev/chainloop/pkg/attestation/crafter/materials" "github.com/chainloop-dev/chainloop/pkg/attestation/renderer/chainloop" ) @@ -114,6 +115,9 @@ func attestationStatusTableOutput(status *action.AttestationStatusResult, w io.W if len(status.Annotations) > 0 { gt.AppendRow(table.Row{"Annotations", "------"}) for _, a := range status.Annotations { + if materials.IsLegacyAnnotation(a.Name) { + continue + } value := a.Value if value == "" { value = NotSet @@ -220,6 +224,9 @@ func materialsTable(status *action.AttestationStatusResult, w io.Writer, full bo if len(m.Annotations) > 0 { mt.AppendRow(table.Row{"Annotations", "------"}) for _, a := range m.Annotations { + if materials.IsLegacyAnnotation(a.Name) { + continue + } value := a.Value if value == "" { value = NotSet diff --git a/pkg/attestation/crafter/materials/materials.go b/pkg/attestation/crafter/materials/materials.go index 370212a06..98349377f 100644 --- a/pkg/attestation/crafter/materials/materials.go +++ b/pkg/attestation/crafter/materials/materials.go @@ -39,6 +39,11 @@ const AnnotationToolNameKey = "chainloop.material.tool.name" const AnnotationToolVersionKey = "chainloop.material.tool.version" const AnnotationToolsKey = "chainloop.material.tools" +// IsLegacyAnnotation returns true if the annotation key is a legacy annotation +func IsLegacyAnnotation(key string) bool { + return key == AnnotationToolNameKey || key == AnnotationToolVersionKey +} + // Tool represents a tool with name and version type Tool struct { Name string