openrewrite / rewrite

Automated mass refactoring of source code.

Home Page:https://docs.openrewrite.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

timtebeek opened this issue · comments

Discussed in #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.

@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.

doAfterVisit(new AddManagedDependencyVisitor(groupId, artifactId,
versionToUse, scope, type, classifier));
maybeUpdateModel();

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>
              """
          )
        )
      )
    );
}