diff --git a/build.gradle b/build.gradle index 174a5e727f..38415389ee 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { group = 'com.blackduck.integration' -version = '12.0.0-SIGQA12-SNAPSHOT' +version = '12.0.0-SIGQA4-IDETECT-5117-SNAPSHOT' apply plugin: 'com.blackduck.integration.solution' apply plugin: 'org.springframework.boot' diff --git a/detectable/src/main/java/com/blackduck/integration/detectable/detectables/uv/UVDetectorOptions.java b/detectable/src/main/java/com/blackduck/integration/detectable/detectables/uv/UVDetectorOptions.java index 63751f0b2c..f97a6028b1 100644 --- a/detectable/src/main/java/com/blackduck/integration/detectable/detectables/uv/UVDetectorOptions.java +++ b/detectable/src/main/java/com/blackduck/integration/detectable/detectables/uv/UVDetectorOptions.java @@ -1,6 +1,7 @@ package com.blackduck.integration.detectable.detectables.uv; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -9,20 +10,34 @@ public class UVDetectorOptions { private final Set excludedDependencyGroups; + private final Set onlyDependencyGroups; + private final Set includedWorkspaceMembers; private final Set excludedWorkspaceMembers; - public UVDetectorOptions(List excludedDependencyGroups, List includedWorkspaceMembers, List excludedWorkspaceMembers) { + public UVDetectorOptions(List excludedDependencyGroups, List onlyDependencyGroups, List includedWorkspaceMembers, List excludedWorkspaceMembers) { this.excludedDependencyGroups = new HashSet<>(excludedDependencyGroups); + this.onlyDependencyGroups = new HashSet<>(onlyDependencyGroups); this.includedWorkspaceMembers = new HashSet<>(includedWorkspaceMembers); this.excludedWorkspaceMembers = new HashSet<>(excludedWorkspaceMembers); } + /** + * Backward-compatible constructor that defaults to an empty onlyDependencyGroups list. + */ + public UVDetectorOptions(List excludedDependencyGroups, List includedWorkspaceMembers, List excludedWorkspaceMembers) { + this(excludedDependencyGroups, Collections.emptyList(), includedWorkspaceMembers, excludedWorkspaceMembers); + } + public Set getExcludedDependencyGroups() { return excludedDependencyGroups.stream().map(String::toLowerCase).collect(Collectors.toSet()); } + public Set getOnlyDependencyGroups() { + return onlyDependencyGroups.stream().map(String::toLowerCase).collect(Collectors.toSet()); + } + public Set getIncludedWorkspaceMembers() { return includedWorkspaceMembers.stream().map(String::toLowerCase).collect(Collectors.toSet()); } diff --git a/detectable/src/main/java/com/blackduck/integration/detectable/detectables/uv/buildexe/UVBuildExtractor.java b/detectable/src/main/java/com/blackduck/integration/detectable/detectables/uv/buildexe/UVBuildExtractor.java index f8e5763866..50b72eb544 100644 --- a/detectable/src/main/java/com/blackduck/integration/detectable/detectables/uv/buildexe/UVBuildExtractor.java +++ b/detectable/src/main/java/com/blackduck/integration/detectable/detectables/uv/buildexe/UVBuildExtractor.java @@ -18,15 +18,23 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; public class UVBuildExtractor { + private static final String TREE_COMMAND = "tree"; + private static final String NO_DEDUPE_FLAG = "--no-dedupe"; + private static final String ALL_EXTRAS_FLAG = "--all-extras"; + private static final String ALL_GROUPS_FLAG = "--all-groups"; + private static final String NO_GROUP_FLAG = "--no-group"; + private static final String ONLY_GROUP_FLAG = "--only-group"; + private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final DetectableExecutableRunner executableRunner; private final File sourceDirectory; private final UVTreeDependencyGraphTransformer uvTreeDependencyGraphTransformer; - public UVBuildExtractor(DetectableExecutableRunner executableRunner, File sourceDirectory, UVTreeDependencyGraphTransformer uvTreeDependencyGraphTransformer) { this.executableRunner = executableRunner; this.sourceDirectory = sourceDirectory; @@ -35,18 +43,8 @@ public UVBuildExtractor(DetectableExecutableRunner executableRunner, File source public Extraction extract(ExecutableTarget uvExe, UVDetectorOptions uvDetectorOptions, UVTomlParser uvTomlParser) throws ExecutableRunnerException { try { - List arguments = new ArrayList<>(); - arguments.add("tree"); - arguments.add("--no-dedupe"); - - if(!uvDetectorOptions.getExcludedDependencyGroups().isEmpty()) { - for(String group : uvDetectorOptions.getExcludedDependencyGroups()) { - arguments.add("--no-group"); - arguments.add(group); - } - } - - // run uv tree command + List arguments = buildTreeCommandArguments(uvDetectorOptions); + ExecutableOutput executableOutput = executableRunner.executeSuccessfully(ExecutableUtils.createFromTarget(sourceDirectory, uvExe, arguments)); List uvTreeOutput = executableOutput.getStandardOutputAsList(); @@ -62,4 +60,54 @@ public Extraction extract(ExecutableTarget uvExe, UVDetectorOptions uvDetectorOp return new Extraction.Builder().exception(e).build(); } } + + private List buildTreeCommandArguments(UVDetectorOptions uvDetectorOptions) { + List arguments = new ArrayList<>(); + arguments.add(TREE_COMMAND); + arguments.add(NO_DEDUPE_FLAG); + + Set onlyGroups = uvDetectorOptions.getOnlyDependencyGroups(); + Set excludedGroups = uvDetectorOptions.getExcludedDependencyGroups(); + + if (!onlyGroups.isEmpty()) { + addOnlyGroupArguments(arguments, onlyGroups, excludedGroups); + } else { + addDefaultGroupArguments(arguments, excludedGroups); + } + + return arguments; + } + + private void addOnlyGroupArguments(List arguments, Set onlyGroups, Set excludedGroups) { + Set conflictingGroups = onlyGroups.stream() + .filter(excludedGroups::contains) + .collect(Collectors.toSet()); + + if (!conflictingGroups.isEmpty()) { + logger.warn( + "Dependency groups {} are present in both 'detect.uv.dependency.groups.only' and 'detect.uv.dependency.groups.excluded'. " + + "The exclusion setting takes precedence; these groups will be excluded.", + conflictingGroups + ); + } + + Set effectiveOnlyGroups = onlyGroups.stream() + .filter(group -> !excludedGroups.contains(group)) + .collect(Collectors.toSet()); + + for (String group : effectiveOnlyGroups) { + arguments.add(ONLY_GROUP_FLAG); + arguments.add(group); + } + } + + private void addDefaultGroupArguments(List arguments, Set excludedGroups) { + arguments.add(ALL_EXTRAS_FLAG); + arguments.add(ALL_GROUPS_FLAG); + + for (String group : excludedGroups) { + arguments.add(NO_GROUP_FLAG); + arguments.add(group); + } + } } diff --git a/detectable/src/test/java/com/blackduck/integration/detectable/detectables/uv/functional/UVDetectableFunctionalTest.java b/detectable/src/test/java/com/blackduck/integration/detectable/detectables/uv/functional/UVDetectableFunctionalTest.java index 6cee44173d..174d2d3c1c 100644 --- a/detectable/src/test/java/com/blackduck/integration/detectable/detectables/uv/functional/UVDetectableFunctionalTest.java +++ b/detectable/src/test/java/com/blackduck/integration/detectable/detectables/uv/functional/UVDetectableFunctionalTest.java @@ -77,7 +77,7 @@ protected void setup() throws IOException { "│ │ │ │ │ ├── aiohttp v3.12.15 (*)\n" + "│ │ │ │ │ ├── cryptography v44.0.3 (*)"); - addExecutableOutput(uvTreeDependencyOutput, new File("uv").getAbsolutePath(), "tree", "--no-dedupe"); + addExecutableOutput(uvTreeDependencyOutput, new File("uv").getAbsolutePath(), "tree", "--no-dedupe", "--all-extras", "--all-groups"); } @NotNull diff --git a/detectable/src/test/java/com/blackduck/integration/detectable/detectables/uv/functional/UVExcludeDevGroupsFunctionalTest.java b/detectable/src/test/java/com/blackduck/integration/detectable/detectables/uv/functional/UVExcludeDevGroupsFunctionalTest.java index 70173d449d..9e065e08ac 100644 --- a/detectable/src/test/java/com/blackduck/integration/detectable/detectables/uv/functional/UVExcludeDevGroupsFunctionalTest.java +++ b/detectable/src/test/java/com/blackduck/integration/detectable/detectables/uv/functional/UVExcludeDevGroupsFunctionalTest.java @@ -66,7 +66,7 @@ protected void setup() throws IOException { " └── typing-extensions v4.9.0"); // Note: with --no-group dev, pytest and mypy are excluded from output - addExecutableOutput(uvTreeDependencyOutput, new File("uv").getAbsolutePath(), "tree", "--no-dedupe", "--no-group", "dev"); + addExecutableOutput(uvTreeDependencyOutput, new File("uv").getAbsolutePath(), "tree", "--no-dedupe", "--all-extras", "--all-groups", "--no-group", "dev"); } @NotNull diff --git a/detectable/src/test/java/com/blackduck/integration/detectable/detectables/uv/unit/UVBuildExtractorTest.java b/detectable/src/test/java/com/blackduck/integration/detectable/detectables/uv/unit/UVBuildExtractorTest.java index e106200de1..36a5b9f80a 100644 --- a/detectable/src/test/java/com/blackduck/integration/detectable/detectables/uv/unit/UVBuildExtractorTest.java +++ b/detectable/src/test/java/com/blackduck/integration/detectable/detectables/uv/unit/UVBuildExtractorTest.java @@ -81,6 +81,8 @@ void extractBuildsBasicArguments() throws Exception { List arguments = captor.getValue().getCommandWithArguments(); assertTrue(arguments.contains("tree")); assertTrue(arguments.contains("--no-dedupe")); + assertTrue(arguments.contains("--all-extras")); + assertTrue(arguments.contains("--all-groups")); } // ==================== Excluded Groups Tests ==================== @@ -103,6 +105,8 @@ void extractAddsNoGroupFlagsForExcludedGroups() throws Exception { List arguments = captor.getValue().getCommandWithArguments(); assertTrue(arguments.contains("tree")); assertTrue(arguments.contains("--no-dedupe")); + assertTrue(arguments.contains("--all-extras")); + assertTrue(arguments.contains("--all-groups")); assertTrue(arguments.contains("--no-group")); int devIndex = arguments.indexOf("dev"); @@ -130,6 +134,8 @@ void extractWithEmptyExcludedGroupsAddsNoFlags() throws Exception { List arguments = captor.getValue().getCommandWithArguments(); + assertTrue(arguments.contains("--all-extras")); + assertTrue(arguments.contains("--all-groups")); long noGroupCount = arguments.stream().filter(arg -> arg.equals("--no-group")).count(); assertEquals(0, noGroupCount); } @@ -151,11 +157,135 @@ void extractWithSingleExcludedGroup() throws Exception { List arguments = captor.getValue().getCommandWithArguments(); + assertTrue(arguments.contains("--all-extras")); + assertTrue(arguments.contains("--all-groups")); long noGroupCount = arguments.stream().filter(arg -> arg.equals("--no-group")).count(); assertEquals(1, noGroupCount); assertTrue(arguments.contains("dev")); } + // ==================== Only Groups Tests ==================== + + @Test + void extractAddsOnlyGroupFlagsAndSkipsAllExtrasAllGroups() throws Exception { + UVBuildExtractor extractor = new UVBuildExtractor(executableRunner, tempDir, transformer); + UVDetectorOptions options = new UVDetectorOptions( + Collections.emptyList(), // excludedGroups + Arrays.asList("dev", "lint"), // onlyGroups + Collections.emptyList(), + Collections.emptyList() + ); + + Extraction extraction = extractor.extract(uvExe, options, tomlParser); + assertExtractionSuccess(extraction); + + ArgumentCaptor captor = ArgumentCaptor.forClass(Executable.class); + verify(executableRunner).executeSuccessfully(captor.capture()); + + List arguments = captor.getValue().getCommandWithArguments(); + assertTrue(arguments.contains("tree")); + assertTrue(arguments.contains("--no-dedupe")); + + // --all-extras and --all-groups should NOT be present when onlyGroups is set + assertTrue(!arguments.contains("--all-extras"), "Expected --all-extras to be absent when onlyGroups is set"); + assertTrue(!arguments.contains("--all-groups"), "Expected --all-groups to be absent when onlyGroups is set"); + + // --only-group flags should be present for each group + long onlyGroupCount = arguments.stream().filter(arg -> arg.equals("--only-group")).count(); + assertEquals(2, onlyGroupCount); + assertTrue(arguments.contains("dev")); + assertTrue(arguments.contains("lint")); + + // Each group should be preceded by --only-group + int devIndex = arguments.indexOf("dev"); + int lintIndex = arguments.indexOf("lint"); + assertTrue(devIndex > 0); + assertTrue(lintIndex > 0); + assertEquals("--only-group", arguments.get(devIndex - 1)); + assertEquals("--only-group", arguments.get(lintIndex - 1)); + } + + @Test + void extractWithSingleOnlyGroup() throws Exception { + UVBuildExtractor extractor = new UVBuildExtractor(executableRunner, tempDir, transformer); + UVDetectorOptions options = new UVDetectorOptions( + Collections.emptyList(), + Arrays.asList("dev"), + Collections.emptyList(), + Collections.emptyList() + ); + + Extraction extraction = extractor.extract(uvExe, options, tomlParser); + assertExtractionSuccess(extraction); + + ArgumentCaptor captor = ArgumentCaptor.forClass(Executable.class); + verify(executableRunner).executeSuccessfully(captor.capture()); + + List arguments = captor.getValue().getCommandWithArguments(); + + assertTrue(!arguments.contains("--all-extras")); + assertTrue(!arguments.contains("--all-groups")); + long onlyGroupCount = arguments.stream().filter(arg -> arg.equals("--only-group")).count(); + assertEquals(1, onlyGroupCount); + assertTrue(arguments.contains("dev")); + } + + // ==================== Conflict Handling Tests ==================== + + @Test + void extractExclusionTakesPrecedenceOverOnlyGroup() throws Exception { + UVBuildExtractor extractor = new UVBuildExtractor(executableRunner, tempDir, transformer); + // "dev" is in both only and excluded — exclusion should take precedence + UVDetectorOptions options = new UVDetectorOptions( + Arrays.asList("dev"), // excludedGroups + Arrays.asList("dev", "lint"), // onlyGroups + Collections.emptyList(), + Collections.emptyList() + ); + + Extraction extraction = extractor.extract(uvExe, options, tomlParser); + assertExtractionSuccess(extraction); + + ArgumentCaptor captor = ArgumentCaptor.forClass(Executable.class); + verify(executableRunner).executeSuccessfully(captor.capture()); + + List arguments = captor.getValue().getCommandWithArguments(); + + // --all-extras and --all-groups should NOT be present (onlyGroups path) + assertTrue(!arguments.contains("--all-extras")); + assertTrue(!arguments.contains("--all-groups")); + + // "dev" should be excluded — only "lint" should remain as --only-group + long onlyGroupCount = arguments.stream().filter(arg -> arg.equals("--only-group")).count(); + assertEquals(1, onlyGroupCount, "Only 'lint' should remain after 'dev' is excluded"); + assertTrue(arguments.contains("lint")); + assertTrue(!arguments.contains("dev"), "'dev' should be excluded from --only-group flags"); + } + + @Test + void extractAllOnlyGroupsExcludedResultsInNoOnlyGroupFlags() throws Exception { + UVBuildExtractor extractor = new UVBuildExtractor(executableRunner, tempDir, transformer); + // All only-groups are also excluded + UVDetectorOptions options = new UVDetectorOptions( + Arrays.asList("dev", "lint"), // excludedGroups + Arrays.asList("dev", "lint"), // onlyGroups + Collections.emptyList(), + Collections.emptyList() + ); + + Extraction extraction = extractor.extract(uvExe, options, tomlParser); + assertExtractionSuccess(extraction); + + ArgumentCaptor captor = ArgumentCaptor.forClass(Executable.class); + verify(executableRunner).executeSuccessfully(captor.capture()); + + List arguments = captor.getValue().getCommandWithArguments(); + + // No --only-group flags since all were excluded + long onlyGroupCount = arguments.stream().filter(arg -> arg.equals("--only-group")).count(); + assertEquals(0, onlyGroupCount, "No --only-group flags should remain when all are excluded"); + } + /** * Asserts that the extraction completed on the success path. diff --git a/documentation/src/main/markdown/currentreleasenotes.md b/documentation/src/main/markdown/currentreleasenotes.md index 4fb7c6ce69..97bd2c495b 100644 --- a/documentation/src/main/markdown/currentreleasenotes.md +++ b/documentation/src/main/markdown/currentreleasenotes.md @@ -16,6 +16,32 @@ * **Deprecation of Java 8 support** - In alignment with EU Cyber Resilience Act (CRA) requirements and compliance timelines, Java 8 support will be deprecated in the anticipated 2026 Q3 Detect 12.0.0 release. +## Version 11.5.0 + +### Changed features + +* The default output directory of the Quack Patch feature has been updated to use [detect_product_short] scan output directory. For more information, see [Quack Patch Documentation](runningdetect/quack-patch.md). +* CentOS support in Detect Docker Inspector has been deprecated and will be removed in 12.0.0. For more details, please see [Docker Inspector Release Notes](packagemgrs/docker/releasenotes.md). + * imageinspector.service.port.centos has been deprecated and will be removed in 12.0.0. +* Clarified documentation for `--detect.uv.dependency.groups.excluded`. Optional is not a dependency group in uv but a section defining extras, therefor supplying `optional` as a value has no effect and exclusions must reference the extra name directly (e.g., postgres, redis). +* Added `detect.uv.dependency.groups.only` property for the UV CLI detector. To restrict scanning to specific dependency groups while excluding standard dependencies and optional extras, use this property. When set, Detect limits analysis to the explicitly listed dependency groups defined in the project's pyproject.toml. Multiple groups can be specified as a comma-separated list (e.g., `detect.uv.dependency.groups.only='dev,lint'`). This applies exclusively to groups under the `[dependency-groups]` section; extras under `[project.optional-dependencies]` are not included. If both this property and `detect.uv.dependency.groups.excluded` are configured, the exclusion setting takes precedence for any overlapping groups and Detect will log a warning. +### Resolved issues +* (IDETECT-5125) Fixed failure during Python scans when the `requirements.txt` file contains Python extras syntax using square brackets, e.g.: `kopf[dev]>=1.3` +* (IDETECT-5090) Fixed PIP Native Inspector failure to parse `requirements.txt` lines that contain [PEP 508 environment markers](https://peps.python.org/pep-0508/). +* (IDETECT-5056) Fixed a Cargo Lock detector failure to parse the caret symbol '^' used in `Cargo.toml` dependency declarations. +* (IDETECT-5071) Fixed an issue with Simple Build Tool (sbt) evictions being included in the BOM. +* (IDETECT-5069) Fixed Setuptools parsing for unsupported install_requires syntax in setup.py: Detect now fails fast and logs an error instead of silently misparsing, generating an incorrect BOM, and incorrectly reporting success. +* (IDETECT-5140) Changed the default output directory of the Quack Patch feature to use [detect_product_short] scan output directory instead of the current working directory. +* (IDETECT-5121) Include Quack Patch output directory as part of diagnostic zip when the feature is enabled. +* (IDETECT-5064) Updated the Gradle init script to explicitly assign an empty configuration set to phantom projects (container modules lacking a `build.gradle` file). This change prevents tools injected by plugins such as Detekt and Ktlint from being included in the dependency report. +* (IDETECT-5097) Updated the Gradle init script to enumerate configurations within `gradle.projectsEvaluated`, ensuring that all `afterEvaluate` callbacks, including those from the Android Gradle Plugin (AGP), have completed before configuration processing begins. +* (IDETECT-5163) Updated the Bazel detector to treat exit code `3` from `query` and `cquery` commands as a partial success. When encountered, the detector now processes any available output and issues a warning indicating that dependency results may be incomplete. +* (IDETECT-5053) / (IDETECT-4988) Fixed pip inspector to correctly parse PEP 440 direct reference packages (`name @ url`), ensuring these packages are included in the dependency tree rather than being omitted. +* (IDETECT-5078) Rather then fail, Detect will now complete scans and generate empty BOMs when a Python Setuptools project has no dependencies. +* (IDETECT-5079) Allow Detect scans to finish with success even if no configured binary file patterns (e.g., .jar, .war, .zip) are found. +* (IDETECT-5118) Fixed UV Lockfile Detector to respect excluded dependency groups for optional‑dependencies. Optional extras specified in exclusion flags are now correctly excluded alongside development dependencies. +* (IDETECT‑5126) Fixed a BitBake layer misidentification issue caused by project folder names colliding with layer names. The detector now resolves layers deterministically, preferring the deepest valid match and falling back to the first valid layer when necessary. +* (IDETECT-5071) Fixed an issue with Simple Build Tool (sbt) evictions being included in the BOM. Dependencies that requested an evicted version are now reported with the version that replaced it. ## Version 12.0.0 ### New features diff --git a/documentation/src/main/markdown/packagemgrs/python.md b/documentation/src/main/markdown/packagemgrs/python.md index 43c907d86b..8bfa0c48a6 100644 --- a/documentation/src/main/markdown/packagemgrs/python.md +++ b/documentation/src/main/markdown/packagemgrs/python.md @@ -132,7 +132,9 @@ UV has two detectors: ### UV CLI detector -UV CLI will run if the uv executable is found along with a pyproject.toml file. It will run uv tree commands to find dependencies for the project. +UV CLI will run if the uv executable is found along with a pyproject.toml file. It will run uv tree commands to find dependencies for the project. By default, the UV CLI detector includes main dependencies, all dependency groups, and all optional extras. Use the `detect.uv.dependency.groups.excluded` property to exclude specific dependency groups from the scan. + +To restrict scanning to specific dependency groups while excluding standard dependencies and optional extras, use the `detect.uv.dependency.groups.only` property. When this property is set, Detect limits analysis to the explicitly listed dependency groups defined in the project's pyproject.toml. You can specify multiple groups as a comma-separated list (for example: `detect.uv.dependency.groups.only='dev,lint'`). This configuration applies exclusively to groups defined under the `[dependency-groups]` section; dependencies declared as extras under `[project.optional-dependencies]` are not included when this property is enabled. If both `detect.uv.dependency.groups.only` and `detect.uv.dependency.groups.excluded` are configured, the exclusion setting takes precedence for any overlapping groups, and Detect will log a warning to indicate the conflict. ### UV Lock detector @@ -144,6 +146,6 @@ UV Lock detector will parse uv.lock, requirements.txt, or both to find project d ### Dependency and Workspace Inclusions/Exclusions -[UV Properties](../properties/detectors/uv.md) supports exclusion of all the dependency groups specified. Since uv has a concept of workspaces, they can be included and excluded using the properties provided. +[UV Properties](../properties/detectors/uv.md) supports exclusion of dependency groups. By default, the UV detector includes main dependencies, all dependency groups, and all optional extras. Use the `detect.uv.dependency.groups.excluded` property to exclude specific dependency groups from the scan. Since uv has a concept of workspaces, they can be included and excluded using the properties provided. The workspace member provided in the property should be identical to the key name under tool.uv.sources since dependencies are created under the same key name in the tree and uv.lock file. For excluding dependency groups and workspaces, presence of uv.lock or uv executable is required. diff --git a/src/main/java/com/blackduck/integration/detect/configuration/DetectProperties.java b/src/main/java/com/blackduck/integration/detect/configuration/DetectProperties.java index ac3595f5f2..c785b73396 100644 --- a/src/main/java/com/blackduck/integration/detect/configuration/DetectProperties.java +++ b/src/main/java/com/blackduck/integration/detect/configuration/DetectProperties.java @@ -2071,6 +2071,17 @@ private DetectProperties() { .setGroups(DetectGroup.UV, DetectGroup.GLOBAL, DetectGroup.SOURCE_SCAN) .build(); + public static final CaseSensitiveStringListProperty DETECT_UV_DEPENDENCY_GROUPS_ONLY = + CaseSensitiveStringListProperty.newBuilder("detect.uv.dependency.groups.only") + .setInfo("uv Only Dependency Groups", DetectPropertyFromVersion.VERSION_12_0_0) + .setHelp( + "A comma-separated list of uv dependency groups to exclusively scan.", + "When set, Detect will include only the named dependency groups defined in a project's pyproject.toml. Regular dependencies and optional extras are skipped. You can list multiple groups (for example: detect.uv.dependency.groups.only='dev,lint'). This property is only supported for projects that use pyproject.toml (dependency groups are not available in setup.py or setup.cfg). If both this property and detect.uv.dependency.groups.excluded are configured, the exclusion setting takes precedence for overlapping groups, and Detect will log a warning." + ) + .setGroups(DetectGroup.UV, DetectGroup.GLOBAL, DetectGroup.SOURCE_SCAN) + .setCategory(DetectCategory.Advanced) + .build(); + public static final CaseSensitiveStringListProperty DETECT_UV_EXCLUDED_WORKSPACE_MEMBERS = CaseSensitiveStringListProperty.newBuilder("detect.uv.excluded.workspace.members") .setInfo("uv Exclude Workspace Members", DetectPropertyFromVersion.VERSION_10_5_0) diff --git a/src/main/java/com/blackduck/integration/detect/configuration/DetectableOptionFactory.java b/src/main/java/com/blackduck/integration/detect/configuration/DetectableOptionFactory.java index 92ace8c329..1a6264cb00 100644 --- a/src/main/java/com/blackduck/integration/detect/configuration/DetectableOptionFactory.java +++ b/src/main/java/com/blackduck/integration/detect/configuration/DetectableOptionFactory.java @@ -386,9 +386,10 @@ private boolean getFollowSymLinks() { public UVDetectorOptions createUVDetectorOptions() { List excludedDependencyGroups = detectConfiguration.getValue(DetectProperties.DETECT_UV_DEPENDENCY_GROUPS_EXCLUDED); + List onlyDependencyGroups = detectConfiguration.getValue(DetectProperties.DETECT_UV_DEPENDENCY_GROUPS_ONLY); List includedWorkSpaceMembers = detectConfiguration.getValue(DetectProperties.DETECT_UV_INCLUDED_WORKSPACE_MEMBERS); List excludeWorkSpaceMembers = detectConfiguration.getValue(DetectProperties.DETECT_UV_EXCLUDED_WORKSPACE_MEMBERS); - return new UVDetectorOptions(excludedDependencyGroups, includedWorkSpaceMembers, excludeWorkSpaceMembers); + return new UVDetectorOptions(excludedDependencyGroups, onlyDependencyGroups, includedWorkSpaceMembers, excludeWorkSpaceMembers); } }