spring-gradle-plugins / dependency-management-plugin

A Gradle plugin that provides Maven-like dependency management functionality
690 stars 88 forks source link

Overriding version forces it to appear in dependencyManagement of generated POM #278

Closed mrusinak closed 4 years ago

mrusinak commented 4 years ago

Cross-posting from https://github.com/spring-projects/spring-boot/issues/21508 by request.

This behavior is seen with the Springboot Plugin 2.2.0 and greater. Springboot plugins 2.1.X do not exhibit this behavior, nor does changing the version of the dependency management plugin seem to have any effect.

. Example Gradle file:

import org.springframework.boot.gradle.plugin.SpringBootPlugin

plugins {
    id 'java'
    id 'maven-publish'
    id 'org.springframework.boot' version '2.3.0.RELEASE' apply false
    id 'io.spring.dependency-management' version '1.0.9.RELEASE'
}

repositories {
    mavenCentral()
}

publishing {
    publications {
        maven(MavenPublication) {
            from project.components.java
        }
    }
}

dependencyManagement {
    imports {
        mavenBom SpringBootPlugin.BOM_COORDINATES
    }
}

// TODO: Comment this line off/on to see changes
ext['mockito.version'] = '2.23.4'

POM file was then generated with Gradle generatePomFileForMavenPublication. When the version override is active, the POM is generated with:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-junit-jupiter</artifactId>
      <version>2.23.4</version>
    </dependency>
    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-core</artifactId>
      <version>2.23.4</version>
    </dependency>
    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-inline</artifactId>
      <version>2.23.4</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>2.3.0.RELEASE</version>
      <scope>import</scope>
      <type>pom</type>
    </dependency>
  </dependencies>
</dependencyManagement>

When the version override is commented out, I correctly get:

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>2.3.0.RELEASE</version>
        <scope>import</scope>
        <type>pom</type>
      </dependency>
    </dependencies>
  </dependencyManagement>

While I could argue that this trivial example is actually working correctly, the real-life situation of overriding test-scope-only versions bleeding into the published POM is less desirable.

It would be nice that If I did have something like testImplementation "org.mockito:mockito-core", then the plugin would be smart enough to exclude that from <dependencyManagement> (or have some way to configure it to do so)

wilkinsona commented 4 years ago

Thanks for opening the issue over here.

I think this may be quite hard to implement in a way that works reliably for all cases. The entire transitive dependency graph of every dependency that appears in the pom would have to be considered when deciding whether or not to add the overriding entries to the published pom. I’d need to investigate to see if that information is readily available during pom generation.

If the dependencies covered by the dependency management overrides are not present in the transitive graph of those declared in the pom it will have no effect. If they are present then their versions will be managed as expected. If this holds true, the problem reported here is entirely cosmetic. Have I overlooked a functional problem that the overriding dependency management causes?

spring-projects-issues commented 4 years ago

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

mrusinak commented 4 years ago

Sorry for the delay.

The problem I ran into was between a library and consuming service. The library for one reason or other was forcing a particular version of Mockito for its tests. This caused the test-only version override to appear in it's manifest, which the consuming service then picked up (which was not explicitly declaring a version)

wilkinsona commented 4 years ago

Thanks, @mrusinak. Unfortunately, I don't think I understand the behaviour that you have described. Unless a consumer of the library was using the library as its parent, the dependency management in the library should have no effect on the consumer. Have I misunderstood?

mrusinak commented 4 years ago

Ill have to setup a test again to confirm, but I believe the version from the library wound up coming across via transitive dependency resolution. I should be able to do that within the week.

mrusinak commented 4 years ago

Recreated independent library & service test setup, and I can confirm that there must have been an error in my earlier test - having the override version in the library's POM did not affect the service's version through transitive dependencies.

Sorry about that. I agree in that case that this does seem to be mostly a cosmetic issue!

wilkinsona commented 4 years ago

Not at all. Thanks for taking the time to follow up. Given that the problem is only cosmetic and the anticipated difficulty of implementing a robust fix, the risks of making a change seem to outweigh the benefits. I’m going to close this one. It can be reconsidered if there is a scenario in the future that is more than cosmetic.