Skip to content

Conversation

@boolivar
Copy link
Contributor

@boolivar boolivar commented Jan 3, 2026

This PR exposes low-level Settings configuration for tasks.
The main purpose is to have ability to configure Settings keys that are not available through DependencyCheckExtension e.g. see #489 or to set up new version of dependency-check-core with old plugin version where extension DSL is not yet upgraded for new features.

DependencyCheckTaskConfig/AnalyzeTaskConfig input hierarchy was introduced to configure tasks and this should resolve #484 issue. DependencyCheckExtension provides conventions for task inputs that can be refined for specific task:

tasks.register<Analyze>("ossCheck") {
	config {
		settings.put(Settings.KEYS.ANALYZER_OSSINDEX_ENABLED, true)
	}
}

Most of the changes are in ConfiguredTask.
Settings values collected from DependencyCheckExtension to MapProperty of DependencyCheckTaskConfig.
Groovy truth is used to replicate setStringIfNotEmpty cases coercing empty strings to null:

getOrNull() ?: null

then nulls removed:

settings.removeAll { it.value == null }

The only thing I worry about is AnalyzeTaskConfig.isScanSetConfigured flag.
I simplified it to !scanSet.empty so it may break expectations regarding setting scanSet to empty list.

Lastly I think it's worth mentioning that Analyze task inputs involved in gradle up-to-date checks which may make sense in some cases, however dependencyCheck result generally depends on external oss/nvd state so it is good to mention disable up-to-date checks option.

cc @ThomGeG

@chadlwilson
Copy link
Collaborator

chadlwilson commented Jan 3, 2026

Thanks for the effort/thought that went into this. Was this discussed somewhere as an approach?

I am just a contributor and long time user, but I'm not in support of this approach.

I understand the motivation, as there are a number of problems with the current approach including

  • amount of boilerplate needed to map settings
  • duplicate configuration and defaulting logic
  • missing settings from Gradle native config
  • inconsistently named settings
  • documentation being separated from code; Gradle plugin lagging behind due to being separated from the rest.
    • changes/new features made in core are often not propagated to this plugin
    • changes made to this plugin are not documented (via core repo)

Exposing Settings seems good from a user perspective "the code is already there!", right? But I believe amounts to a maintenance and support nightmare.

The concerns I have here are a few aspects (not going into detail, just broad inferences for now)

  1. introduces yet another configuration approach for Gradle, adding to semantic confusion for users. We should have one way to do things for 99% of users.
  2. externally couples users to internals (developer API) of ODC core making changes/refactoring even more difficult
  3. a lot of Settings is basically undocumented - documentation, especially regarding defaults, typically comes by the consuming software (plugins, CLI etc)
  4. a number values of Settings either have potential to break the Gradle plugin or won't work correctly in the context of Gradle. Once they are exposed by an API they will be expected to work and continue to work as they did forever.
  5. yet more inconsistency with the Maven plugin
  6. Settings modelling is already basically a flat list of "stuff" and by design, somewhat full of leaky abstractions (seemingly intended for internal use) that do not model/group related settings which feels very non-Gradle idiomatic.

If people really want to do this; it is still mostly possible to "break glass" and set raw Settings keys by using the existing Settings System.setProperty(..) support in doFirst{ } blocks or similar, which is (IMHO) intentionally undocumented, for all the reasons above. I believe you can also use an externalised properties file; and set that file by a System property.

To me, that is perfectly good enough, and we should not make it easier to cut through all the layers to ODC internals. So it is unfortunately a -1 for me.

If we wanted to consider a middle-ground that I might find slightly more tolerable, we might consider an extra option for power-user-only ability to set a properties file to bootstrap settings via at the below, however given none of the other tools/plugins seem to utilise this option, perhaps that's not intended either.

