diff --git a/build.gradle b/build.gradle index 59c0dde1f7..82bee8c426 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,6 @@ buildscript { maven { url "https://repo.spring.io/plugins-release" } } dependencies { - classpath 'org.springframework.build.gradle:propdeps-plugin:0.0.7' //still uses the old ways classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}" } } @@ -33,7 +32,7 @@ plugins { id "de.undercouch.download" version "3.4.3" id "org.unbroken-dome.test-sets" version "3.0.0" apply false //note: build scan plugin now must be applied in settings.gradle - id "com.jfrog.artifactory" version "4.9.8" apply false + id "com.jfrog.artifactory" version "4.15.2" apply false id 'biz.aQute.bnd.builder' version '5.0.1' apply false } @@ -97,7 +96,6 @@ if (System.getenv('GRADLE_ENTERPRISE_URL')) { configure(subprojects) { p -> apply plugin: 'java' apply plugin: 'jacoco' - apply plugin: 'propdeps' //TODO replace with a simpler local plugin? apply from: "${rootDir}/gradle/setup.gradle" description = 'Non-Blocking Reactive Foundation for the JVM' @@ -199,6 +197,7 @@ gradle.allprojects() { p -> configure(subprojects) { p -> //these apply once the above configure is done, but before project-specific build.gradle have applied apply plugin: "io.reactor.gradle.java-conventions" + apply plugin: "io.reactor.gradle.optional-dependencies" apply from: "${rootDir}/gradle/javadoc.gradle" //these apply AFTER project-specific build.gradle have applied diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index bf14b85dd6..df57d43907 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -39,18 +39,22 @@ test { } gradlePlugin { - plugins { - customVersionPlugin { - id = "io.reactor.gradle.custom-version" - implementationClass = "io.reactor.gradle.CustomVersionPlugin" + plugins { + customVersionPlugin { + id = "io.reactor.gradle.custom-version" + implementationClass = "io.reactor.gradle.CustomVersionPlugin" + } + detectCIPlugin { + id = "io.reactor.gradle.detect-ci" + implementationClass = "io.reactor.gradle.DetectCiPlugin" + } + javaConventionsPlugin { + id = "io.reactor.gradle.java-conventions" + implementationClass = "io.reactor.gradle.JavaConventions" + } + optionalDependenciesPlugin { + id = "io.reactor.gradle.optional-dependencies" + implementationClass = "io.reactor.gradle.OptionalDependenciesPlugin" + } } - detectCIPlugin { - id = "io.reactor.gradle.detect-ci" - implementationClass = "io.reactor.gradle.DetectCiPlugin" - } - javaConventionsPlugin { - id = "io.reactor.gradle.java-conventions" - implementationClass = "io.reactor.gradle.JavaConventions" - } - } } \ No newline at end of file diff --git a/buildSrc/src/main/java/io/reactor/gradle/OptionalDependenciesPlugin.java b/buildSrc/src/main/java/io/reactor/gradle/OptionalDependenciesPlugin.java new file mode 100644 index 0000000000..30a9b5a390 --- /dev/null +++ b/buildSrc/src/main/java/io/reactor/gradle/OptionalDependenciesPlugin.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2011-Present VMware Inc. or its affiliates, All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.reactor.gradle; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.artifacts.Configuration; +import org.gradle.api.attributes.Usage; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.plugins.JavaPluginConvention; +import org.gradle.api.tasks.SourceSetContainer; +import org.gradle.api.tasks.javadoc.Javadoc; +import org.gradle.plugins.ide.eclipse.EclipsePlugin; +import org.gradle.plugins.ide.eclipse.model.EclipseModel; + +/** + * A {@code Plugin} that adds support for Maven-style optional dependencies. Creates a new + * {@code optional} configuration. The {@code optional} configuration is part of the + * project's compile and runtime classpath's but does not affect the classpath of + * dependent projects. + * + * @author Andy Wilkinson + */ +public class OptionalDependenciesPlugin implements Plugin { + + /** + * Name of the {@code optional} configuration. + */ + public static final String OPTIONAL_CONFIGURATION_NAME = "optional"; + + @Override + public void apply(Project project) { + Configuration optional = project.getConfigurations().create(OPTIONAL_CONFIGURATION_NAME); + optional.attributes((attributes) -> attributes.attribute(Usage.USAGE_ATTRIBUTE, + project.getObjects().named(Usage.class, Usage.JAVA_RUNTIME))); + project.getPlugins().withType(JavaPlugin.class, (javaPlugin) -> { + SourceSetContainer sourceSets = project.getConvention().getPlugin(JavaPluginConvention.class) + .getSourceSets(); + sourceSets.all((sourceSet) -> { + sourceSet.setCompileClasspath(sourceSet.getCompileClasspath().plus(optional)); + sourceSet.setRuntimeClasspath(sourceSet.getRuntimeClasspath().plus(optional)); + }); + project.getTasks().withType(Javadoc.class) + .all((javadoc) -> javadoc.setClasspath(javadoc.getClasspath().plus(optional))); + }); + project.getPlugins().withType(EclipsePlugin.class, + (eclipsePlugin) -> project.getExtensions().getByType(EclipseModel.class) + .classpath((classpath) -> classpath.getPlusConfigurations().add(optional))); + } + +} diff --git a/buildSrc/src/test/java/io/reactor/gradle/OptionalDependenciesPluginTest.java b/buildSrc/src/test/java/io/reactor/gradle/OptionalDependenciesPluginTest.java new file mode 100644 index 0000000000..2b0f9df6e0 --- /dev/null +++ b/buildSrc/src/test/java/io/reactor/gradle/OptionalDependenciesPluginTest.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2011-Present VMware Inc. or its affiliates, All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.reactor.gradle; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; + +import org.gradle.testkit.runner.BuildResult; +import org.gradle.testkit.runner.GradleRunner; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Integration tests for {@link OptionalDependenciesPlugin}. + * + * @author Andy Wilkinson + */ +public class OptionalDependenciesPluginTest { + + private File projectDir; + + private File buildFile; + + @BeforeEach + public void setup(@TempDir File projectDir) throws IOException { + this.projectDir = projectDir; + this.buildFile = new File(this.projectDir, "build.gradle"); + } + + @Test + void optionalConfigurationIsCreated() throws IOException { + try (PrintWriter out = new PrintWriter(new FileWriter(this.buildFile))) { + out.println("plugins { id 'io.reactor.gradle.optional-dependencies' }"); + out.println("task printConfigurations {"); + out.println(" doLast {"); + out.println(" configurations.all { println it.name }"); + out.println(" }"); + out.println("}"); + } + BuildResult buildResult = runGradle("printConfigurations"); + assertThat(buildResult.getOutput()).contains(OptionalDependenciesPlugin.OPTIONAL_CONFIGURATION_NAME); + } + + @Test + void optionalDependenciesAreAddedToMainSourceSetsCompileClasspath() throws IOException { + optionalDependenciesAreAddedToSourceSetClasspath("main", "compileClasspath"); + } + + @Test + void optionalDependenciesAreAddedToMainSourceSetsRuntimeClasspath() throws IOException { + optionalDependenciesAreAddedToSourceSetClasspath("main", "runtimeClasspath"); + } + + @Test + void optionalDependenciesAreAddedToTestSourceSetsCompileClasspath() throws IOException { + optionalDependenciesAreAddedToSourceSetClasspath("test", "compileClasspath"); + } + + @Test + void optionalDependenciesAreAddedToTestSourceSetsRuntimeClasspath() throws IOException { + optionalDependenciesAreAddedToSourceSetClasspath("test", "runtimeClasspath"); + } + + public void optionalDependenciesAreAddedToSourceSetClasspath(String sourceSet, String classpath) + throws IOException { + try (PrintWriter out = new PrintWriter(new FileWriter(this.buildFile))) { + out.println("plugins {"); + out.println(" id 'io.reactor.gradle.optional-dependencies'"); + out.println(" id 'java'"); + out.println("}"); + out.println("repositories {"); + out.println(" mavenCentral()"); + out.println("}"); + out.println("dependencies {"); + out.println(" optional 'io.projectreactor.addons:reactor-extra:3.3.0.RELEASE'"); + out.println("}"); + out.println("task printClasspath {"); + out.println(" doLast {"); + out.println(" println sourceSets." + sourceSet + "." + classpath + ".files"); + out.println(" }"); + out.println("}"); + } + BuildResult buildResult = runGradle("printClasspath"); + assertThat(buildResult.getOutput()).contains("reactor-extra"); + } + + private BuildResult runGradle(String... args) { + return GradleRunner.create().withProjectDir(this.projectDir).withArguments(args).withPluginClasspath().build(); + } + +} diff --git a/reactor-core/build.gradle b/reactor-core/build.gradle index c5b63f60e3..85178890f9 100644 --- a/reactor-core/build.gradle +++ b/reactor-core/build.gradle @@ -74,7 +74,7 @@ dependencies { //Optional Metrics optional "io.micrometer:micrometer-core:$micrometerVersion" - optional("org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion}") + optional "org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion}" //Optional BlockHound support optional "io.projectreactor.tools:blockhound:$blockhoundVersion" diff --git a/reactor-test/build.gradle b/reactor-test/build.gradle index 888bacef45..0d9cdc06fe 100644 --- a/reactor-test/build.gradle +++ b/reactor-test/build.gradle @@ -38,6 +38,8 @@ ext { dependencies { compile project(":reactor-core") + optional "org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion}" + testCompile "junit:junit:$jUnitVersion" testImplementation "org.junit.jupiter:junit-jupiter-api:${jUnitJupiterVersion}" testRuntime "org.junit.jupiter:junit-jupiter-engine:${jUnitJupiterVersion}"