From 4f224826f20ff1307baacb7865d1c756a23efc0a Mon Sep 17 00:00:00 2001 From: Guillaume Le Floch Date: Tue, 8 Sep 2020 12:12:08 +0200 Subject: [PATCH] handle gradle included builds --- .../gradle/builder/QuarkusModelBuilder.java | 43 ++++++++++++++++--- .../resolver/QuarkusGradleModelFactory.java | 5 ++- .../resolver/model/impl/WorkspaceImpl.java | 1 + .../gradle/QuarkusGradleWrapperTestBase.java | 1 + .../devmode/MultiModuleIncludedBuildTest.java | 43 +++++++++++++++++++ .../devmode/QuarkusDevGradleTestBase.java | 2 +- .../app/build.gradle | 29 +++++++++++++ .../app/settings.gradle | 12 ++++++ .../main/java/org/acme/ExampleResource.java | 22 ++++++++++ .../src/main/resources/application.properties | 2 + .../external-library/build.gradle | 29 +++++++++++++ .../external-library/settings.gradle | 18 ++++++++ .../main/java/org/acme/lib/LibService.java | 10 +++++ .../src/main/resources/META-INF/beans.xml | 0 .../gradle.properties | 4 ++ 15 files changed, 212 insertions(+), 9 deletions(-) create mode 100644 integration-tests/gradle/src/test/java/io/quarkus/gradle/devmode/MultiModuleIncludedBuildTest.java create mode 100644 integration-tests/gradle/src/test/resources/multi-module-included-build/app/build.gradle create mode 100644 integration-tests/gradle/src/test/resources/multi-module-included-build/app/settings.gradle create mode 100644 integration-tests/gradle/src/test/resources/multi-module-included-build/app/src/main/java/org/acme/ExampleResource.java create mode 100644 integration-tests/gradle/src/test/resources/multi-module-included-build/app/src/main/resources/application.properties create mode 100644 integration-tests/gradle/src/test/resources/multi-module-included-build/external-library/build.gradle create mode 100644 integration-tests/gradle/src/test/resources/multi-module-included-build/external-library/settings.gradle create mode 100644 integration-tests/gradle/src/test/resources/multi-module-included-build/external-library/src/main/java/org/acme/lib/LibService.java create mode 100644 integration-tests/gradle/src/test/resources/multi-module-included-build/external-library/src/main/resources/META-INF/beans.xml create mode 100644 integration-tests/gradle/src/test/resources/multi-module-included-build/gradle.properties diff --git a/devtools/gradle/src/main/java/io/quarkus/gradle/builder/QuarkusModelBuilder.java b/devtools/gradle/src/main/java/io/quarkus/gradle/builder/QuarkusModelBuilder.java index 188b1b0bcbd01..7dd87f0b30067 100644 --- a/devtools/gradle/src/main/java/io/quarkus/gradle/builder/QuarkusModelBuilder.java +++ b/devtools/gradle/src/main/java/io/quarkus/gradle/builder/QuarkusModelBuilder.java @@ -26,6 +26,7 @@ import org.gradle.api.GradleException; import org.gradle.api.Project; import org.gradle.api.Task; +import org.gradle.api.UnknownDomainObjectException; import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.ExternalModuleDependency; import org.gradle.api.artifacts.ModuleDependency; @@ -35,6 +36,7 @@ import org.gradle.api.artifacts.ResolvedDependency; import org.gradle.api.artifacts.component.ProjectComponentIdentifier; import org.gradle.api.attributes.Category; +import org.gradle.api.initialization.IncludedBuild; import org.gradle.api.internal.artifacts.dependencies.DefaultDependencyArtifact; import org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency; import org.gradle.api.plugins.Convention; @@ -45,6 +47,7 @@ import io.quarkus.bootstrap.BootstrapConstants; import io.quarkus.bootstrap.model.AppArtifactKey; +import io.quarkus.bootstrap.resolver.QuarkusGradleModelFactory; import io.quarkus.bootstrap.resolver.model.ArtifactCoords; import io.quarkus.bootstrap.resolver.model.Dependency; import io.quarkus.bootstrap.resolver.model.ModelParameter; @@ -103,9 +106,9 @@ public Object buildAll(String modelName, ModelParameter parameter, Project proje final Map appDependencies = new LinkedHashMap<>(); final Set visitedDeps = new HashSet<>(); - final ResolvedConfiguration configuration = classpathConfig(project, mode).getResolvedConfiguration(); - collectDependencies(configuration, mode, project, appDependencies); - collectFirstMetDeploymentDeps(configuration.getFirstLevelModuleDependencies(), appDependencies, + final ResolvedConfiguration resolvedConfiguration = classpathConfig(project, mode).getResolvedConfiguration(); + collectDependencies(resolvedConfiguration, mode, project, appDependencies); + collectFirstMetDeploymentDeps(resolvedConfiguration.getFirstLevelModuleDependencies(), appDependencies, deploymentDeps, visitedDeps); final List extensionDependencies = collectExtensionDependencies(project, deploymentDeps); @@ -113,7 +116,8 @@ public Object buildAll(String modelName, ModelParameter parameter, Project proje ArtifactCoords appArtifactCoords = new ArtifactCoordsImpl(project.getGroup().toString(), project.getName(), project.getVersion().toString()); - return new QuarkusModelImpl(new WorkspaceImpl(appArtifactCoords, getWorkspace(project.getRootProject(), mode)), + return new QuarkusModelImpl( + new WorkspaceImpl(appArtifactCoords, getWorkspace(project.getRootProject(), mode)), new LinkedList<>(appDependencies.values()), extensionDependencies, deploymentDeps.stream().map(QuarkusModelBuilder::toEnforcedPlatformDependency) @@ -317,8 +321,10 @@ private List collectExtensionDependencies(Project project, private void collectDependencies(ResolvedConfiguration configuration, LaunchMode mode, Project project, Map appDependencies) { + final Set artifacts = configuration.getResolvedArtifacts(); Set artifactFiles = null; + // if the number of artifacts is less than the number of files then probably // the project includes direct file dependencies if (artifacts.size() < configuration.getFiles().size()) { @@ -331,9 +337,14 @@ private void collectDependencies(ResolvedConfiguration configuration, final DependencyImpl dep = initDependency(a); if (LaunchMode.DEVELOPMENT.equals(mode) && a.getId().getComponentIdentifier() instanceof ProjectComponentIdentifier) { - Project projectDep = project.getRootProject() - .findProject(((ProjectComponentIdentifier) a.getId().getComponentIdentifier()).getProjectPath()); - addDevModePaths(dep, a, projectDep); + IncludedBuild includedBuild = includedBuild(project, a.getName()); + if (includedBuild != null) { + addSubstitutedProject(dep, includedBuild.getProjectDir(), mode); + } else { + Project projectDep = project.getRootProject() + .findProject(((ProjectComponentIdentifier) a.getId().getComponentIdentifier()).getProjectPath()); + addDevModePaths(dep, a, projectDep); + } } else { dep.addPath(a.getFile()); } @@ -402,6 +413,24 @@ private void addDevModePaths(final DependencyImpl dep, ResolvedArtifact a, Proje } } + private void addSubstitutedProject(final DependencyImpl dep, File projectFile, LaunchMode mode) { + final QuarkusModel quarkusModel = QuarkusGradleModelFactory.create(projectFile, mode.name()); + final io.quarkus.bootstrap.resolver.model.SourceSet moduleOutput = quarkusModel.getWorkspace().getMainModule() + .getSourceSet(); + dep.addPath(moduleOutput.getResourceDirectory()); + for (File sourceDirectory : moduleOutput.getSourceDirectories()) { + dep.addPath(sourceDirectory); + } + } + + private IncludedBuild includedBuild(final Project project, final String projectName) { + try { + return project.getGradle().includedBuild(projectName); + } catch (UnknownDomainObjectException ignore) { + return null; + } + } + private SourceSetImpl convert(SourceSet sourceSet) { if (sourceSet.getOutput().getResourcesDir().exists()) { return new SourceSetImpl( diff --git a/independent-projects/bootstrap/gradle-resolver/src/main/java/io/quarkus/bootstrap/resolver/QuarkusGradleModelFactory.java b/independent-projects/bootstrap/gradle-resolver/src/main/java/io/quarkus/bootstrap/resolver/QuarkusGradleModelFactory.java index 3a898a83867c9..46db36ca3cb52 100644 --- a/independent-projects/bootstrap/gradle-resolver/src/main/java/io/quarkus/bootstrap/resolver/QuarkusGradleModelFactory.java +++ b/independent-projects/bootstrap/gradle-resolver/src/main/java/io/quarkus/bootstrap/resolver/QuarkusGradleModelFactory.java @@ -19,6 +19,7 @@ public static QuarkusModel create(File projectDir, String mode, List jvm .forProjectDirectory(projectDir) .connect()) { connection.newBuild().forTasks(tasks).addJvmArguments(jvmArgs).run(); + return connection.action(new QuarkusModelBuildAction(mode)).run(); } } @@ -28,7 +29,9 @@ public static QuarkusModel createForTasks(File projectDir, String... tasks) { .forProjectDirectory(projectDir) .connect()) { final ModelBuilder modelBuilder = connection.model(QuarkusModel.class); - modelBuilder.forTasks(tasks); + if (tasks.length != 0) { + modelBuilder.forTasks(tasks); + } return modelBuilder.get(); } } diff --git a/independent-projects/bootstrap/gradle-resolver/src/main/java/io/quarkus/bootstrap/resolver/model/impl/WorkspaceImpl.java b/independent-projects/bootstrap/gradle-resolver/src/main/java/io/quarkus/bootstrap/resolver/model/impl/WorkspaceImpl.java index bba576057fc4a..339aacaebc6f6 100644 --- a/independent-projects/bootstrap/gradle-resolver/src/main/java/io/quarkus/bootstrap/resolver/model/impl/WorkspaceImpl.java +++ b/independent-projects/bootstrap/gradle-resolver/src/main/java/io/quarkus/bootstrap/resolver/model/impl/WorkspaceImpl.java @@ -35,4 +35,5 @@ public Collection getAllModules() { public WorkspaceModule getModule(ArtifactCoords key) { return modules.get(key); } + } diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/QuarkusGradleWrapperTestBase.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/QuarkusGradleWrapperTestBase.java index 6e1b65198251b..18d7b7fb4f6e4 100644 --- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/QuarkusGradleWrapperTestBase.java +++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/QuarkusGradleWrapperTestBase.java @@ -33,6 +33,7 @@ public BuildResult runGradleWrapper(File projectDir, String... args) throws IOEx .directory(projectDir) .command(command) .redirectInput(ProcessBuilder.Redirect.INHERIT) + .redirectError(logOutput) .redirectOutput(logOutput) .redirectError(logOutput) .start(); diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/devmode/MultiModuleIncludedBuildTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/devmode/MultiModuleIncludedBuildTest.java new file mode 100644 index 0000000000000..df62fb2198014 --- /dev/null +++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/devmode/MultiModuleIncludedBuildTest.java @@ -0,0 +1,43 @@ +package io.quarkus.gradle.devmode; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +public class MultiModuleIncludedBuildTest extends QuarkusDevGradleTestBase { + + @Override + protected String projectDirectoryName() { + return "multi-module-included-build"; + } + + @Override + protected String[] buildArguments() { + return new String[] { "clean", "--include-build", "../external-library", "quarkusDev" }; + } + + @Override + protected void testDevMode() throws Exception { + assertThat(getHttpResponse("/hello")).contains("foo bar"); + } + + @Override + protected File getProjectDir() { + File projectDir = super.getProjectDir(); + final File appProjectProperties = new File(projectDir, "app/gradle.properties"); + final File libProjectProperties = new File(projectDir, "external-library/gradle.properties"); + final Path projectProperties = projectDir.toPath().resolve("gradle.properties"); + + try { + Files.copy(projectProperties, appProjectProperties.toPath()); + Files.copy(projectProperties, libProjectProperties.toPath()); + } catch (IOException e) { + throw new IllegalStateException("Unable to copy gradle.properties file", e); + } + this.projectDir = appProjectProperties.getParentFile(); + return this.projectDir; + } +} diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/devmode/QuarkusDevGradleTestBase.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/devmode/QuarkusDevGradleTestBase.java index 166edbd198eec..ffb6f7d7d1f2a 100644 --- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/devmode/QuarkusDevGradleTestBase.java +++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/devmode/QuarkusDevGradleTestBase.java @@ -28,7 +28,7 @@ public abstract class QuarkusDevGradleTestBase extends QuarkusGradleWrapperTestB private static final String PLUGIN_UNDER_TEST_METADATA_PROPERTIES = "plugin-under-test-metadata.properties"; private Future quarkusDev; - private File projectDir; + protected File projectDir; @Test public void main() throws Exception { diff --git a/integration-tests/gradle/src/test/resources/multi-module-included-build/app/build.gradle b/integration-tests/gradle/src/test/resources/multi-module-included-build/app/build.gradle new file mode 100644 index 0000000000000..21b65330ee69c --- /dev/null +++ b/integration-tests/gradle/src/test/resources/multi-module-included-build/app/build.gradle @@ -0,0 +1,29 @@ +plugins { + id 'java' + id 'io.quarkus' +} + +repositories { + mavenCentral() + if (System.properties.containsKey('maven.repo.local')) { + maven { + url System.properties.get('maven.repo.local') + } + } else { + mavenLocal() + } +} + +dependencies { + implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}") + implementation 'io.quarkus:quarkus-resteasy' + implementation 'org.acme:external-library:1.0.0-SNAPSHOT' +} + +group 'org.acme' +version '1.0.0-SNAPSHOT' + +compileJava { + options.encoding = 'UTF-8' + options.compilerArgs << '-parameters' +} diff --git a/integration-tests/gradle/src/test/resources/multi-module-included-build/app/settings.gradle b/integration-tests/gradle/src/test/resources/multi-module-included-build/app/settings.gradle new file mode 100644 index 0000000000000..80745a0d871b8 --- /dev/null +++ b/integration-tests/gradle/src/test/resources/multi-module-included-build/app/settings.gradle @@ -0,0 +1,12 @@ +pluginManagement { + repositories { + mavenLocal() + mavenCentral() + gradlePluginPortal() + } + plugins { + id 'io.quarkus' version "${quarkusPluginVersion}" + } +} + +rootProject.name='app' diff --git a/integration-tests/gradle/src/test/resources/multi-module-included-build/app/src/main/java/org/acme/ExampleResource.java b/integration-tests/gradle/src/test/resources/multi-module-included-build/app/src/main/java/org/acme/ExampleResource.java new file mode 100644 index 0000000000000..4a05673847be1 --- /dev/null +++ b/integration-tests/gradle/src/test/resources/multi-module-included-build/app/src/main/java/org/acme/ExampleResource.java @@ -0,0 +1,22 @@ +package org.acme; + +import org.acme.lib.LibService; + +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +@Path("/hello") +public class ExampleResource { + + @Inject + LibService libService; + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + return "foo " + libService.bar(); + } +} \ No newline at end of file diff --git a/integration-tests/gradle/src/test/resources/multi-module-included-build/app/src/main/resources/application.properties b/integration-tests/gradle/src/test/resources/multi-module-included-build/app/src/main/resources/application.properties new file mode 100644 index 0000000000000..75b9417d6dc14 --- /dev/null +++ b/integration-tests/gradle/src/test/resources/multi-module-included-build/app/src/main/resources/application.properties @@ -0,0 +1,2 @@ +# Configuration file +# key = value diff --git a/integration-tests/gradle/src/test/resources/multi-module-included-build/external-library/build.gradle b/integration-tests/gradle/src/test/resources/multi-module-included-build/external-library/build.gradle new file mode 100644 index 0000000000000..47e70bd7a8757 --- /dev/null +++ b/integration-tests/gradle/src/test/resources/multi-module-included-build/external-library/build.gradle @@ -0,0 +1,29 @@ +plugins { + id 'java' + id 'io.quarkus' + id "org.kordamp.gradle.jandex" version '0.6.0' +} + +repositories { + mavenCentral() + if (System.properties.containsKey('maven.repo.local')) { + maven { + url System.properties.get('maven.repo.local') + } + } else { + mavenLocal() + } +} + +dependencies { + implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}") + implementation 'io.quarkus:quarkus-core' +} + +group 'org.acme' +version '1.0.0-SNAPSHOT' + +compileJava { + options.encoding = 'UTF-8' + options.compilerArgs << '-parameters' +} diff --git a/integration-tests/gradle/src/test/resources/multi-module-included-build/external-library/settings.gradle b/integration-tests/gradle/src/test/resources/multi-module-included-build/external-library/settings.gradle new file mode 100644 index 0000000000000..c64ace75b3c73 --- /dev/null +++ b/integration-tests/gradle/src/test/resources/multi-module-included-build/external-library/settings.gradle @@ -0,0 +1,18 @@ +pluginManagement { + repositories { + mavenCentral() + gradlePluginPortal() + if (System.properties.containsKey('maven.repo.local')) { + maven { + url System.properties.get('maven.repo.local') + } + } else { + mavenLocal() + } + } + plugins { + id 'io.quarkus' version "${quarkusPluginVersion}" + } +} + +rootProject.name='external-library' diff --git a/integration-tests/gradle/src/test/resources/multi-module-included-build/external-library/src/main/java/org/acme/lib/LibService.java b/integration-tests/gradle/src/test/resources/multi-module-included-build/external-library/src/main/java/org/acme/lib/LibService.java new file mode 100644 index 0000000000000..5f872ecd6a32f --- /dev/null +++ b/integration-tests/gradle/src/test/resources/multi-module-included-build/external-library/src/main/java/org/acme/lib/LibService.java @@ -0,0 +1,10 @@ +package org.acme.lib; + +import javax.inject.Singleton; + +@Singleton +public class LibService { + public String bar() { + return "bar"; + } +} diff --git a/integration-tests/gradle/src/test/resources/multi-module-included-build/external-library/src/main/resources/META-INF/beans.xml b/integration-tests/gradle/src/test/resources/multi-module-included-build/external-library/src/main/resources/META-INF/beans.xml new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/integration-tests/gradle/src/test/resources/multi-module-included-build/gradle.properties b/integration-tests/gradle/src/test/resources/multi-module-included-build/gradle.properties new file mode 100644 index 0000000000000..a0bb7cd4da3b4 --- /dev/null +++ b/integration-tests/gradle/src/test/resources/multi-module-included-build/gradle.properties @@ -0,0 +1,4 @@ +#Gradle properties +#Tue Aug 25 06:41:36 GMT 2020 +quarkusPlatformArtifactId=quarkus-bom +quarkusPlatformGroupId=io.quarkus