Build: Effectively remove transitive deps from generated maven poms
With gradle, deploying to maven means first generating poms. These are filled in based on dependencies of the project. Recently, we started disallowing transitive dependencies. However, this configuration does not translate to maven poms because maven has no concept of excluding all transitive dependencies. This change adds exclusions for each of the transitive deps of each dependency being added to the maven pom. It does so by creating dummy configurations for each direct dependency (which does not have transitive deps excluded), so that we can iterate the transitive deps when building the pom. Note, this should be simpler (just modifying maven's pom model), but gradle tries to hide that from their api, causing us to need to manipulate the xml directly. https://discuss.gradle.org/t/modifying-maven-pom-generation-to-add-excludes/12744
This commit is contained in:
parent
a846a257c5
commit
837c593ec2
11
build.gradle
11
build.gradle
|
@ -20,15 +20,6 @@
|
|||
import com.bmuschko.gradle.nexus.NexusPlugin
|
||||
import org.gradle.plugins.ide.eclipse.model.SourceFolder
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.bmuschko:gradle-nexus-plugin:2.3.1'
|
||||
}
|
||||
}
|
||||
|
||||
// common maven publishing configuration
|
||||
subprojects {
|
||||
group = 'org.elasticsearch'
|
||||
|
@ -110,8 +101,6 @@ subprojects {
|
|||
configurations {
|
||||
all {
|
||||
resolutionStrategy {
|
||||
failOnVersionConflict()
|
||||
|
||||
dependencySubstitution {
|
||||
substitute module("org.elasticsearch:rest-api-spec:${version}") with project("${projectsPrefix}:rest-api-spec")
|
||||
substitute module("org.elasticsearch:elasticsearch:${version}") with project("${projectsPrefix}:core")
|
||||
|
|
|
@ -53,6 +53,7 @@ dependencies {
|
|||
compile 'org.eclipse.jgit:org.eclipse.jgit:3.2.0.201312181205-r'
|
||||
compile 'com.perforce:p4java:2012.3.551082' // THIS IS SUPPOSED TO BE OPTIONAL IN THE FUTURE....
|
||||
compile 'de.thetaphi:forbiddenapis:2.0'
|
||||
compile 'com.bmuschko:gradle-nexus-plugin:2.3.1'
|
||||
}
|
||||
|
||||
processResources {
|
||||
|
|
|
@ -18,14 +18,25 @@
|
|||
*/
|
||||
package org.elasticsearch.gradle
|
||||
|
||||
import groovy.xml.Namespace
|
||||
import groovy.xml.QName
|
||||
import nebula.plugin.extraconfigurations.ProvidedBasePlugin
|
||||
import org.apache.maven.model.Exclusion
|
||||
import org.elasticsearch.gradle.precommit.PrecommitTasks
|
||||
import org.gradle.api.XmlProvider
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.Dependency
|
||||
import org.gradle.api.artifacts.ModuleDependency
|
||||
import org.gradle.api.artifacts.ModuleVersionIdentifier
|
||||
import org.gradle.api.artifacts.ProjectDependency
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.JavaVersion
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.artifacts.ResolvedArtifact
|
||||
import org.gradle.api.artifacts.dsl.RepositoryHandler
|
||||
import org.gradle.api.artifacts.maven.MavenPom
|
||||
import org.gradle.api.tasks.bundling.Jar
|
||||
import org.gradle.api.tasks.compile.JavaCompile
|
||||
import org.gradle.internal.jvm.Jvm
|
||||
|
@ -48,6 +59,8 @@ class BuildPlugin implements Plugin<Project> {
|
|||
project.pluginManager.apply('nebula.info-java')
|
||||
project.pluginManager.apply('nebula.info-scm')
|
||||
project.pluginManager.apply('nebula.info-jar')
|
||||
project.pluginManager.apply('com.bmuschko.nexus')
|
||||
project.pluginManager.apply(ProvidedBasePlugin)
|
||||
|
||||
globalBuildInfo(project)
|
||||
configureRepositories(project)
|
||||
|
@ -103,16 +116,77 @@ class BuildPlugin implements Plugin<Project> {
|
|||
|
||||
/** Makes dependencies non-transitive by default */
|
||||
static void configureConfigurations(Project project) {
|
||||
// fail on any conflicting dependency versions
|
||||
project.configurations.all({ Configuration configuration ->
|
||||
if (configuration.name.startsWith('_transitive_')) {
|
||||
// don't force transitive configurations to not conflict with themselves, since
|
||||
// we just have them to find *what* transitive deps exist
|
||||
return
|
||||
}
|
||||
configuration.resolutionStrategy.failOnVersionConflict()
|
||||
})
|
||||
|
||||
// force all dependencies added directly to compile/testCompile to be non-transitive, except for ES itself
|
||||
project.configurations.compile.dependencies.all { dep ->
|
||||
Closure disableTransitiveDeps = { ModuleDependency dep ->
|
||||
if (!(dep instanceof ProjectDependency) && dep.getGroup() != 'org.elasticsearch') {
|
||||
dep.transitive = false
|
||||
|
||||
// also create a configuration just for this dependency version, so that later
|
||||
// we can determine which dependencies it has (for pom generation excludes)
|
||||
String depId = "${dep.getGroup()}:${dep.getName()}:${dep.getVersion()}"
|
||||
String depConfig = "_transitive_${depId}"
|
||||
if (project.configurations.findByName(depConfig) == null) {
|
||||
project.configurations.create(depConfig)
|
||||
project.dependencies.add(depConfig, depId)
|
||||
}
|
||||
}
|
||||
}
|
||||
project.configurations.testCompile.dependencies.all { dep ->
|
||||
if (!(dep instanceof ProjectDependency) && dep.getGroup() != 'org.elasticsearch') {
|
||||
dep.transitive = false
|
||||
|
||||
project.configurations.compile.dependencies.all(disableTransitiveDeps)
|
||||
project.configurations.testCompile.dependencies.all(disableTransitiveDeps)
|
||||
project.configurations.provided.dependencies.all(disableTransitiveDeps)
|
||||
|
||||
// add exclusions to the pom directly, for each of the transitive deps of this project's deps
|
||||
project.modifyPom { MavenPom pom ->
|
||||
pom.withXml { XmlProvider xml ->
|
||||
// first find if we have dependencies at all, and grab the node
|
||||
NodeList depsNodes = xml.asNode().get('dependencies')
|
||||
if (depsNodes.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
// check each dependency for any transitive deps
|
||||
for (Node depNode : depsNodes.get(0).children()) {
|
||||
String groupId = depNode.get('groupId').get(0).text()
|
||||
String artifactId = depNode.get('artifactId').get(0).text()
|
||||
String version = depNode.get('version').get(0).text()
|
||||
|
||||
// collect the transitive deps now that we know what this dependency is
|
||||
String depId = "${groupId}:${artifactId}:${version}"
|
||||
String depConfig = "_transitive_${depId}"
|
||||
Configuration configuration = project.configurations.findByName(depConfig)
|
||||
println ("Inspecting dep: ${depId}")
|
||||
if (configuration == null) {
|
||||
continue // we did not make this dep non-transitive
|
||||
}
|
||||
Set<ResolvedArtifact> artifacts = configuration.resolvedConfiguration.resolvedArtifacts
|
||||
if (artifacts.size() <= 1) {
|
||||
// this dep has no transitive deps (or the only artifact is itself)
|
||||
continue
|
||||
}
|
||||
|
||||
// we now know we have something to exclude, so add the exclusion elements
|
||||
Node exclusions = depNode.appendNode('exclusions')
|
||||
for (ResolvedArtifact transitiveArtifact : artifacts) {
|
||||
ModuleVersionIdentifier transitiveDep = transitiveArtifact.moduleVersion.id
|
||||
if (transitiveDep.group == groupId && transitiveDep.name == artifactId) {
|
||||
continue; // don't exclude the dependency itself!
|
||||
}
|
||||
Node exclusion = exclusions.appendNode('exclusion')
|
||||
exclusion.appendNode('groupId', transitiveDep.group)
|
||||
exclusion.appendNode('artifactId', transitiveDep.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -120,6 +194,7 @@ class BuildPlugin implements Plugin<Project> {
|
|||
/** Adds repositores used by ES dependencies */
|
||||
static void configureRepositories(Project project) {
|
||||
RepositoryHandler repos = project.repositories
|
||||
repos.mavenLocal() // nocommit: remove
|
||||
repos.mavenCentral()
|
||||
repos.maven {
|
||||
name 'sonatype-snapshots'
|
||||
|
|
|
@ -33,7 +33,6 @@ class PluginBuildPlugin extends BuildPlugin {
|
|||
@Override
|
||||
void apply(Project project) {
|
||||
super.apply(project)
|
||||
project.pluginManager.apply(ProvidedBasePlugin)
|
||||
// TODO: add target compatibility (java version) to elasticsearch properties and set for the project
|
||||
configureDependencies(project)
|
||||
// this afterEvaluate must happen before the afterEvaluate added by integTest configure,
|
||||
|
|
|
@ -23,15 +23,15 @@ apply plugin: 'com.bmuschko.nexus'
|
|||
|
||||
dependencies {
|
||||
compile "org.elasticsearch:elasticsearch:${version}"
|
||||
compile "com.carrotsearch.randomizedtesting:randomizedtesting-runner:${versions.randomizedrunner}"
|
||||
compile "junit:junit:${versions.junit}"
|
||||
compile 'org.hamcrest:hamcrest-all:1.3'
|
||||
compile "org.apache.lucene:lucene-test-framework:${versions.lucene}"
|
||||
compile "org.apache.lucene:lucene-codecs:${versions.lucene}"
|
||||
compile "org.apache.httpcomponents:httpclient:${versions.httpclient}"
|
||||
compile "org.apache.httpcomponents:httpcore:${versions.httpcore}"
|
||||
compile "commons-logging:commons-logging:${versions.commonslogging}"
|
||||
compile "commons-codec:commons-codec:${versions.commonscodec}"
|
||||
compile "com.carrotsearch.randomizedtesting:randomizedtesting-runner:${versions.randomizedrunner}@jar"
|
||||
compile "junit:junit:${versions.junit}@jar"
|
||||
compile 'org.hamcrest:hamcrest-all:1.3@jar'
|
||||
compile "org.apache.lucene:lucene-test-framework:${versions.lucene}@jar"
|
||||
compile "org.apache.lucene:lucene-codecs:${versions.lucene}@jar"
|
||||
compile "org.apache.httpcomponents:httpclient:${versions.httpclient}@jar"
|
||||
compile "org.apache.httpcomponents:httpcore:${versions.httpcore}@jar"
|
||||
compile "commons-logging:commons-logging:${versions.commonslogging}@jar"
|
||||
compile "commons-codec:commons-codec:${versions.commonscodec}@jar"
|
||||
}
|
||||
|
||||
compileJava.options.compilerArgs << '-Xlint:-cast,-deprecation,-fallthrough,-overrides,-rawtypes,-serial,-try,-unchecked'
|
||||
|
|
Loading…
Reference in New Issue