protected void initializeSettings() {
settings = new Settings()

@boolivar
Copy link
Contributor Author

boolivar commented Jan 3, 2026

@chadlwilson thank you for such a detailed answer! I really appreciate your time and effort spent on this!

Let me justify myself since my change probably brings too many things at once.

  1. introduces yet another configuration approach for Gradle
  2. yet more inconsistency with the Maven plugin

I'm not sure about Maven plugin but this is a general Gradle approach - using extension to configure task inputs:

With this approach tasks can be registered and configured separately. Also here is a user request: #484.

As I already mentioned inputs are used by Gradle e.g. for input validation, up-to-date checks and task dependencies resolution:
https://docs.gradle.org/9.2.1/userguide/implementing_custom_tasks.html#understanding_inputs_and_outputs
So it seems like a good idea to have well structured inputs for tasks.

And here is the problem with existing Settings System.setProperty(..) support: it is not visible by Gradle although it is working solution. Again, the recommendation is to use inputs.


At this point I assume Settings.KEYS exposed is the main concern.

I completely understand your point and absolutely agree with the leaky abstraction.
I've spent a lot of time debugging the plugin and sneaking into the source code in order to find the way how to provide nexus credentials (#489) so probably this forced me to thought that it would be much easier if there is a way to provide Settings directly. 🤷‍♂️
I agree that it is just a shortcut to the dependencycheck core and

we should not make it easier to cut through all the layers to ODC internals

However Settings.KEYS doesn't seem like internals - it is an API of dependencycheck Engine.
Any other software with dependency-check-core dependency is at risk by using this API.

At the end of the day extension DSL is still in place and should be the main approach for plugin configuration while task configuration is more like an advanced technique with some tradeoffs like possibility to break something or future version incompatibility.

I'm happy this conversation is started and hope we can find common solution.
Thank you for the great tool and your feedback! 🚀

@chadlwilson
Copy link
Collaborator

chadlwilson commented Jan 3, 2026

My concern above isn't making any particular comment about your task configuration approach (although why do things differently to #487 without contributing to get that work merged is a bit odd).

The concern is mainly the generic Settings binding and coupling. Software is built on abstractions and layers and not everything is intended to be exposed to everywhere else directly.

ODC core is a relatively small project (maintainer wise) and does not seem to be religious about defining its Java API. Basically everything seems to be public by default, there are few interfaces,.the impls are not split, and so personally I don't think this can be assumed to mean anything. It's an obvious truth that the closer you move something to end users, the less likely you can change it without annoying people. So the question is - is it OK to make all Settings visible,. discoverable (via Kotlin mainly) and usable by end users in the current state?

To me, Settings is mainly intended to be for plugin/API developers. Even ODCs own CLI doesn't expose every settings key by some kind of magic mapping to a CLI arg.

I of course understand well that inputs are the Gradle way, but I still believe that directly allowing setting every single Setting via Inputs is a bad idea for the reasons I outlined above. If this is intended for advanced usages, I think it's fine to add friction via System properties.

Personally I don't think a project should make it easier for users to do things that make maintainers lives harder, especially given how few people have even used the current friction as a reason to help and address some of the missing settings. So the debate here for others to decide is whether this does indeed make maintenance harder, or whether I am inventing problems

Anyway, it's not my project, and I don't have merge permissions - I'm just an occasional (minor) contributor, issue triager and user who has an opinion :)

Copy link
Contributor

@jeremylong jeremylong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have to agree with @chadlwilson - I'm not a fan of exposing the Settings object. If additional settings should be exposed, they should be added to an extension.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a task configuration system that exposes low-level Settings configuration for DependencyCheck tasks. The main purpose is to enable configuration of Settings keys not available through DependencyCheckExtension or to support new versions of dependency-check-core with older plugin versions.

Key changes:

  • Introduces DependencyCheckTaskConfig and AnalyzeTaskConfig input hierarchy for configuring tasks
  • Refactors ConfiguredTask to build settings from a map rather than directly calling settings methods
  • Adds config() methods to all tasks allowing per-task configuration overrides

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/main/groovy/org/owasp/dependencycheck/gradle/extension/DependencyCheckTaskConfig.groovy New interface defining base task configuration with failOnError property and settings map
src/main/groovy/org/owasp/dependencycheck/gradle/extension/AnalyzeTaskConfig.groovy New abstract class extending DependencyCheckTaskConfig with analyze-specific properties
src/main/groovy/org/owasp/dependencycheck/gradle/extension/AdditionalCpe.groovy Marks getName() as @internal to prevent it from affecting task up-to-date checks
src/main/groovy/org/owasp/dependencycheck/gradle/tasks/ConfiguredTask.groovy Major refactoring to use config object pattern and build settings map; simplified proxy configuration
src/main/groovy/org/owasp/dependencycheck/gradle/tasks/AbstractAnalyze.groovy Updated to use AnalyzeTaskConfig and expose config() method
src/main/groovy/org/owasp/dependencycheck/gradle/tasks/Update.groovy Added config() method for task-level configuration
src/main/groovy/org/owasp/dependencycheck/gradle/tasks/Purge.groovy Added config() method for task-level configuration
src/test/groovy/org/owasp/dependencycheck/gradle/DependencyCheckPluginIntegSpec.groovy Added integration test verifying multiple analyze tasks can be configured independently

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for multiple analysis tasks

3 participants