Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to handle plugins that add their own dependencies? #15

Closed
mqware opened this issue Nov 21, 2023 · 4 comments
Closed

How to handle plugins that add their own dependencies? #15

mqware opened this issue Nov 21, 2023 · 4 comments
Labels

Comments

@mqware
Copy link

mqware commented Nov 21, 2023

I am trying to apply a community-plugin that automatically adds its own dependency, and of course I am getting an error from the org.example.dependency-analysis-project plugin that versions must be declared in the platform project. Apart from modifying the plugin code itself, what would be the best approach to handle a situation like this?
I was thinking that maybe in addition to showing the error message, the plugin could also remove any dependencies that were added with a version, and then the user would have to make sure that the same dependency is defined in the platform and added in the build script. But so far I don't have any luck implementing this. Do you have any suggestions on how to resolve this issue?
Thanks.
Peter

@jjohannes
Copy link
Owner

Hi @mqware. It's a good idea to remove dependencies that were added by another plugin to have full control over them in your build. You can do that through the withDependencies hook, which this project already uses to check the ordering of dependencies (although I might change that check, see #14). withDependencies is called right before dependency resolution starts. It operates on a Set<Dependency> which you are allowed to modify. For example, the following would remove all dependencies called guice from all scopes:

configurations.all {
    withDependencies {
        this.removeAll { it.name == "guice" }
    }
}

Official documentation of the feature: https://docs.gradle.org/current/userguide/resolution_rules.html#changing_configuration_dependencies_prior_to_resolution

@mqware
Copy link
Author

mqware commented Nov 23, 2023

Hi @jjohannes. Thanks, sounds like I was on the right track then, I just need to figure out how to actually implement it. (Which is the hard part :-) I was trying to do something similar in the org.example.dependency-analysis-project plugin, because I wanted to detect dependencies with versions, and remove them dynamically. But when I do that I get a java.util.ConcurrentModificationException.

// Check that dependencies are always declared without version.
configurations.all {
    if (configurationPrefixesToSkip.any { name.startsWith(it) }) {
        return@all
    }

    val configuration = this
    withDependencies {
        forEach { dependency ->
            if (dependency is ExternalModuleDependency && !dependency.version.isNullOrEmpty()) {
                this.remove(dependency)
                ...

@mqware
Copy link
Author

mqware commented Nov 24, 2023

While I am still not sure why this.remove() throws an exception, this.removeAll { } seems to work. But it is still not working well, because if I try to remove all dependencies (that are defined with a version) in the org.example.dependency-analysis plugin, then it will complain about the platform project having dependencies with a version. If I try the remove in the org.example.dependency-analysis-project plugin, then the alphabetical order check will complain. So, it looks like the order of checks will need to be changed.

@jjohannes
Copy link
Owner

In the current setup, I think conceptually org.example.dependency-analysis-project would be the right place to do the removal. This plugin is meant for "normal Java projects" (projects that are NOT platform). While org.example.dependency-analysis is used everywhere for the order check. If we move this check into a task – I'll take some time soon to check how to do that best (#14) – then org.example.dependency-analysis will no longer have a withDependencies block. Instead it'll register a task. Then you most likely won't have the problem anymore.

In the current setup: You now have a very sensitive order of the things done in withDependencies:

  1. remove dependencies without version
    • but not for platform projects (!)
  2. do the ordering check

I may have to think about this a bit more, but it might be better to only have one withDependencies block in your plugins so that you fully control the order. One option is to move everything into the withDependencies in org.example.dependency-analysis and make things conditional. The code runs after Gradle's general configuration phase, so you can check what kind of project you are dealing with using plugins.hasPlugin. For example something like this:

org.example.dependency-analysis-project.gradle.kts

configurations.all {
    withDependencies {
        if (plugins.hasPlugin("java")) { // only 'normal' Java projects, not platforms
            // remove dependencies with versions
        }
        // do checks on the remaining dependencies
    }
}

I am not sure if this is the most elegant solution though. When I look at #14 I'll give this some more thoughts and provide an update here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants