Skip to content

Commit

Permalink
Improve accuracy of dependency resolution diagnostic
Browse files Browse the repository at this point in the history
  • Loading branch information
sambsnyd committed Nov 10, 2023
1 parent 3840fdb commit ddae3ad
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@
import org.openrewrite.internal.lang.Nullable;
import org.openrewrite.java.dependencies.table.GradleDependencyConfigurationErrors;
import org.openrewrite.java.dependencies.table.RepositoryAccessibilityReport;
import org.openrewrite.maven.MavenExecutionContextView;
import org.openrewrite.maven.MavenSettings;
import org.openrewrite.maven.internal.MavenPomDownloader;
import org.openrewrite.maven.tree.MavenRepository;
import org.openrewrite.maven.tree.MavenRepositoryMirror;
import org.openrewrite.maven.tree.MavenResolutionResult;

import java.io.UncheckedIOException;
Expand Down Expand Up @@ -62,7 +65,10 @@ public String getDescription() {
}

public static class Accumulator {
boolean foundGradle;
Set<MavenRepository> repositoriesFromGradle = new HashSet<>();

boolean foundMaven;
Set<MavenRepository> repositoriesFromMaven = new HashSet<>();
}

Expand All @@ -80,11 +86,14 @@ public TreeVisitor<?, ExecutionContext> getScanner(Accumulator acc) {
return null;
}
tree.getMarkers().findFirst(GradleProject.class).ifPresent(gp -> {
acc.foundGradle = true;
acc.repositoriesFromGradle.addAll(gp.getMavenRepositories());
acc.repositoriesFromGradle.addAll(gp.getMavenPluginRepositories());
});
tree.getMarkers().findFirst(MavenResolutionResult.class).ifPresent(mrr ->
acc.repositoriesFromMaven.addAll(mrr.getPom().getRepositories()));
tree.getMarkers().findFirst(MavenResolutionResult.class).ifPresent(mrr -> {
acc.foundMaven = true;
acc.repositoriesFromMaven.addAll(mrr.getPom().getRepositories());
});
return tree;
}
};
Expand All @@ -93,8 +102,12 @@ public TreeVisitor<?, ExecutionContext> getScanner(Accumulator acc) {
@Override
public Collection<? extends SourceFile> generate(Accumulator acc, ExecutionContext ctx) {
Set<String> seen = new HashSet<>();
record(true, acc.repositoriesFromMaven, seen, ctx);
record(false, acc.repositoriesFromGradle, seen, ctx);
if(acc.foundMaven) {
record(true, acc.repositoriesFromMaven, seen, ctx);
}
if(acc.foundGradle) {
record(false, acc.repositoriesFromGradle, seen, ctx);
}
return emptyList();
}

Expand Down Expand Up @@ -123,11 +136,21 @@ private void record(boolean addMavenDefaultRepositories, Collection<MavenReposit
if(reason == null) {
reason = new RuntimeException("Repository unreachable for unknown reason");
}
seen.add(noTrailingSlash(repo.getUri()));
report.insertRow(ctx, rowFor(repo, reason));

MavenExecutionContextView mctx = new MavenExecutionContextView(ctx);
MavenSettings settings = mctx.getSettings();
if(settings != null) {
// normalizeRepository() internally applies mirrors,but normalizeRepository() just returned null.
// Replicate mirror application so that the correct URL is recorded
repo = MavenRepositoryMirror.apply(mctx.getMirrors(settings), repo);
}
if(seen.add(noTrailingSlash(repo.getUri()))) {
report.insertRow(ctx, rowFor(repo, reason));
}
} else {
seen.add(noTrailingSlash(normalized.getUri()));
report.insertRow(ctx, rowFor(repo, null));
if(seen.add(noTrailingSlash(normalized.getUri()))) {
report.insertRow(ctx, rowFor(normalized, null));
}
}
}
}
Expand Down Expand Up @@ -156,7 +179,7 @@ private static RepositoryAccessibilityReport.Row rowFor(MavenRepository repo, @N
exceptionClass = t.getClass().getName();
exceptionMessage = t.getMessage();
}
return new RepositoryAccessibilityReport.Row(repo.getUri(), exceptionClass, exceptionMessage, httpResponseCode);
return new RepositoryAccessibilityReport.Row(noTrailingSlash(repo.getUri()), exceptionClass, exceptionMessage, httpResponseCode);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,17 @@
package org.openrewrite.java.dependencies;

