From c91d8b1fbba4d067c8306d077fe3fc3412c18b4c Mon Sep 17 00:00:00 2001 From: Thomas Schafer Date: Thu, 20 Nov 2025 16:06:39 +0000 Subject: [PATCH 1/4] chore: pass target file out of plugin --- internal/mocks/uvclient.go | 19 +++++++++++++++---- internal/uv/uv_plugin.go | 4 ++-- internal/uv/uvclient.go | 12 +++++++++--- internal/uv/uvclient_test.go | 2 +- pkg/depgraph/sbom_resolution.go | 14 +++++++------- pkg/depgraph/sbom_resolution_test.go | 20 +++++++++++++------- pkg/sca_plugin/interface.go | 1 + 7 files changed, 48 insertions(+), 24 deletions(-) diff --git a/internal/mocks/uvclient.go b/internal/mocks/uvclient.go index f1cf591..6015e15 100644 --- a/internal/mocks/uvclient.go +++ b/internal/mocks/uvclient.go @@ -1,18 +1,27 @@ package mocks -import "github.com/rs/zerolog" +import ( + "github.com/rs/zerolog" + + "github.com/snyk/cli-extension-dep-graph/internal/uv" + scaplugin "github.com/snyk/cli-extension-dep-graph/pkg/sca_plugin" +) // MockUVClient is a mock implementation of UVClient for testing type MockUVClient struct { - ExportSBOMFunc func(inputDir string) ([]byte, error) + ExportSBOMFunc func(inputDir string) (*scaplugin.Finding, error) ShouldExportSBOMFunc func(inputDir string, logger *zerolog.Logger) bool } -func (m *MockUVClient) ExportSBOM(inputDir string) ([]byte, error) { +func (m *MockUVClient) ExportSBOM(inputDir string) (*scaplugin.Finding, error) { if m.ExportSBOMFunc != nil { return m.ExportSBOMFunc(inputDir) } - return []byte(`{"mock":"sbom"}`), nil + return &scaplugin.Finding{ + Sbom: []byte(`{"mock":"sbom"}`), + TargetFile: "", + FilesProcessed: []string{}, + }, nil } func (m *MockUVClient) ShouldExportSBOM(inputDir string, logger *zerolog.Logger) bool { @@ -21,3 +30,5 @@ func (m *MockUVClient) ShouldExportSBOM(inputDir string, logger *zerolog.Logger) } return true } + +var _ uv.Client = (*MockUVClient)(nil) diff --git a/internal/uv/uv_plugin.go b/internal/uv/uv_plugin.go index 695008a..1eec8be 100644 --- a/internal/uv/uv_plugin.go +++ b/internal/uv/uv_plugin.go @@ -22,9 +22,9 @@ func (p Plugin) BuildFindingsFromDir(inputDir string, _ scaplugin.Options, logge return []scaplugin.Finding{}, nil } - sbomOutput, err := p.client.ExportSBOM(inputDir) + finding, err := p.client.ExportSBOM(inputDir) if err != nil { return []scaplugin.Finding{}, fmt.Errorf("failed to export SBOM using uv: %w", err) } - return []scaplugin.Finding{{Sbom: sbomOutput, FilesProcessed: []string{}}}, nil + return []scaplugin.Finding{*finding}, nil } diff --git a/internal/uv/uvclient.go b/internal/uv/uvclient.go index 45f7bc2..ce22052 100644 --- a/internal/uv/uvclient.go +++ b/internal/uv/uvclient.go @@ -4,15 +4,17 @@ import ( "encoding/json" "fmt" "os/exec" + "path" "regexp" "strconv" "strings" "github.com/rs/zerolog" + scaplugin "github.com/snyk/cli-extension-dep-graph/pkg/sca_plugin" ) type Client interface { - ExportSBOM(inputDir string) ([]byte, error) + ExportSBOM(inputDir string) (*scaplugin.Finding, error) ShouldExportSBOM(inputDir string, logger *zerolog.Logger) bool } @@ -40,7 +42,7 @@ func NewUvClientWithExecutor(uvBinary string, executor cmdExecutor) Client { } // exportSBOM exports an SBOM in CycloneDX format using uv. -func (c client) ExportSBOM(inputDir string) ([]byte, error) { +func (c client) ExportSBOM(inputDir string) (*scaplugin.Finding, error) { output, err := c.executor.Execute(c.uvBinary, inputDir, "export", "--format", "cyclonedx1.5", "--frozen", "--preview") if err != nil { return nil, fmt.Errorf("failed to execute uv export: %w", err) @@ -50,7 +52,11 @@ func (c client) ExportSBOM(inputDir string) ([]byte, error) { return nil, err } - return output, nil + return &scaplugin.Finding{ + Sbom: output, + FilesProcessed: []string{}, + TargetFile: path.Join(inputDir, UvLockFileName), + }, nil } // Verifies that the SBOM is valid JSON and has a root component. diff --git a/internal/uv/uvclient_test.go b/internal/uv/uvclient_test.go index 8087456..0415ba2 100644 --- a/internal/uv/uvclient_test.go +++ b/internal/uv/uvclient_test.go @@ -45,7 +45,7 @@ func TestUVClient_ExportSBOM_Success(t *testing.T) { result, err := client.ExportSBOM("/test/dir") assert.NoError(t, err) - assert.JSONEq(t, validSBOM, string(result)) + assert.JSONEq(t, validSBOM, string(result.Sbom)) } func TestUVClient_ExportSBOM_Error(t *testing.T) { diff --git a/pkg/depgraph/sbom_resolution.go b/pkg/depgraph/sbom_resolution.go index 7cdd121..81cf014 100644 --- a/pkg/depgraph/sbom_resolution.go +++ b/pkg/depgraph/sbom_resolution.go @@ -81,7 +81,7 @@ func handleSBOMResolutionDI( // Convert SBOMs to workflow.Data workflowData := []workflow.Data{} for _, f := range findings { // Could be parallelised in future - data, err := sbomToWorkflowData(f.Sbom, snykClient, logger, remoteRepoURL) + data, err := sbomToWorkflowData(f, snykClient, logger, remoteRepoURL) if err != nil { return nil, fmt.Errorf("error converting SBOM: %w", err) } @@ -150,8 +150,8 @@ func executeLegacyWorkflow( return nil, fmt.Errorf("error handling legacy workflow: %w", err) } -func sbomToWorkflowData(sbomOutput []byte, snykClient *snykclient.SnykClient, logger *zerolog.Logger, remoteRepoURL string) ([]workflow.Data, error) { - sbomReader := bytes.NewReader(sbomOutput) +func sbomToWorkflowData(finding scaplugin.Finding, snykClient *snykclient.SnykClient, logger *zerolog.Logger, remoteRepoURL string) ([]workflow.Data, error) { + sbomReader := bytes.NewReader(finding.Sbom) scans, warnings, err := snykClient.SBOMConvert(context.Background(), logger, sbomReader, remoteRepoURL) if err != nil { @@ -160,7 +160,7 @@ func sbomToWorkflowData(sbomOutput []byte, snykClient *snykclient.SnykClient, lo logger.Printf("Successfully converted SBOM, warning(s): %d\n", len(warnings)) - depGraphsData, err := extractDepGraphsFromScans(scans) + depGraphsData, err := extractDepGraphsFromScans(scans, finding.TargetFile) if err != nil { return nil, fmt.Errorf("failed to extract depgraphs from scan results: %w", err) } @@ -171,7 +171,7 @@ func sbomToWorkflowData(sbomOutput []byte, snykClient *snykclient.SnykClient, lo return depGraphsData, nil } -func extractDepGraphsFromScans(scans []*snykclient.ScanResult) ([]workflow.Data, error) { +func extractDepGraphsFromScans(scans []*snykclient.ScanResult, targetFile string) ([]workflow.Data, error) { var depGraphList []workflow.Data for _, scan := range scans { @@ -189,8 +189,8 @@ func extractDepGraphsFromScans(scans []*snykclient.ScanResult) ([]workflow.Data, // Create workflow data with the depgraph data := workflow.NewData(DataTypeID, contentTypeJSON, depGraphBytes) - data.SetMetaData(contentLocationKey, "uv.lock") - data.SetMetaData(MetaKeyNormalisedTargetFile, "uv.lock") + data.SetMetaData(contentLocationKey, targetFile) + data.SetMetaData(MetaKeyNormalisedTargetFile, targetFile) if scan.Identity.Type != "" { data.SetMetaData(MetaKeyTargetFileFromPlugin, scan.Identity.Type) diff --git a/pkg/depgraph/sbom_resolution_test.go b/pkg/depgraph/sbom_resolution_test.go index 705d612..7834a5c 100644 --- a/pkg/depgraph/sbom_resolution_test.go +++ b/pkg/depgraph/sbom_resolution_test.go @@ -131,8 +131,10 @@ func Test_callback_SBOMResolution(t *testing.T) { ctx.config.Set(configuration.API_URL, mockSBOMService.URL) mockUVClient := &mocks.MockUVClient{ - ExportSBOMFunc: func(_ string) ([]byte, error) { - return []byte(`{"bomFormat":"CycloneDX","specVersion":"1.5","components":[]}`), nil + ExportSBOMFunc: func(_ string) (*scaplugin.Finding, error) { + return &scaplugin.Finding{ + Sbom: []byte(`{"bomFormat":"CycloneDX","specVersion":"1.5","components":[]}`), + }, nil }, } @@ -159,7 +161,7 @@ func Test_callback_SBOMResolution(t *testing.T) { resolutionHandler := NewCalledResolutionHandlerFunc(nil, nil) mockUVClient := &mocks.MockUVClient{ - ExportSBOMFunc: func(_ string) ([]byte, error) { + ExportSBOMFunc: func(_ string) (*scaplugin.Finding, error) { return nil, fmt.Errorf("uv command failed") }, } @@ -187,8 +189,10 @@ func Test_callback_SBOMResolution(t *testing.T) { ctx.config.Set(configuration.API_URL, mockSBOMService.URL) mockUVClient := &mocks.MockUVClient{ - ExportSBOMFunc: func(_ string) ([]byte, error) { - return []byte(`{"bomFormat":"CycloneDX","specVersion":"1.5","components":[]}`), nil + ExportSBOMFunc: func(_ string) (*scaplugin.Finding, error) { + return &scaplugin.Finding{ + Sbom: []byte(`{"bomFormat":"CycloneDX","specVersion":"1.5","components":[]}`), + }, nil }, } @@ -268,8 +272,10 @@ func Test_callback_SBOMResolution(t *testing.T) { ctx.config.Set(configuration.API_URL, mockSBOMService.URL) mockUVClient := &mocks.MockUVClient{ - ExportSBOMFunc: func(_ string) ([]byte, error) { - return []byte(`{"bomFormat":"CycloneDX","specVersion":"1.5","components":[]}`), nil + ExportSBOMFunc: func(_ string) (*scaplugin.Finding, error) { + return &scaplugin.Finding{ + Sbom: []byte(`{"bomFormat":"CycloneDX","specVersion":"1.5","components":[]}`), + }, nil }, } diff --git a/pkg/sca_plugin/interface.go b/pkg/sca_plugin/interface.go index 9e068a7..d6d7934 100644 --- a/pkg/sca_plugin/interface.go +++ b/pkg/sca_plugin/interface.go @@ -7,6 +7,7 @@ type Options struct{} type Finding struct { Sbom Sbom FilesProcessed []string + TargetFile string } type Sbom []byte From b48464dfe926b2f746f67032bdcf04e23c0b2965 Mon Sep 17 00:00:00 2001 From: Thomas Schafer Date: Thu, 20 Nov 2025 16:31:05 +0000 Subject: [PATCH 2/4] chore: pass processed files out of plugin --- internal/mocks/uvclient.go | 11 ++++++++--- internal/uv/uv.go | 6 +++++- internal/uv/uvclient.go | 9 ++++++--- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/internal/mocks/uvclient.go b/internal/mocks/uvclient.go index 6015e15..045609c 100644 --- a/internal/mocks/uvclient.go +++ b/internal/mocks/uvclient.go @@ -1,6 +1,8 @@ package mocks import ( + "path" + "github.com/rs/zerolog" "github.com/snyk/cli-extension-dep-graph/internal/uv" @@ -18,9 +20,12 @@ func (m *MockUVClient) ExportSBOM(inputDir string) (*scaplugin.Finding, error) { return m.ExportSBOMFunc(inputDir) } return &scaplugin.Finding{ - Sbom: []byte(`{"mock":"sbom"}`), - TargetFile: "", - FilesProcessed: []string{}, + Sbom: []byte(`{"mock":"sbom"}`), + FilesProcessed: []string{ + path.Join(inputDir, uv.RequirementsTxtFileName), + path.Join(inputDir, uv.PyprojectTomlFileName), + }, + TargetFile: path.Join(inputDir, uv.UvLockFileName), }, nil } diff --git a/internal/uv/uv.go b/internal/uv/uv.go index 371db24..52a182f 100644 --- a/internal/uv/uv.go +++ b/internal/uv/uv.go @@ -8,7 +8,11 @@ import ( "github.com/rs/zerolog" ) -const UvLockFileName = "uv.lock" +const ( + UvLockFileName = "uv.lock" + RequirementsTxtFileName = "requirements.txt" + PyprojectTomlFileName = "pyproject.toml" +) // This is copied from cli-extension-os-flows. We could export from here via GAF config and re-use if this duplication // becomes a problem, but this duplication is only temporary. diff --git a/internal/uv/uvclient.go b/internal/uv/uvclient.go index ce22052..f6fd647 100644 --- a/internal/uv/uvclient.go +++ b/internal/uv/uvclient.go @@ -53,9 +53,12 @@ func (c client) ExportSBOM(inputDir string) (*scaplugin.Finding, error) { } return &scaplugin.Finding{ - Sbom: output, - FilesProcessed: []string{}, - TargetFile: path.Join(inputDir, UvLockFileName), + Sbom: output, + FilesProcessed: []string{ + path.Join(inputDir, RequirementsTxtFileName), + path.Join(inputDir, PyprojectTomlFileName), + }, + TargetFile: path.Join(inputDir, UvLockFileName), }, nil } From 5b5372d08f7997db346c1c60a75a17dfdb6d48c7 Mon Sep 17 00:00:00 2001 From: Thomas Schafer Date: Fri, 21 Nov 2025 15:32:42 +0000 Subject: [PATCH 3/4] chore: rename fields to be more descriptive --- internal/mocks/uvclient.go | 4 ++-- internal/uv/uvclient.go | 4 ++-- pkg/depgraph/sbom_resolution.go | 4 ++-- pkg/depgraph/sbom_resolution_test.go | 30 ++++++++++++++-------------- pkg/sca_plugin/interface.go | 6 +++--- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/internal/mocks/uvclient.go b/internal/mocks/uvclient.go index 045609c..1005296 100644 --- a/internal/mocks/uvclient.go +++ b/internal/mocks/uvclient.go @@ -21,11 +21,11 @@ func (m *MockUVClient) ExportSBOM(inputDir string) (*scaplugin.Finding, error) { } return &scaplugin.Finding{ Sbom: []byte(`{"mock":"sbom"}`), - FilesProcessed: []string{ + FileExclusions: []string{ path.Join(inputDir, uv.RequirementsTxtFileName), path.Join(inputDir, uv.PyprojectTomlFileName), }, - TargetFile: path.Join(inputDir, uv.UvLockFileName), + NormalisedTargetFile: uv.UvLockFileName, }, nil } diff --git a/internal/uv/uvclient.go b/internal/uv/uvclient.go index f6fd647..47a3df9 100644 --- a/internal/uv/uvclient.go +++ b/internal/uv/uvclient.go @@ -54,11 +54,11 @@ func (c client) ExportSBOM(inputDir string) (*scaplugin.Finding, error) { return &scaplugin.Finding{ Sbom: output, - FilesProcessed: []string{ + FileExclusions: []string{ path.Join(inputDir, RequirementsTxtFileName), path.Join(inputDir, PyprojectTomlFileName), }, - TargetFile: path.Join(inputDir, UvLockFileName), + NormalisedTargetFile: UvLockFileName, }, nil } diff --git a/pkg/depgraph/sbom_resolution.go b/pkg/depgraph/sbom_resolution.go index 81cf014..df70d4b 100644 --- a/pkg/depgraph/sbom_resolution.go +++ b/pkg/depgraph/sbom_resolution.go @@ -106,7 +106,7 @@ func handleSBOMResolutionDI( func getExclusionsFromFindings(findings []scaplugin.Finding) []string { exclusions := []string{} for _, f := range findings { - exclusions = append(exclusions, f.FilesProcessed...) + exclusions = append(exclusions, f.FileExclusions...) } return exclusions } @@ -160,7 +160,7 @@ func sbomToWorkflowData(finding scaplugin.Finding, snykClient *snykclient.SnykCl logger.Printf("Successfully converted SBOM, warning(s): %d\n", len(warnings)) - depGraphsData, err := extractDepGraphsFromScans(scans, finding.TargetFile) + depGraphsData, err := extractDepGraphsFromScans(scans, finding.NormalisedTargetFile) if err != nil { return nil, fmt.Errorf("failed to extract depgraphs from scan results: %w", err) } diff --git a/pkg/depgraph/sbom_resolution_test.go b/pkg/depgraph/sbom_resolution_test.go index 7834a5c..d429ce8 100644 --- a/pkg/depgraph/sbom_resolution_test.go +++ b/pkg/depgraph/sbom_resolution_test.go @@ -242,8 +242,8 @@ func Test_callback_SBOMResolution(t *testing.T) { // Create mock plugin that returns two findings mockPlugin := &mockScaPlugin{ findings: []scaplugin.Finding{ - {Sbom: []byte(`{"bomFormat":"CycloneDX","specVersion":"1.5","components":[]}`), FilesProcessed: []string{}}, - {Sbom: []byte(`{"bomFormat":"CycloneDX","specVersion":"1.5","components":[{"name":"test"}]}`), FilesProcessed: []string{}}, + {Sbom: []byte(`{"bomFormat":"CycloneDX","specVersion":"1.5","components":[]}`), FileExclusions: []string{}}, + {Sbom: []byte(`{"bomFormat":"CycloneDX","specVersion":"1.5","components":[{"name":"test"}]}`), FileExclusions: []string{}}, }, } @@ -297,19 +297,19 @@ func Test_callback_SBOMResolution(t *testing.T) { t.Run("handleSBOMResolution with FlagAllProjects", func(t *testing.T) { finding1 := scaplugin.Finding{ Sbom: []byte(`{"bomFormat":"CycloneDX","specVersion":"1.5","components":[]}`), - FilesProcessed: []string{"uv.lock", "pyproject.toml"}, + FileExclusions: []string{"uv.lock", "pyproject.toml"}, } finding2 := scaplugin.Finding{ Sbom: []byte(`{"bomFormat":"CycloneDX","specVersion":"1.5","components":[{"name":"test"}]}`), - FilesProcessed: []string{"requirements.txt", "setup.py"}, + FileExclusions: []string{"requirements.txt", "setup.py"}, } finding3 := scaplugin.Finding{ Sbom: []byte(`{"bomFormat":"CycloneDX","specVersion":"1.5","components":[{"name":"someFinding"}]}`), - FilesProcessed: []string{"package.json"}, + FileExclusions: []string{"package.json"}, } finding4 := scaplugin.Finding{ Sbom: []byte(`{"bomFormat":"CycloneDX","specVersion":"1.5","components":[{"name":"anotherFinding"}]}`), - FilesProcessed: []string{"go.mod"}, + FileExclusions: []string{"go.mod"}, } tc := []struct { @@ -520,7 +520,7 @@ func Test_callback_SBOMResolution(t *testing.T) { findings: []scaplugin.Finding{ { Sbom: []byte(`{"bomFormat":"CycloneDX","specVersion":"1.5","components":[]}`), - FilesProcessed: []string{"uv.lock"}, + FileExclusions: []string{"uv.lock"}, }, }, } @@ -590,7 +590,7 @@ func Test_callback_SBOMResolution(t *testing.T) { findings: []scaplugin.Finding{ { Sbom: []byte(`{"bomFormat":"CycloneDX","specVersion":"1.5","components":[]}`), - FilesProcessed: []string{"uv.lock"}, + FileExclusions: []string{"uv.lock"}, }, }, } @@ -632,7 +632,7 @@ func Test_getExclusionsFromFindings(t *testing.T) { findings: []scaplugin.Finding{ { Sbom: []byte(`{"bomFormat":"CycloneDX"}`), - FilesProcessed: []string{}, + FileExclusions: []string{}, }, }, expected: []string{}, @@ -642,7 +642,7 @@ func Test_getExclusionsFromFindings(t *testing.T) { findings: []scaplugin.Finding{ { Sbom: []byte(`{"bomFormat":"CycloneDX"}`), - FilesProcessed: []string{"file1.py", "file2.py"}, + FileExclusions: []string{"file1.py", "file2.py"}, }, }, expected: []string{"file1.py", "file2.py"}, @@ -652,11 +652,11 @@ func Test_getExclusionsFromFindings(t *testing.T) { findings: []scaplugin.Finding{ { Sbom: []byte(`{"bomFormat":"CycloneDX"}`), - FilesProcessed: []string{"file1.py", "file2.py"}, + FileExclusions: []string{"file1.py", "file2.py"}, }, { Sbom: []byte(`{"bomFormat":"CycloneDX","specVersion":"1.5"}`), - FilesProcessed: []string{"file3.py", "file4.py", "file5.py"}, + FileExclusions: []string{"file3.py", "file4.py", "file5.py"}, }, }, expected: []string{"file1.py", "file2.py", "file3.py", "file4.py", "file5.py"}, @@ -666,15 +666,15 @@ func Test_getExclusionsFromFindings(t *testing.T) { findings: []scaplugin.Finding{ { Sbom: []byte(`{"bomFormat":"CycloneDX"}`), - FilesProcessed: []string{}, + FileExclusions: []string{}, }, { Sbom: []byte(`{"bomFormat":"CycloneDX","specVersion":"1.5"}`), - FilesProcessed: []string{"file1.py"}, + FileExclusions: []string{"file1.py"}, }, { Sbom: []byte(`{"bomFormat":"CycloneDX","specVersion":"1.6"}`), - FilesProcessed: []string{"file2.py", "file3.py"}, + FileExclusions: []string{"file2.py", "file3.py"}, }, }, expected: []string{"file1.py", "file2.py", "file3.py"}, diff --git a/pkg/sca_plugin/interface.go b/pkg/sca_plugin/interface.go index d6d7934..1341a8f 100644 --- a/pkg/sca_plugin/interface.go +++ b/pkg/sca_plugin/interface.go @@ -5,9 +5,9 @@ import "github.com/rs/zerolog" type Options struct{} type Finding struct { - Sbom Sbom - FilesProcessed []string - TargetFile string + Sbom Sbom // The raw SBOM bytes + FileExclusions []string // Paths for files that other plugins should ignore + NormalisedTargetFile string // The target file name without any qualifiers, e.g. `uv.lock` (and not `dir/uv.lock`) } type Sbom []byte From c46066ca9951a71354107081127eff6dc70f05cb Mon Sep 17 00:00:00 2001 From: Thomas Schafer Date: Fri, 21 Nov 2025 16:07:05 +0000 Subject: [PATCH 4/4] chore: comment out exclusions for now - will address in 1059 --- internal/mocks/uvclient.go | 9 ++------- internal/uv/uvclient.go | 10 ++++++---- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/internal/mocks/uvclient.go b/internal/mocks/uvclient.go index 1005296..f8650c2 100644 --- a/internal/mocks/uvclient.go +++ b/internal/mocks/uvclient.go @@ -1,8 +1,6 @@ package mocks import ( - "path" - "github.com/rs/zerolog" "github.com/snyk/cli-extension-dep-graph/internal/uv" @@ -20,11 +18,8 @@ func (m *MockUVClient) ExportSBOM(inputDir string) (*scaplugin.Finding, error) { return m.ExportSBOMFunc(inputDir) } return &scaplugin.Finding{ - Sbom: []byte(`{"mock":"sbom"}`), - FileExclusions: []string{ - path.Join(inputDir, uv.RequirementsTxtFileName), - path.Join(inputDir, uv.PyprojectTomlFileName), - }, + Sbom: []byte(`{"mock":"sbom"}`), + FileExclusions: []string{}, NormalisedTargetFile: uv.UvLockFileName, }, nil } diff --git a/internal/uv/uvclient.go b/internal/uv/uvclient.go index 47a3df9..d56b775 100644 --- a/internal/uv/uvclient.go +++ b/internal/uv/uvclient.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" "os/exec" - "path" "regexp" "strconv" "strings" @@ -53,10 +52,13 @@ func (c client) ExportSBOM(inputDir string) (*scaplugin.Finding, error) { } return &scaplugin.Finding{ - Sbom: output, + Sbom: output, FileExclusions: []string{ - path.Join(inputDir, RequirementsTxtFileName), - path.Join(inputDir, PyprojectTomlFileName), + // TODO(uv): uncomment when we are able to pass these to the CLI correctly. Currently the + // `--exclude` flag does not accept paths, it only accepts file or dir names, which does not + // work for our use case. + // path.Join(inputDir, uv.RequirementsTxtFileName), + // path.Join(inputDir, uv.PyprojectTomlFileName), }, NormalisedTargetFile: UvLockFileName, }, nil