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

Exclude spring managed dependencies #453

Closed
JulianDoe opened this issue Dec 18, 2020 · 8 comments
Closed

Exclude spring managed dependencies #453

JulianDoe opened this issue Dec 18, 2020 · 8 comments

Comments

@JulianDoe
Copy link

JulianDoe commented Dec 18, 2020

We use your plugin to determine newer versions of libraries in our project. In addition, we use the spring.boot,.framework and its feature to manage dependent libraries.
Unfortunately, your plugin reports newer version of libraries which are managed through the spring.boot.framework. It is a little time consuming to determine which reported lib is manually updateable and which is managed. Therefore, we tried to exclude the managed libs with a component selection rule:

dependencyUpdates {
        resolutionStrategy {    
             Map managedDependencies = dependencyManagement.getManagedVersions()
             componentSelection { rules ->
                  rules.all { ComponentSelection selection ->
                      boolean isManagedDependency =  managedDependencies.containsKey(selection.candidate.moduleIdentifier.toString())
                      if (isManagedDependency) {
                        selection.reject('Release candidate')
                      }
                }
            }
        }
       revision = "release"
}

However, at the very first run of the dependency plugin the dependencyManagement.getManagedVersions() returns an empty map. Is there an better or more easier way to exclude managed libraries from the report?

@ben-manes
Copy link
Owner

I think you could either defer to the end of the configuration phase using afterEvaluate or to the execution phase by calling getManagedVersions within your rule.

Most likely you would want to use force so that the dependency is listed as up-to-date. I think that would look something like,

afterEvaluate {
  dependencyUpdates.resolutionStrategy {
    dependencyManagement.managedVersions.each { key, version ->
      force "$key:$version"
    }
  }
}

Your sample could be fixed by moving the call to dependencyManagement into the selection rule. This would then list the dependency as unresolvable, which might not be desired as appears in the report as a possible error.

Another approach would be to use an outputFormatter to remove from the results and then call one of the built-ins, like PlainTextReporter. Then those dependencies wouldn't be listed all.

Hopefully one of those variants works out.

@chadlwilson
Copy link
Contributor

chadlwilson commented Dec 19, 2020

Thanks for the suggestion @ben-manes! Like the OP, this has been irritating me for a while. Your suggestion does get a lot closer, but for others' interest, it does have a couple of cases where the results are a bit weird which people might want to be aware of.

  • If you have a declared say, implementation 'group:artifact:version' that overrrides the dependency managed version it will report it as dependencies [that] exceed the version found at the release revision level which is a little misleading (perhaps this is desirable, a hint that you should override the dependency managed version directly via ext['blah.version'] in the Spring Boot case....?)

  • if you declare that you are using a dependency (without version) which is not directly dependency managed; but is a transitive dependency of something else that is dependency managed then it will still show up in the report as upgradeable, rather than just leaving you with the dependency managed version e.g

implementation 'org.springframework.boot:spring-boot-starter-undertow'
implementation 'org.jboss.xnio:xnio-api'
  • it seems to break the rejectVersionIf magic like the below from the README, which starts suggesting release candidates to me again. Consolidating everything into afterEvaluate with resolutionStrategy instead seems to resolve this, though.
def isNonStable = { String version ->
    def stableKeyword = ['RELEASE', 'FINAL', 'GA'].any { it -> version.toUpperCase().contains(it) }
    def regex = /^[0-9,.v-]+(-r)?$/
    return !stableKeyword && !(version ==~ regex)
}

afterEvaluate {
    dependencyUpdates {
        revision = 'release'
        resolutionStrategy {
            // Excludes from `dependencyUpdates` versions managed by Spring Boot.
            if (!project.hasProperty("updatesIncludeManagedVersions")) {
                dependencyManagement.managedVersions.each { key, version ->
                    force "$key:$version"
                }
            }
            componentSelection {
                all {
                    if (isNonStable(it.candidate.version) && !isNonStable(it.currentVersion)) {
                        reject('Not a stable version')
                    }
                }
            }
        }
    }
}

@JulianDoe
Copy link
Author

JulianDoe commented Dec 21, 2020

Thank you both for the quick responses.
@chadlwilson Your solution works also in our project. Thanks!

@arolfes
Copy link

arolfes commented Nov 12, 2021

Thank you @chadlwilson . your proposal helps me alot

in gradle kotlin dsl the solution looks like:

tasks.withType<com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask> {
    revision = "release"
    checkForGradleUpdate = false
    outputFormatter = "json,html"
    outputDir = "build/dependencyUpdates"
    reportfileName = "report"
    afterEvaluate {
        resolutionStrategy {
            // Excludes from `dependencyUpdates` versions managed by Spring Boot.
            if (!project.hasProperty("updatesIncludeManagedVersions")) {
                dependencyManagement.managedVersions.forEach { (key, version) ->
                    force("$key:$version")
                }
            }
            componentSelection {
                all {
                    if (isNonStable(candidate.version) && !isNonStable(currentVersion)) {
                        reject("Release candidate")
                    }
                }
            }
        }
    }
}

An working example can be found here: https://github.com/arolfes/gradle-versions-plugin-spring-boot

@jasonab
Copy link

jasonab commented Mar 30, 2023

am I correct that this does not exclude test* dependencies?

@ben-manes
Copy link
Owner

componentSelection.all means it applies to every component. You could follow the docs to apply it more conditionally if desired.

@jasonab
Copy link

jasonab commented Mar 31, 2023

Thanks, I do want to exclude test* dependencies, but I'm still seeing those show up in the report (at least, that's where I think they are coming from). I'll have to investigate further.

@ben-manes
Copy link
Owner

You could write a custom report and exclude dependency updates that you don't care about. The plugin will resolve all configurations, though, and does not have an option to exclude particular ones.

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

No branches or pull requests

5 participants