Skip to content

Commit 56cc9f0

Browse files
Report overwritten managed dependency versions (closes #161)
Co-authored-by: sanagaraj-pivotal <[email protected]>
1 parent f500e93 commit 56cc9f0

File tree

4 files changed

+768
-0
lines changed

4 files changed

+768
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright 2021 - 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.sbm.boot.upgrade_27_30.checks;
18+
19+
import org.springframework.sbm.boot.asciidoctor.ChangeSection;
20+
import org.springframework.sbm.boot.asciidoctor.Section;
21+
import org.springframework.sbm.boot.asciidoctor.TodoList;
22+
import org.springframework.sbm.boot.upgrade_27_30.Sbu30_PreconditionCheck;
23+
import org.springframework.sbm.boot.upgrade_27_30.Sbu30_PreconditionCheckResult;
24+
import org.springframework.sbm.boot.upgrade_27_30.Sbu30_UpgradeSectionBuilder;
25+
import org.springframework.sbm.engine.context.ProjectContext;
26+
import org.springframework.stereotype.Component;
27+
28+
import java.util.List;
29+
import java.util.Set;
30+
import java.util.stream.Collectors;
31+
32+
@Component
33+
public class RedeclaredDependenciesBuilder implements Sbu30_UpgradeSectionBuilder {
34+
private final RedeclaredDependenciesFinder finder;
35+
36+
public RedeclaredDependenciesBuilder(RedeclaredDependenciesFinder finder) {
37+
this.finder = finder;
38+
}
39+
40+
@Override
41+
public boolean isApplicable(ProjectContext projectContext) {
42+
return !finder.findMatches(projectContext).isEmpty();
43+
}
44+
45+
@Override
46+
public Section build(ProjectContext projectContext) {
47+
Set<RedeclaredDependenciesFinder.RedeclaredDependency> matches = finder.findMatches(projectContext);
48+
List<TodoList.Todo> todos = matches.stream()
49+
.map(m -> TodoList.Todo.builder()
50+
.text(String.format("Remove explicit declaration of version for artifact: %s, its already declared with version %s", m.getRedeclaredDependency().getCoordinates(), m.originalVersion()))
51+
.build()).toList();
52+
53+
return ChangeSection.RelevantChangeSection.builder()
54+
.title("Remove redundant explicit version declaration")
55+
.relevanceSection()
56+
.paragraph("""
57+
The scan found one or more redeclared dependencies in build files.
58+
Please check them and remove redundant declarations.
59+
"""
60+
)
61+
.todoSection()
62+
.todoList(TodoList.builder()
63+
.todos(todos)
64+
.build())
65+
.build();
66+
}
67+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright 2021 - 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.sbm.boot.upgrade_27_30.checks;
18+
19+
import org.jetbrains.annotations.NotNull;
20+
import org.openrewrite.maven.tree.MavenResolutionResult;
21+
import org.openrewrite.maven.tree.ResolvedManagedDependency;
22+
import org.springframework.sbm.build.api.ApplicationModule;
23+
import org.springframework.sbm.build.api.Dependency;
24+
import org.springframework.sbm.build.impl.OpenRewriteMavenBuildFile;
25+
import org.springframework.sbm.engine.context.ProjectContext;
26+
import org.springframework.stereotype.Component;
27+
28+
import java.util.HashSet;
29+
import java.util.List;
30+
import java.util.Map;
31+
import java.util.Set;
32+
import java.util.stream.Collectors;
33+
34+
@Component
35+
public class RedeclaredDependenciesFinder implements Sbm30_Finder<Set<Dependency>> {
36+
private final Set<String> analysingDependencies = new HashSet<>();
37+
38+
public RedeclaredDependenciesFinder() {
39+
}
40+
41+
public RedeclaredDependenciesFinder(Set<String> analysingDependencies) {
42+
this.analysingDependencies.addAll(analysingDependencies);
43+
}
44+
45+
@NotNull
46+
@Override
47+
public Set<RedeclaredDependency> findMatches(ProjectContext context) {
48+
Set<RedeclaredDependency> result = new HashSet<>();
49+
context.getApplicationModules().stream()
50+
.forEach(am -> {
51+
List<org.openrewrite.maven.tree.Dependency> requestedDependencies = ((MavenResolutionResult) (((OpenRewriteMavenBuildFile) am.getBuildFile()).getPom())).getPom().getRequestedDependencies();
52+
Map<String, String> managedMap = prepareManagedDependenciesMap(am);
53+
List<Dependency> declaredDependencies = am.getBuildFile().getDeclaredDependencies();
54+
Set<RedeclaredDependency> redeclaredDependencies = requestedDependencies.stream()
55+
.filter(d -> analysingDependencies.isEmpty() || analysingDependencies.contains(getGroupAndArtifactKey(d)))
56+
.filter(d -> d.getVersion() != null && !d.getVersion().isEmpty())
57+
.filter(d -> managedMap.containsKey(getGroupAndArtifactKey(d)))
58+
.map(d -> {
59+
Dependency dependency = Dependency.builder().groupId(d.getGroupId()).artifactId(d.getArtifactId()).version(d.getVersion()).build();
60+
return new RedeclaredDependency(dependency, managedMap.get(getGroupAndArtifactKey(d)));
61+
})
62+
.collect(Collectors.toSet());
63+
result.addAll(redeclaredDependencies);
64+
});
65+
return result;
66+
}
67+
68+
@NotNull
69+
private Map<String, String> prepareManagedDependenciesMap(ApplicationModule am) {
70+
List<ResolvedManagedDependency> managedDependencies = ((MavenResolutionResult) (((OpenRewriteMavenBuildFile) am.getBuildFile()).getPom())).getPom().getDependencyManagement();
71+
return managedDependencies.stream()
72+
.filter(d -> d.getVersion() != null && !d.getVersion().isEmpty())
73+
.collect(Collectors.toMap(this::getGroupAndArtifactKeyResolved, ResolvedManagedDependency::getVersion, (d1, d2) -> d2));
74+
}
75+
76+
@NotNull
77+
private String getGroupAndArtifactKeyResolved(ResolvedManagedDependency d) {
78+
return d.getGroupId() + ":" + d.getArtifactId();
79+
}
80+
81+
@NotNull
82+
private String getGroupAndArtifactKey(org.openrewrite.maven.tree.Dependency d) {
83+
return d.getGroupId() + ":" + d.getArtifactId();
84+
}
85+
86+
public record RedeclaredDependency(Dependency redeclaredDependency,
87+
String originalVersion) {
88+
89+
public Dependency getRedeclaredDependency() {
90+
return redeclaredDependency;
91+
}
92+
93+
public String getOriginalVersion() {
94+
return originalVersion;
95+
}
96+
}
97+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
* Copyright 2021 - 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.sbm.boot.upgrade_27_30.checks;
18+
19+
import org.junit.jupiter.api.Test;
20+
import org.springframework.sbm.boot.asciidoctor.ChangeSection;
21+
import org.springframework.sbm.boot.asciidoctor.Section;
22+
import org.springframework.sbm.boot.asciidoctor.TodoList;
23+
import org.springframework.sbm.boot.upgrade_27_30.checks.RedeclaredDependenciesFinder.RedeclaredDependency;
24+
import org.springframework.sbm.build.api.ApplicationModule;
25+
import org.springframework.sbm.build.api.Dependency;
26+
import org.springframework.sbm.engine.context.ProjectContext;
27+
28+
import java.util.List;
29+
import java.util.Set;
30+
import java.util.stream.Collectors;
31+
32+
import static org.assertj.core.api.Assertions.assertThat;
33+
import static org.mockito.Mockito.mock;
34+
import static org.mockito.Mockito.when;
35+
36+
/*
37+
* Copyright 2021 - 2022 the original author or authors.
38+
*
39+
* Licensed under the Apache License, Version 2.0 (the "License");
40+
* you may not use this file except in compliance with the License.
41+
* You may obtain a copy of the License at
42+
*
43+
* https://www.apache.org/licenses/LICENSE-2.0
44+
*
45+
* Unless required by applicable law or agreed to in writing, software
46+
* distributed under the License is distributed on an "AS IS" BASIS,
47+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
48+
* See the License for the specific language governing permissions and
49+
* limitations under the License.
50+
*/
51+
52+
public class RedeclaredDependenciesBuilderTest {
53+
54+
@Test
55+
void shouldBuildSectionWhenFinderHasMatches() {
56+
Set<RedeclaredDependency> matches = Set.of(new RedeclaredDependency(
57+
Dependency.builder()
58+
.groupId("test.group")
59+
.artifactId("test-artifact")
60+
.version("2.0.0")
61+
.build(),
62+
"1.0.0"
63+
));
64+
65+
ProjectContext context = mock(ProjectContext.class);
66+
RedeclaredDependenciesFinder finder = mock(RedeclaredDependenciesFinder.class);
67+
when(finder.findMatches(context)).thenReturn(matches);
68+
RedeclaredDependenciesBuilder builder = new RedeclaredDependenciesBuilder(finder);
69+
assertThat(builder.isApplicable(context)).isTrue();
70+
}
71+
72+
@Test
73+
void shouldBuildSectionWhenFinderHasNoMatches() {
74+
Set<RedeclaredDependency> matches = Set.of();
75+
ProjectContext context = mock(ProjectContext.class);
76+
RedeclaredDependenciesFinder finder = mock(RedeclaredDependenciesFinder.class);
77+
when(finder.findMatches(context)).thenReturn(matches);
78+
RedeclaredDependenciesBuilder builder = new RedeclaredDependenciesBuilder(finder);
79+
assertThat(builder.isApplicable(context)).isFalse();
80+
}
81+
82+
@Test
83+
void assertContent() {
84+
85+
Set<RedeclaredDependency> matches = Set.of(new RedeclaredDependency(
86+
Dependency.builder()
87+
.groupId("test.group")
88+
.artifactId("test-artifact")
89+
.version("2.0.0")
90+
.build(),
91+
"1.0.0"
92+
),
93+
new RedeclaredDependency(
94+
Dependency.builder()
95+
.groupId("test.group")
96+
.artifactId("test-artifact2")
97+
.version("3.0.0")
98+
.build(),
99+
"2.0.0"
100+
));
101+
102+
ProjectContext context = mock(ProjectContext.class);
103+
RedeclaredDependenciesFinder finder = mock(RedeclaredDependenciesFinder.class);
104+
when(finder.findMatches(context)).thenReturn(matches);
105+
RedeclaredDependenciesBuilder builder = new RedeclaredDependenciesBuilder(finder);
106+
107+
Section section = builder.build(context);
108+
109+
assertThat(section).isInstanceOf(ChangeSection.class);
110+
ChangeSection relevantChangeSection = ChangeSection.class.cast(section);
111+
assertThat(relevantChangeSection.getTitle()).isEqualTo("Remove redundant explicit version declaration");
112+
assertThat(relevantChangeSection.getRelevanceSection()).isNotNull();
113+
assertThat(relevantChangeSection.getRelevanceSection().getParagraphs()).hasSize(1);
114+
assertThat(relevantChangeSection.getRelevanceSection().getParagraphs().get(0).getText()).isEqualTo("""
115+
The scan found one or more redeclared dependencies in build files.
116+
Please check them and remove redundant declarations.
117+
""");
118+
List<TodoList.Todo> todos = relevantChangeSection.getTodoSection().getTodoLists().get(0).getTodos();
119+
List<String> stringToDos = todos.stream()
120+
.map(TodoList.Todo::getText)
121+
.collect(Collectors.toList());
122+
assertThat(stringToDos).contains("Remove explicit declaration of version for artifact: test.group:test-artifact:2.0.0, its already declared with version 1.0.0");
123+
assertThat(stringToDos).contains("Remove explicit declaration of version for artifact: test.group:test-artifact2:3.0.0, its already declared with version 2.0.0");
124+
}
125+
}

0 commit comments

Comments
 (0)