openrewrite / openrewrite/rewrite

Maven add missing version to a dependency

Open
#6,770 11 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Java
Stars
3.7k
Forks
571
Avg merge
13h 12m
Merged PRs (30d)
261

Description

What problem are you trying to solve?

Spring boot and other frameworks manage dependencies. It can happen the dependency is removed from the dependencies management part. After migration to the new parent version, your application will complain the version of the dependency is missing. This happens when you migrate to Spring Boot 4 for dependencies spring-retry and rest-assured.

What precondition(s) should be checked before applying this recipe?

If the dependency has a version or not.

Description recipe

The recipe should follow the input of other maven recipes like upgradeparentversion.

  • groupId
  • artifactId
  • newVersion
  • versionPattern
    Optional is acceptTransitive like with recipe AddDependency. To not add the version if dependency is found in management dependency.

Draft recipe

`
@Value
@EqualsAndHashCode(callSuper = false)
public class ExplicitAddDependencyVersion extends Recipe {

@Getter
final String displayName = "Add version to dependency";

@Getter
final String description =
        "Add version to a dependency that is missing it. This can be required when dependency is not managed anymore by a parent pom.";

@Option(
        displayName = "Group",
        description = "The first part of a dependency coordinate `com.google.guava:guava:VERSION`.",
        example = "com.google.guava")
String groupId;

@Option(
        displayName = "Artifact",
        description = "The second part of a dependency coordinate `com.google.guava:guava:VERSION`.",
        example = "guava")
String artifactId;

@Option(
        displayName = "Version",
        description = "An exact version number or node-style semver selector used to select the version number.",
        example = "29.X")
String newVersion;

@Override
public Validated<Object> validate() {
    Validated<Object> validated = super.validate();
    //noinspection ConstantConditions
    if (newVersion != null) {
        validated = validated.and(Semver.validate(newVersion, null));
    }

    return validated;
}

@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
    return new MavenIsoVisitor<>() {
        @Override
        public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) {
            Xml.Tag t = super.visitTag(tag, ctx);
            if (isDependencyTag(groupId, artifactId)) {
                if (t.getChildValue("version").isEmpty()) {
                    Xml.Tag versionTag = Xml.Tag.build("<version>" + newVersion + "</version>");

                    t = (Xml.Tag)
                            new AddToTagVisitor<>(t, versionTag, new MavenTagInsertionComparator(t.getChildren()))
                                    .visitNonNull(t, 0, getCursor().getParent());
                    maybeUpdateModel();
                }
            }
            return t;
        }
    };
}

}
`

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Use the drafted ExplicitAddDependencyVersion recipe as the entry point, and compare its inputs and visitor behavior with the upgradeparentversion and AddDependency recipes. Check how managed dependencies and transitive dependencies should affect the precondition. Done means a targeted dependency receives the requested version only when it lacks one and is not managed elsewhere.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
build-system
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.