diff --git a/src/main/groovy/nebula/plugin/extraconfigurations/ProvidedBasePlugin.groovy b/src/main/groovy/nebula/plugin/extraconfigurations/ProvidedBasePlugin.groovy deleted file mode 100644 index d6d7315..0000000 --- a/src/main/groovy/nebula/plugin/extraconfigurations/ProvidedBasePlugin.groovy +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright 2014-2016 Netflix, Inc. - * - * 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 - * - * http://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 nebula.plugin.extraconfigurations - -import com.netflix.nebula.interop.GradleKt -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.artifacts.Configuration -import org.gradle.api.artifacts.Dependency -import org.gradle.api.artifacts.maven.Conf2ScopeMappingContainer -import org.gradle.api.plugins.JavaPlugin -import org.gradle.api.plugins.MavenPlugin -import org.gradle.api.plugins.WarPlugin -import org.gradle.api.publish.PublishingExtension -import org.gradle.api.publish.ivy.IvyPublication -import org.gradle.api.publish.maven.MavenPublication -import org.gradle.api.publish.plugins.PublishingPlugin -import org.gradle.api.tasks.bundling.War -import org.gradle.plugins.ide.eclipse.EclipsePlugin -import org.gradle.plugins.ide.idea.IdeaPlugin -import org.slf4j.Logger -import org.slf4j.LoggerFactory - -class ProvidedBasePlugin implements Plugin { - static final Logger LOGGER = LoggerFactory.getLogger(ProvidedBasePlugin) - static final String PROVIDED_CONFIGURATION_NAME = 'provided' - - @Override - void apply(Project project) { - if (!GradleKt.versionLessThan(project.gradle, "3.4")) { - LOGGER.warn("nebula.provided-base plugin does nothing on Gradle 3.4 and later. Use the 'compileOnly' configuration") - return - } - project.plugins.withType(JavaPlugin) { - Configuration providedConfiguration = createProvidedConfiguration(project) - configureIdeaPlugin(project, providedConfiguration) - configureEclipsePlugin(project, providedConfiguration) - configureMavenPublishPlugin(project, providedConfiguration) - configureIvyPublishPlugin(project, providedConfiguration) - configureWarPlugin(project, providedConfiguration) - configureMavenPlugin(project, providedConfiguration) - } - } - - private Configuration createProvidedConfiguration(Project project) { - Configuration compileConf = project.configurations.getByName(JavaPlugin.COMPILE_CONFIGURATION_NAME) - - // Our legacy provided scope, uber conf of provided and compile. This ensures what we're at least resolving with compile dependencies. - def providedConf = project.configurations.create(PROVIDED_CONFIGURATION_NAME) - .setVisible(true) - .setTransitive(true) - .setDescription('much like compile, but indicates that you expect the JDK or a container to provide it. It is only available on the compilation classpath, and is not transitive.') - - compileConf.extendsFrom(providedConf) - - // exclude provided dependencies when resolving dependencies between projects - providedConf.allDependencies.all { Dependency dep -> - project.configurations.default.exclude(group: dep.group, module: dep.name) - } - - providedConf - } - - /** - * Configures the IDEA plugin to add the provided configuration to the PROVIDED scope. - * - * @param project Project - * @param providedConfiguration Provided configuration - */ - private void configureIdeaPlugin(Project project, Configuration providedConfiguration) { - project.plugins.withType(IdeaPlugin) { - project.idea.module { - scopes.PROVIDED.plus += [providedConfiguration] - } - } - } - - /** - * Configures the Eclipse plugin to add the provided configuration. - * - * @param project Project - * @param providedConfiguration Provided configuration - */ - private void configureEclipsePlugin(Project project, Configuration providedConfiguration) { - project.plugins.withType(EclipsePlugin) { - project.eclipse.classpath.plusConfigurations += [providedConfiguration] - } - } - - /** - * Configures Maven Publishing plugin to ensure that published dependencies receive the correct scope. - * - * @param project Project - * @param providedConfiguration Provided configuration - */ - private void configureMavenPublishPlugin(Project project, Configuration providedConfiguration) { - project.plugins.withType(PublishingPlugin) { - project.publishing { - publications { - project.extensions.findByType(PublishingExtension)?.publications?.withType(MavenPublication) { MavenPublication pub -> - pub.pom.withXml { - // Replace dependency "runtime" scope element value with "provided" - asNode().dependencies.dependency.findAll { - it.scope.text() == JavaPlugin.RUNTIME_CONFIGURATION_NAME && providedConfiguration.allDependencies.find { dep -> - dep.name == it.artifactId.text() - } - }.each { runtimeDep -> - runtimeDep.scope*.value = PROVIDED_CONFIGURATION_NAME - } - } - } - } - } - } - } - - /** - * Configures Ivy Publishing plugin to ensure that published dependencies receive the correct conf attribute value. - * - * @param project Project - * @param providedConfiguration Provided configuration - */ - private void configureIvyPublishPlugin(Project project, Configuration providedConfiguration) { - project.plugins.withType(PublishingPlugin) { - project.publishing { - publications { - project.extensions.findByType(PublishingExtension)?.publications?.withType(IvyPublication) { IvyPublication pub -> - pub.descriptor.withXml { - def rootNode = asNode() - - // Add provided configuration if it doesn't exist yet - if (!rootNode.configurations.find { it.@name == PROVIDED_CONFIGURATION_NAME }) { - rootNode.configurations[0].appendNode('conf', [name: PROVIDED_CONFIGURATION_NAME, visibility: 'public']) - } - - // Replace dependency "runtime->default" conf attribute value with "provided" - rootNode.dependencies.dependency.findAll { - it.@conf == "$JavaPlugin.RUNTIME_CONFIGURATION_NAME->default" && providedConfiguration.allDependencies.find { dep -> - dep.name == it.@name - } - }.each { runtimeDep -> - runtimeDep.@conf = PROVIDED_CONFIGURATION_NAME - } - } - } - } - } - } - } - - /** - * Configures War plugin to ensure that provided dependencies are excluded from runtime classpath. - * - * @param project Project - * @param providedConfiguration Provided configuration - */ - private void configureWarPlugin(Project project, Configuration providedConfiguration) { - project.plugins.withType(WarPlugin) { - project.tasks.withType(War) { - classpath = classpath.minus(providedConfiguration) - } - } - } - - /** - * Configures the Maven plugin to ensure that published dependencies receive the correct scope. - * - * @param project Project - * @param providedConfiguration provided configuration - */ - private void configureMavenPlugin(Project project, Configuration providedConfiguration) { - project.plugins.withType(MavenPlugin) { - project.conf2ScopeMappings.addMapping(MavenPlugin.COMPILE_PRIORITY + 1, providedConfiguration, - Conf2ScopeMappingContainer.PROVIDED) - } - } -} diff --git a/src/test/groovy/nebula/plugin/extraconfigurations/ProvidedBasePluginIntegrationTest.groovy b/src/test/groovy/nebula/plugin/extraconfigurations/ProvidedBasePluginIntegrationTest.groovy deleted file mode 100644 index 4424536..0000000 --- a/src/test/groovy/nebula/plugin/extraconfigurations/ProvidedBasePluginIntegrationTest.groovy +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Copyright 2014 Netflix, Inc. - * - * 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 - * - * http://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 nebula.plugin.extraconfigurations - -import nebula.test.dependencies.DependencyGraphBuilder -import nebula.test.dependencies.GradleDependencyGenerator -import spock.lang.Ignore - -@Ignore -class ProvidedBasePluginIntegrationTest extends AbstractIntegrationTest { - def setup() { - buildFile << """ -apply plugin: 'java' -apply plugin: 'nebula.provided-base' -""" - } - - def "Can compile production code dependent on dependency declared as provided"() { - when: - buildFile << """ -repositories { - mavenCentral() -} - -dependencies { - provided 'org.apache.commons:commons-lang3:3.3.2' -} -""" - createProductionJavaSourceFile() - runTasksSuccessfully('compileJava') - - then: - new File(projectDir, 'build/classes/main/nebula/extraconf/HelloWorld.class').exists() - } - - def "Can test production code dependent on dependency declared as provided"() { - when: - buildFile << """ -repositories { - mavenCentral() -} - -dependencies { - provided 'org.apache.commons:commons-lang3:3.3.2' - testCompile 'junit:junit:4.8.2' -} -""" - createProductionJavaSourceFile() - createTestSourceJavaClass() - runTasksSuccessfully('test') - - then: - new File(projectDir, 'build/classes/main/nebula/extraconf/HelloWorld.class').exists() - new File(projectDir, 'build/classes/test/nebula/extraconf/HelloWorldTest.class').exists() - new File(projectDir, 'build/test-results/test/TEST-nebula.extraconf.HelloWorldTest.xml').exists() - } - - private void createProductionJavaSourceFile() { - File javaFile = createFile("src/main/java/nebula/extraconf/HelloWorld.java") - javaFile << """ -package nebula.extraconf; - -import org.apache.commons.lang3.StringUtils; - -public class HelloWorld { - public String getMessage() { - return StringUtils.upperCase("Hello World!"); - } -} -""" - } - - private void createTestSourceJavaClass() { - File javaTestFile = createFile('src/test/java/nebula/extraconf/HelloWorldTest.java') - javaTestFile << """ -package nebula.extraconf; - -import org.junit.Test; -import static org.junit.Assert.assertEquals; - -public class HelloWorldTest { - @Test - public void getMessage() { - assertEquals("HELLO WORLD!", new HelloWorld().getMessage()); - } -} -""" - } - - def "Adds provided dependencies to PROVIDED scope if Idea plugin is applied"() { - when: - buildFile << """ -apply plugin: 'idea' - -repositories { - mavenCentral() -} - -dependencies { - provided 'org.apache.commons:commons-lang3:3.3.2' -} -""" - runTasksSuccessfully('idea') - - then: - File ideaModuleFile = new File(projectDir, "${moduleName}.iml") - ideaModuleFile.exists() - def moduleXml = new XmlSlurper().parseText(ideaModuleFile.text) - def orderEntries = moduleXml.component.orderEntry.findAll { - it.@type.text() == 'module-library' && it.@scope.text() == 'PROVIDED' - } - orderEntries.find { it.library.CLASSES.root.@url.text().contains('commons-lang3-3.3.2.jar') } - } - - def 'verify eclipse add provided'() { - buildFile << ''' - apply plugin: 'eclipse' - - repositories { mavenCentral() } - - dependencies { - provided 'org.apache.commons:commons-lang3:3.3.2' - } - '''.stripIndent() - - when: - runTasksSuccessfully('eclipse') - - then: - File eclipseClasspath = new File(projectDir, '.classpath') - eclipseClasspath.exists() - def classpathXml = new XmlSlurper().parseText(eclipseClasspath.text) - classpathXml.classpath.classpathentry.find { - it?.@path?.contains 'org.apache.commons/commons-lang3/3.3.2' - } != null - } - - def "Publishing provided dependencies to a Maven repository preserves the scope when using Maven Publish plugin"() { - given: - File repoUrl = new File(projectDir, 'build/repo') - - when: - buildFile << """ -apply plugin: 'maven-publish' - -group = '$GROUP_ID' -version '$VERSION' - -repositories { - mavenCentral() -} - -dependencies { - provided 'org.apache.commons:commons-lang3:3.3.2' -} - -publishing { - publications { - mavenJava(MavenPublication) { - from components.java - } - } - - repositories { - maven { - url '${repoUrl.toURI().toURL()}' - } - } -} -""" - runTasksSuccessfully('publish') - - then: - assertProvidedDependencyInGeneratedPom(repoUrl, 'org.apache.commons', 'commons-lang3', '3.3.2') - } - - def "Publishing provided dependencies to a Maven repository preserves the scope when using Maven plugin"() { - given: - File repoUrl = new File(projectDir, 'build/repo/') - - when: - buildFile << """ -apply plugin: 'maven' - -group = '$GROUP_ID' -version '$VERSION' - -repositories { - mavenCentral() -} - -dependencies { - provided 'org.apache.commons:commons-lang3:3.3.2' -} - -uploadArchives { - repositories.mavenDeployer { - repository(url: "${repoUrl.toURI().toURL()}") - } -} -""" - runTasksSuccessfully('install', 'uploadArchives') - - then: - assertProvidedDependencyInGeneratedPom(MAVEN_LOCAL_DIR, 'org.apache.commons', 'commons-lang3', '3.3.2') - assertProvidedDependencyInGeneratedPom(repoUrl, 'org.apache.commons', 'commons-lang3', '3.3.2') - } - - def "Publishing provided dependencies to an Ivy repository preserves the scope"() { - given: - File repoUrl = new File(projectDir, 'build/repo') - - when: - buildFile << """ -apply plugin: 'ivy-publish' - -group = '$GROUP_ID' -version '$VERSION' - -repositories { - mavenCentral() -} - -dependencies { - compile 'com.google.guava:guava:16.0' - provided 'org.apache.commons:commons-lang3:3.3.2' -} - -publishing { - publications { - ivyJava(IvyPublication) { - from components.java - } - } - - repositories { - ivy { - url '$repoUrl.canonicalPath' - } - } -} -""" - runTasksSuccessfully('publish') - - then: - assertProvidedDependencyInGeneratedIvy(repoUrl, 'org.apache.commons', 'commons-lang3', '3.3.2') - } - - def "Provided dependencies are not included in war archive"() { - when: - buildFile << """ -apply plugin: 'war' -apply plugin: 'nebula.provided-base' - -repositories { - mavenCentral() -} - -dependencies { - provided 'org.apache.commons:commons-lang3:3.3.2' -} - -task explodedWar(type: Copy) { - into "\$buildDir/libs/exploded" - with war -} -""" - runTasksSuccessfully('explodedWar') - - then: - !new File(projectDir, 'build/libs/exploded/WEB-INF/lib/commons-lang3-3.3.2.jar').exists() - } - - def "Order of plugins declaration does not affect war content"() { - when: - buildFile << """ -apply plugin: 'war' - -repositories { - mavenCentral() -} - -dependencies { - provided 'org.apache.commons:commons-lang3:3.3.2' -} - -task explodedWar(type: Copy) { - into "\$buildDir/libs/exploded" - with war -} -""" - runTasksSuccessfully('explodedWar') - - then: - !new File(projectDir, 'build/libs/exploded/WEB-INF/lib/commons-lang3-3.3.2.jar').exists() - } - - def "Transitive dependencies in scope provided are not included in war archive"() { - when: - helper.addSubproject( - "shared-component", - """ -apply plugin: 'java' -apply plugin: 'nebula.provided-base' - -repositories { - mavenCentral() -} - -dependencies { - provided 'org.apache.commons:commons-lang3:3.3.2' -} -""" - ) - - helper.addSubproject( - "webapp-component", - """ -apply plugin: 'war' -apply plugin: 'nebula.provided-base' - -repositories { - mavenCentral() -} - -dependencies { - compile project(":shared-component") -} - -task explodedWar(type: Copy) { - into "\$buildDir/libs/exploded" - with war -} -""" - ) - - runTasksSuccessfully('explodedWar') - - then: - !new File(projectDir, 'webapp-component/build/libs/exploded/WEB-INF/lib/commons-lang3-3.3.2.jar').exists() - } - - def 'still works if maven-publish publication is modified in after evaluate'() { - given: - def graph = new DependencyGraphBuilder().addModule('test.nebula:foo:1.0.0').build() - File mavenRepo = new GradleDependencyGenerator(graph, "${projectDir}/testrepogen").generateTestMavenRepo() - File repoUrl = new File(projectDir, 'build/repo') - - buildFile << """\ - apply plugin: 'maven-publish' - - group = '$GROUP_ID' - version = '$VERSION' - - repositories { maven { url '${mavenRepo.absolutePath}' } } - - dependencies { - provided 'test.nebula:foo:1.0.0' - } - - afterEvaluate { - publishing { - repositories { - maven { - name 'testRepo' - url '${repoUrl.toURI().toURL()}' - } - } - publications { - testMaven(MavenPublication) { - from components.java - } - } - } - } - """.stripIndent() - - when: - runTasksSuccessfully('publish') - - then: - assertProvidedDependencyInGeneratedPom(repoUrl, 'test.nebula', 'foo', '1.0.0') - } -} diff --git a/src/test/groovy/nebula/plugin/extraconfigurations/ProvidedBasePluginSpec.groovy b/src/test/groovy/nebula/plugin/extraconfigurations/ProvidedBasePluginSpec.groovy deleted file mode 100644 index 58b38db..0000000 --- a/src/test/groovy/nebula/plugin/extraconfigurations/ProvidedBasePluginSpec.groovy +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2014-2015 Netflix, Inc. - * - * 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 - * - * http://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 nebula.plugin.extraconfigurations - -import nebula.test.PluginProjectSpec -import org.gradle.api.artifacts.Configuration -import org.gradle.api.artifacts.ResolvedConfiguration -import org.gradle.api.plugins.JavaPlugin -import org.gradle.api.plugins.JavaPluginConvention -import org.gradle.api.tasks.SourceSet -import org.gradle.api.tasks.bundling.War -import spock.lang.Ignore -import spock.lang.Unroll - -@Ignore -class ProvidedBasePluginSpec extends PluginProjectSpec { - @Override - String getPluginName() { - 'nebula.provided-base' - } - - def "Does not create provided configuration if Java plugin is not applied"() { - when: - project.apply plugin: pluginName - - then: - !project.configurations.findByName(ProvidedBasePlugin.PROVIDED_CONFIGURATION_NAME) - } - - def 'Creates provided configuration if Java plugin is applied'() { - when: - project.apply plugin: 'java' - project.apply plugin: pluginName - - then: 'Compile configuration extends from provided configuration' - Configuration compileConfiguration = project.configurations.getByName(JavaPlugin.COMPILE_CONFIGURATION_NAME) - compileConfiguration.extendsFrom.collect { it.name } as Set == [ProvidedBasePlugin.PROVIDED_CONFIGURATION_NAME] as Set - !compileConfiguration.visible - compileConfiguration.transitive - - and: 'Provided configuration exists and does not extend other configurations' - Configuration providedConfiguration = project.configurations.getByName(ProvidedBasePlugin.PROVIDED_CONFIGURATION_NAME) - providedConfiguration.extendsFrom == Collections.emptySet() - providedConfiguration.visible - providedConfiguration.transitive - } - - def 'order independent does provided conf exist'() { - when: - project.apply plugin: pluginName - project.apply plugin: 'java' - - then: - project.configurations.getByName(ProvidedBasePlugin.PROVIDED_CONFIGURATION_NAME) - } - - def 'check versions'() { - when: - project.apply plugin: 'java' - project.apply plugin: pluginName - - project.repositories { - mavenCentral() - } - - project.dependencies { - compile 'com.google.guava:guava:12.0' - provided 'commons-io:commons-io:2.4' - } - - then: - ResolvedConfiguration resolved = project.configurations.compile.resolvedConfiguration - resolved.getResolvedArtifacts().any { it.name == 'guava' } - resolved.getResolvedArtifacts().any { it.name == 'commons-io' } - - ResolvedConfiguration resolvedProvided = project.configurations.provided.resolvedConfiguration - !resolvedProvided.getResolvedArtifacts().any { it.name == 'guava' } - resolvedProvided.getResolvedArtifacts().any { it.name == 'commons-io' } - - JavaPluginConvention javaConvention = project.getConvention().getPlugin(JavaPluginConvention) - SourceSet mainSourceSet = javaConvention.sourceSets.main - mainSourceSet.compileClasspath.any { it.name.contains 'guava'} - mainSourceSet.compileClasspath.any { it.name.contains 'commons-io'} - - SourceSet testSourceSet = javaConvention.sourceSets.test - testSourceSet.compileClasspath.any { it.name.contains 'guava'} - testSourceSet.compileClasspath.any { it.name.contains 'commons-io'} - } - - @Unroll - def "Dependency declared by configuration '#providedConfigurationName' is not added to War classpath if also defined by 'compile' configuration"() { - when: - project.apply plugin: 'war' - project.apply plugin: pluginName - project.repositories.mavenCentral() - project.dependencies.add('compile', 'commons-io:commons-io:2.2') - project.dependencies.add(providedConfigurationName, 'commons-io:commons-io:2.4') - - then: - def resolved = project.configurations.getByName('compile').resolvedConfiguration - resolved.getResolvedArtifacts().any { it.name == 'commons-io' && it.moduleVersion.id.version == '2.4' } // This is different from above - - def resolvedProvided = project.configurations.getByName(providedConfigurationName).resolvedConfiguration - resolvedProvided.getResolvedArtifacts().any { it.name == 'commons-io' && it.moduleVersion.id.version == '2.4' } - - War warTask = project.tasks.getByName('war') - def commonIos = warTask.classpath.findAll { it.name.contains 'commons-io' } - commonIos.size() == 0 - - where: - providedConfigurationName << ['providedCompile', 'provided'] - } -}