rewrite icon indicating copy to clipboard operation
rewrite copied to clipboard

Recipe AddDependency doesn't remove version when there is a managed dependency

Open timtebeek opened this issue 1 year ago • 1 comments

Discussed in https://github.com/openrewrite/rewrite/discussions/4313

Originally posted by @rregout July 10, 2024 I have created a rewrite.yml with the following recipe list:

type: specs.openrewrite.org/v1beta/recipe
name: com.example.AddSpringBootStarterDependency
displayName: Add Maven dependency example
recipeList:
  - org.openrewrite.maven.AddManagedDependency:
      groupId: org.springframework.boot
      artifactId: spring-boot-dependencies
      version: 3.3.1
      type: pom
      scope: import
      addToRootPom: true
  - org.openrewrite.maven.AddDependency:
      groupId: org.springframework.boot
      artifactId: spring-boot-starter
      onlyIfUsing: javax.ejb.Singleton
      version: 3.3.1

With this a simple module project:

A parent pom:

<project>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>parent-project</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>services</module>
    </modules>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>javax</groupId>
                <artifactId>javaee-api</artifactId>
                <version>7.0</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

and a module pom:

<project>
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>com.example</groupId>
        <artifactId>parent-project</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>services</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
        </dependency>
    </dependencies>

</project>

And within the module an example Java class:

package com.example;

import javax.ejb.Singleton;

@Singleton
public class SingletonExample {

}

After running the command mvn -U org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=com.example.AddSpringBootStarterDependency the result is a parent pom with

<project>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>parent-project</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>services</module>
    </modules>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>javax</groupId>
                <artifactId>javaee-api</artifactId>
                <version>7.0</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>3.3.1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

and the module with:

<project>
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>com.example</groupId>
        <artifactId>parent-project</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>services</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>3.3.1</version>
        </dependency>
    </dependencies>

</project>

Why is the version of the dependency spring-boot-starter still in the module pom? It should use the one in de managed dependencies of the parent pom and not adding the version to the module pom.

timtebeek avatar Jul 11 '24 10:07 timtebeek

@rregout I've replicate the above with a unit test in AddManagedDependencyTest. Not sure yet why this problem occurs. I suspect this update to the Maven model might not have occurred by the time we get to Add the non-managed dependendency. https://github.com/openrewrite/rewrite/blob/98efffd877dabb522705d00b050dc2551912488f/rewrite-maven/src/main/java/org/openrewrite/maven/AddManagedDependency.java#L217-L219

Welcome to explore further using this test on a draft PR; I don't have time to follow up right now, but would like to see this resolved too.

@Test
@Issue("https://github.com/openrewrite/rewrite/discussions/4313")
void addManagedFirstDependencySecond() {
    rewriteRun(
      spec -> spec.recipeFromYaml(
        """
          type: specs.openrewrite.org/v1beta/recipe
          name: com.example.AddSpringBootStarterDependency
          displayName: Add Maven dependency example
          recipeList:
            - org.openrewrite.maven.AddManagedDependency:
                groupId: org.springframework.boot
                artifactId: spring-boot-dependencies
                version: 3.3.1
                type: pom
                scope: import
                addToRootPom: true
            - org.openrewrite.maven.AddDependency:
                groupId: org.springframework.boot
                artifactId: spring-boot-starter
                onlyIfUsing: java.lang.String
                version: 3.3.1
          """,
        "com.example.AddSpringBootStarterDependency"
      ),
      mavenProject("parent",
        pomXml(
          """
            <project>
                <modelVersion>4.0.0</modelVersion>
                <groupId>com.example</groupId>
                <artifactId>parent-project</artifactId>
                <version>0.0.1-SNAPSHOT</version>
                <packaging>pom</packaging>
                <modules>
                    <module>services</module>
                </modules>
                <dependencyManagement>
                    <dependencies>
                        <dependency>
                            <groupId>javax</groupId>
                            <artifactId>javaee-api</artifactId>
                            <version>7.0</version>
                        </dependency>
                    </dependencies>
                </dependencyManagement>
            </project>
            """,
          """
            <project>
                <modelVersion>4.0.0</modelVersion>
                <groupId>com.example</groupId>
                <artifactId>parent-project</artifactId>
                <version>0.0.1-SNAPSHOT</version>
                <packaging>pom</packaging>
                <modules>
                    <module>services</module>
                </modules>
                <dependencyManagement>
                    <dependencies>
                        <dependency>
                            <groupId>javax</groupId>
                            <artifactId>javaee-api</artifactId>
                            <version>7.0</version>
                        </dependency>
                        <dependency>
                            <groupId>org.springframework.boot</groupId>
                            <artifactId>spring-boot-dependencies</artifactId>
                            <version>3.3.1</version>
                            <type>pom</type>
                            <scope>import</scope>
                        </dependency>
                    </dependencies>
                </dependencyManagement>
            </project>
            """
        ),
        mavenProject("services",
          srcMainJava(
            java(
              """
                class Foo {
                    String message;
                }
                """
            )
          ),
          pomXml(
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <parent>
                      <groupId>com.example</groupId>
                      <artifactId>parent-project</artifactId>
                      <version>0.0.1-SNAPSHOT</version>
                  </parent>
                  <artifactId>services</artifactId>
                  <version>0.0.1-SNAPSHOT</version>
                  <dependencies>
                      <dependency>
                          <groupId>javax</groupId>
                          <artifactId>javaee-api</artifactId>
                      </dependency>
                  </dependencies>
              </project>
              """,
            // Child pom should not have an explicit version, as the parent manages the same version
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <parent>
                      <groupId>com.example</groupId>
                      <artifactId>parent-project</artifactId>
                      <version>0.0.1-SNAPSHOT</version>
                  </parent>
                  <artifactId>services</artifactId>
                  <version>0.0.1-SNAPSHOT</version>
                  <dependencies>
                      <dependency>
                          <groupId>javax</groupId>
                          <artifactId>javaee-api</artifactId>
                      </dependency>
                      <dependency>
                          <groupId>org.springframework.boot</groupId>
                          <artifactId>spring-boot-starter</artifactId>
                      </dependency>
                  </dependencies>
              </project>
              """
          )
        )
      )
    );
}

timtebeek avatar Jul 11 '24 10:07 timtebeek