From fa6188c57b0864cbd4cdb948392e4a54c53c0de8 Mon Sep 17 00:00:00 2001 From: Andriy Redko Date: Wed, 7 Jun 2023 09:38:54 -0400 Subject: [PATCH] Add OptionalDependenciesPlugin to support Maven/Ivy style optional dependencies Signed-off-by: Andriy Redko --- .../plugin/OptionalDependenciesPlugin.groovy | 124 ++++++++++++++++++ ...pensearch.optional-dependencies.properties | 12 ++ libs/cli/build.gradle | 1 - libs/core/build.gradle | 1 - server/build.gradle | 8 +- 5 files changed, 140 insertions(+), 6 deletions(-) create mode 100644 buildSrc/src/main/groovy/org/opensearch/gradle/plugin/OptionalDependenciesPlugin.groovy create mode 100644 buildSrc/src/main/resources/META-INF/gradle-plugins/opensearch.optional-dependencies.properties diff --git a/buildSrc/src/main/groovy/org/opensearch/gradle/plugin/OptionalDependenciesPlugin.groovy b/buildSrc/src/main/groovy/org/opensearch/gradle/plugin/OptionalDependenciesPlugin.groovy new file mode 100644 index 0000000000000..e531f2a60369d --- /dev/null +++ b/buildSrc/src/main/groovy/org/opensearch/gradle/plugin/OptionalDependenciesPlugin.groovy @@ -0,0 +1,124 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * 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 org.opensearch.gradle.plugin + +import org.gradle.api.Plugin +import org.gradle.api.Project +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 + +/** + * Including the support of `optional` dependencies: https://github.com/nebula-plugins/gradle-extra-configurations-plugin/blob/v9.0.0/src/main/groovy/nebula/plugin/extraconfigurations/OptionalBasePlugin.groovy + */ +class OptionalDependenciesPlugin implements Plugin { + static final String OPTIONAL_IDENTIFIER = 'optional' + + @Override + void apply(Project project) { + enhanceProjectModel(project) + configureMavenPublishPlugin(project) + configureIvyPublishPlugin(project) + } + + /** + * Enhances the Project domain object by adding + * + * a) a extra property List that holds optional dependencies + * b) a extra method that can be executed as parameter when declaring dependencies + * + * @param project Project + */ + private void enhanceProjectModel(Project project) { + project.ext.optionalDeps = [] + + project.ext.optional = { dep -> + project.ext.optionalDeps << dep + } + } + + /** + * Configures Maven Publishing plugin to ensure that published dependencies receive the optional element. + * + * @param project Project + */ + private void configureMavenPublishPlugin(Project project) { + project.plugins.withType(PublishingPlugin) { + project.publishing { + publications { + project.extensions.findByType(PublishingExtension)?.publications?.withType(MavenPublication) { MavenPublication pub -> + pub.pom.withXml { + project.ext.optionalDeps.each { dep -> + def foundDep = asNode().dependencies.dependency.find { + it.groupId.text() == dep.group && it.artifactId.text() == dep.name + } + + if (foundDep) { + if (foundDep.optional) { + foundDep.optional.value = 'true' + } else { + foundDep.appendNode(OPTIONAL_IDENTIFIER, 'true') + } + } + } + } + } + } + } + } + } + + /** + * Configures Ivy Publishing plugin to ensure that published dependencies receive the correct conf attribute value. + * + * @param project Project + */ + private void configureIvyPublishPlugin(Project project) { + project.plugins.withType(PublishingPlugin) { + project.publishing { + publications { + project.extensions.findByType(PublishingExtension)?.publications?.withType(IvyPublication) { IvyPublication pub -> + pub.descriptor.withXml { + def rootNode = asNode() + + // Add optional configuration if it doesn't exist yet + if (!rootNode.configurations.find { it.@name == OPTIONAL_IDENTIFIER }) { + rootNode.configurations[0].appendNode('conf', [name: OPTIONAL_IDENTIFIER, visibility: 'public']) + } + + // Replace dependency "runtime->default" conf attribute value with "optional" + project.ext.optionalDeps.each { dep -> + def foundDep = rootNode.dependencies.dependency.find { it.@name == dep.name } + foundDep?.@conf = OPTIONAL_IDENTIFIER + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/opensearch.optional-dependencies.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/opensearch.optional-dependencies.properties new file mode 100644 index 0000000000000..8b6f6f307cd5d --- /dev/null +++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/opensearch.optional-dependencies.properties @@ -0,0 +1,12 @@ +# +# SPDX-License-Identifier: Apache-2.0 +# +# The OpenSearch Contributors require contributions made to +# this file be licensed under the Apache-2.0 license or a +# compatible open source license. +# +# Modifications Copyright OpenSearch Contributors. See +# GitHub history for details. +# + +implementation-class=org.opensearch.gradle.plugin.OptionalDependenciesPlugin diff --git a/libs/cli/build.gradle b/libs/cli/build.gradle index 802bd7a774af7..a58c4dafac874 100644 --- a/libs/cli/build.gradle +++ b/libs/cli/build.gradle @@ -28,7 +28,6 @@ * under the License. */ apply plugin: 'opensearch.build' -apply plugin: 'com.netflix.nebula.optional-base' apply plugin: 'opensearch.publish' dependencies { diff --git a/libs/core/build.gradle b/libs/core/build.gradle index 6c6fc745b5942..65d507c37b3ff 100644 --- a/libs/core/build.gradle +++ b/libs/core/build.gradle @@ -30,7 +30,6 @@ import org.opensearch.gradle.info.BuildParams -apply plugin: 'com.netflix.nebula.optional-base' apply plugin: 'opensearch.publish' archivesBaseName = 'opensearch-core' diff --git a/server/build.gradle b/server/build.gradle index e69f64b7b3758..2e941121bfaeb 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -33,9 +33,9 @@ import org.opensearch.gradle.info.BuildParams plugins { id('com.google.protobuf') version 'latest.release' id('opensearch.build') - id('com.netflix.nebula.optional-base') id('opensearch.publish') id('opensearch.internal-cluster-test') + id('opensearch.optional-dependencies') } publishing { @@ -135,13 +135,13 @@ dependencies { api 'org.hdrhistogram:HdrHistogram:2.1.12' // lucene spatial - api "org.locationtech.spatial4j:spatial4j:${versions.spatial4j}" - api "org.locationtech.jts:jts-core:${versions.jts}" + api "org.locationtech.spatial4j:spatial4j:${versions.spatial4j}", optional + api "org.locationtech.jts:jts-core:${versions.jts}", optional // logging api "org.apache.logging.log4j:log4j-api:${versions.log4j}" api "org.apache.logging.log4j:log4j-jul:${versions.log4j}" - api "org.apache.logging.log4j:log4j-core:${versions.log4j}" + api "org.apache.logging.log4j:log4j-core:${versions.log4j}", optional // jna api "net.java.dev.jna:jna:${versions.jna}"