Awesome
Nebula Publishing Plugin
Usage
WARNING: Version 14.x.x requires at least Gradle 5.4
WARNING: Version 17.x.x requires at least Gradle 6.0 or newer for sources and javadoc plugins
WARNING: Version 19.x.x requires at least Gradle 8.0 or newer for sources and javadoc plugins
To apply this plugin if using plugins block
plugins {
id 'com.netflix.nebula.<publishing plugin of your choice>' version '20.2.0'
}
If using an older version of Gradle
buildscript {
repositories { mavenCentral() }
dependencies {
classpath 'com.netflix.nebula:nebula-publishing-plugin:20.2.0'
}
}
apply plugin: 'com.netflix.nebula.<publishing plugin of your choice>'
Provides publishing related plugins to reduce boiler plate and add functionality to maven-publish/ivy-publish.
Maven Related Publishing Plugins
nebula.maven-base-publish
Create a maven publication named nebula. This named container will be used to generate task names as described in
the Maven Publish documentation on gradle.org. Examples
include publishNebulaPublicationToMavenLocalRepository
and publishNebulaPublicationToMyArtifactoryRepository
.
All of the maven based publishing plugins will interact with this publication. All of the other maven based plugins will also automatically apply this so most users will not need to.
Eliminates this boilerplate:
apply plugin: 'maven-publish'
publishing {
publications {
nebula(MavenPublication) {
}
}
}
nebula.maven-dependencies
We detect if the war plugin is applied and publish the web component, it will default to publishing the java component.
Applying this plugin would be the same as:
if war detected
publishing {
publications {
nebula(MavenPublication) {
from components.web
// code to append dependencies since they are useful information
}
}
}
if war not detected
publishing {
publications {
nebula(MavenPublication) {
from components.java
}
}
}
Note that nebula.maven-dependencies is based on the Gradle maven-publish plugin, which places first order compile dependencies in the runtime scope in the POM. If you wish your compile dependencies to be compile scope dependencies in the POM, you can add a withXml block like so:
publishing {
publications {
nebula(MavenPublication) {
pom.withXml {
configurations.compile.resolvedConfiguration.firstLevelModuleDependencies.each { dep ->
asNode().dependencies[0].dependency.find {
it.artifactId[0].text() == dep.moduleName &&
it.groupId[0].text() == dep.moduleGroup
}?.scope[0]?.value = 'compile'
}
}
}
}
}
com.netflix.nebula.maven-publish
Link all the other maven plugins together.
com.netflix.nebula.maven-manifest
Adds a properties block to the pom. Copying in data from our gradle-info-plugin.
com.netflix.nebula.maven-resolved-dependencies
Walk through all project dependencies and replace all dynamic dependencies with what those jars currently resolve to. Necessary if nebula-dependency-recommender-plugin is used to include version numbers in POM files generated by Gradle's maven-publish
.
com.netflix.nebula.maven-scm
Adds scm block to the pom. Tries to use the the info-scm plugin from gradle-info-plugin
com.netflix.nebula.maven-developer
When Gradle Contacts plugin is applied, it will take the configured contacts and add them to the POM file.
Example, given:
apply plugin: 'com.netflix.nebula.contacts'
contacts {
'nebula@example.test' {
moniker 'Example Nebula'
github 'nebula-plugins'
}
}
resulting POM will be:
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>test.nebula</groupId>
<artifactId>developerpomtest</artifactId>
<version>0.1.0</version>
<packaging>pom</packaging>
<name>developerpomtest</name>
<developers>
<developer>
<id>nebula-plugins</id>
<name>Example Nebula</name>
<email>nebula@example.test</email>
</developer>
</developers>
</project>
Ivy Related Publishing Plugins
com.netflix.nebula.ivy-base-publish
Create an ivy publication named nebulaIvy. This named container will be used to generate task names as described in
the Ivy Publish documentation on gradle.org. Examples
include publishNebulaIvyPublicationToMyLocalIvyRepository
and publishNebulaIvyPublicationToMyArtifactoryRepository
.
All of the ivy based publishing plugins will interact with this publication. All of the other ivy based plugins will also automatically apply this so most users will not need to.
Eliminates this boilerplate:
apply plugin: 'ivy-publish'
publishing {
publications {
nebulaIvy(IvyPublication) {
}
}
}
com.netflix.nebula.ivy-dependencies
We detect if the war plugin is applied and publish the web component, it will default to publishing the java component.
Applying this plugin would be the same as:
if war detected
publishing {
publications {
nebulaIvy(IvyPublication) {
from components.web
// code to append dependencies since they are useful information
}
}
}
if war not detected
publishing {
publications {
nebulaIvy(IvyPublication) {
from components.java
}
}
}
com.netflix.nebula.ivy-publish
Link all the other ivy plugins together.
com.netflix.nebula.ivy-manifest
Adds a properties block to the ivy.xml. Copying in data from our gradle-info-plugin.
com.netflix.nebula.ivy-resolved
Walk through all project dependencies and replace all dynamic dependencies with what those jars currently resolve to.
Extra Publication Plugins
com.netflix.nebula.javadoc-jar
Creates a javadocJar task to package up javadoc and add it to publications so it is published.
Eliminates this boilerplate:
tasks.create('javadocJar', Jar) {
dependsOn tasks.javadoc
from tasks.javadoc.destinationDir
archiveClassifier 'javadoc'
archiveExtension 'jar'
group 'build'
}
publishing {
publications {
nebula(MavenPublication) { // if maven-publish is applied
artifact tasks.javadocJar
}
nebulaIvy(IvyPublication) { // if ivy-publish is applied
artifact tasks.javadocJar
}
}
}
com.netflix.nebula.source-jar
Creates a sourceJar tasks to package up the the source code of your project and add it to publications so it is published.
Eliminates this boilerplate:
tasks.create('sourceJar', Jar) {
dependsOn tasks.classes
from sourceSets.main.allSource
archiveClassifier 'sources'
archiveExtension 'jar'
group 'build'
}
publishing {
publications {
nebula(MavenPublication) { // if maven-publish is applied
artifact tasks.sourceJar
}
nebulaIvy(IvyPublication) { // if ivy-publish is applied
artifact tasks.sourceJar
}
}
}
com.netflix.nebula.publish-verification
Plugin features are enabled only for Gradle 4.8 and higher. Creates a task which runs before actual publication into repositories. It catches some known bad patters so you can make explicit decision dependency by dependency.
Usage
This plugin is NOT automatically applied with nebula.ivy-publish
or nebula.maven-publish
. You have to apply the plugin to all modules within the project.
allprojects {
apply plugin: 'com.netflix.nebula.publish-verification'
}
Plugin is integrated with Gradle publishing and with Artifactory plugin. The task itself is a dependence of tasks with type PublishToIvyRepository
or PublishToMavenRepository
. The task will also get hooked to tasks named
artifactoryPublish
and artifactoryDeploy
coming from com.jfrog.artifactory
plugin. If you need any other integration
you have to manually configure relationship in your build file.
Your dependency has a lower status then your project violation
Explanation
When you are publishing a release build and your first level dependency (directly specified in your build file) is with lower status like candidate
(e.g. 1.2.0-rc.2
or latest.candidate
) or snapshot
(e.g. 1.2.0-SNAPSHOT
or latest.snapshot
) your build will fail. The reason for this check is a protection of your consumers. As a library producer, you could easily introduce lower status of dependencies in your consumer dependency graph. We consider that dependency with lower status means also lower or not completely guaranteed quality. This verification will explicitly highlight such dependencies and you can make an appropriate decision how to handle them instead of silently publishing.
How to resolve
The solution could be slightly different depending on your situation:
- Concrete violating version
1.2.0-rc.2
could be replaced with stable version1.2.0
latest.candidate
can be replaced withlatest.release
- Open range version
1.+
can currently also resolve to1.5-SNAPSHOT
, then you can switch to a preferred fixed version. - You might be having the right version in your file but some of your dependencies are depending on a lower status version which will win conflict resolution. The best is to fix your downstream library not depend on the lower status library.
- It can be a completely valid situation, that you depend on a candidate. Then you can ignore given library from this verification.
Your dependency has incorrect subversion definition
Explanation
An incorrect version definition is e.g. 1.1+. It would resolve to 1.1, 1.10, 1.11 etc. but it would miss versions like 1.2, 1.3 etc. This is not what most people would want. We are detecting this situation because it is hard to spot and it leads to unexpected dependency resolutions which are confusing build owners.
How to resolve
The right definition is 1.+ to use the highest version with major version 1 or you can use [1.1,] to use version 1.1 or higher.
How to ignore selected dependencies.
It might happen that you need to create a release which has to depend on a library which has a lower status. E.g. it contains critical bug fix or you are early adopter of release candidates. You can exclude those libraries from the checking process.
dependencies {
implementation 'group:this_will_be_checked:1.0'
implementation nebulaPublishVerification.ignore('foo:bar:1.0-SNAPSHOT')
implementation nebulaPublishVerification.ignore(group: 'baz', name: 'bax', version: '1.0-SNAPSHOT')
}
Or you can use extension for this plugin which allows you exclude not just single artifacts but whole groups.
nebulaPublishVerification {
ignore('foo:bar:1.0-SNAPSHOT')
ignoreGroup 'com.company.foo.group'
}
Gradle Compatibility Tested
Built with Azul JDK8 Tested with Azul JDK8, JDK11, JDK17
| Gradle Version | Works | | 7.0 | yes | | 8.0 | yes | | 8.1 | yes |
LICENSE
Copyright 2014-2023 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.