import org.junit.jupiter.api.Test;
import org.openrewrite.InMemoryExecutionContext;
import org.openrewrite.Parser;
import org.openrewrite.java.dependencies.table.RepositoryAccessibilityReport;
import org.openrewrite.maven.MavenExecutionContextView;
import org.openrewrite.maven.MavenSettings;
import org.openrewrite.test.RecipeSpec;
import org.openrewrite.test.RewriteTest;

import java.io.ByteArrayInputStream;
import java.nio.file.Paths;

import static org.assertj.core.api.Assertions.assertThat;
import static org.openrewrite.gradle.Assertions.buildGradle;
import static org.openrewrite.gradle.Assertions.withToolingApi;
Expand All @@ -44,6 +51,40 @@ void gradle() {
assertThat(rows).contains(
new RepositoryAccessibilityReport.Row("https://repo.maven.apache.org/maven2", "", "", 200));
assertThat(rows).filteredOn(row -> row.getUri().startsWith("file:/") && "".equals(row.getExceptionMessage())).hasSize(1);
assertThat(rows).contains(
new RepositoryAccessibilityReport.Row("https://plugins.gradle.org/m2", "", "", 200));
assertThat(rows)
.filteredOn(row -> row.getUri().equals("https://nonexistent.moderne.io/maven2") && row.getHttpCode() == null).hasSize(1);
}),
//language=groovy
buildGradle("""
plugins {
id("java")
}
repositories {
mavenLocal()
mavenCentral()
maven {
url "https://nonexistent.moderne.io/maven2"
}
}
dependencies {
implementation("org.openrewrite.nonexistent:nonexistent:0.0.0")
}
""")
);
}


@Test
void gradleNoDefaultRepos() {
rewriteRun(
spec -> spec.beforeRecipe(withToolingApi())
// It is a limitation of the tooling API which prevents configuration-granularity error information from being collected.
// So the GradleDependencyConfigurationErrors table will never be populated in unit tests.
.dataTable(RepositoryAccessibilityReport.Row.class, rows -> {
assertThat(rows).hasSize(2);
assertThat(rows).contains(
new RepositoryAccessibilityReport.Row("https://plugins.gradle.org/m2", "", "", 200));
assertThat(rows).contains(
Expand All @@ -59,14 +100,55 @@ void gradle() {
url "https://nonexistent.moderne.io/maven2"
}
}
dependencies {
implementation("org.openrewrite.nonexistent:nonexistent:0.0.0")
}
""")
);
}

@Test
void mavenSettingsWithMirrors() {
rewriteRun(
spec -> {
MavenExecutionContextView ctx = MavenExecutionContextView.view(new InMemoryExecutionContext());
MavenSettings settings = MavenSettings.parse(new Parser.Input(Paths.get("settings.xml"), () -> new ByteArrayInputStream(
//language=xml
"""
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<mirrors>
<mirror>
<mirrorOf>*</mirrorOf>
<name>mirrored-repo</name>
<url>https://nonexistent.moderne.io/maven2</url>
<id>repo</id>
</mirror>
</mirrors>
</settings>
""".getBytes())), ctx);
ctx.setMavenSettings(settings);
spec.beforeRecipe(withToolingApi())
.dataTable(RepositoryAccessibilityReport.Row.class, rows -> {
assertThat(rows).contains(
new RepositoryAccessibilityReport.Row("https://nonexistent.moderne.io/maven2", "java.net.UnknownHostException", "nonexistent.moderne.io", null)
);
assertThat(rows).noneMatch(repo -> repo.getUri().contains("https://repo.maven.apache.org/maven2"));
})
.executionContext(ctx);
},
//language=xml
pomXml("""
<project>
<groupId>com.example</groupId>
<artifactId>test</artifactId>
<version>0.1.0</version>
</project>
""")
);
}

@Test
void maven() {
Expand All @@ -80,8 +162,8 @@ void maven() {
new RepositoryAccessibilityReport.Row("https://nonexistent.moderne.io/maven2", "java.net.UnknownHostException", "nonexistent.moderne.io", null)
);
}),
//language=xml
pomXml("""
//language=xml
pomXml("""
<project>
<groupId>com.example</groupId>
<artifactId>test</artifactId>
Expand Down

0 comments on commit ddae3ad

Please sign in to comment.