How to publish an XML file to Maven repo from Gradle - gradle

I have a static xml file that I want to publish to a Maven repository (my local Maven repo for now) from Gradle using the maven-publish plugin.
build.gradle looks like this:
apply plugin: 'maven-publish'
group 'com.example.gradletest'
version '1.0-SNAPSHOT'
publishing {
publications {
beta(MavenPublication) {
artifactId 'feature-file'
artifact 'src/main/resources/features.xml'
}
}
}
This works, but I would like to add a classifier too, where should I define that?
https://docs.gradle.org/current/userguide/publishing_maven.html says in section 68.2.2 that it should be possible to do:
publishing {
publications {
beta(MavenPublication) {
artifactId 'feature-file'
artifact ('src/main/resources/features.xml') {
classifier 'features'
}
}
}
}
but then I get this error:
A problem occurred configuring root project 'testapplication'.
Exception thrown while executing model rule: org.gradle.api.publish.plugins.PublishingPlugin$Rules#publishing(org.gradle.api.plugins.ExtensionContainer)
No signature of method: java.io.File.call() is applicable for argument types: (build_101arjzoe908rdkh5aikrn6bt$_run_closure5_closure16_closure19_closure20) values: [build_101arjzoe908rdkh5aikrn6bt$_run_closure5_closure16_closure19_closure20#2aa7399c]
Possible solutions: wait(), any(), wait(long), each(groovy.lang.Closure), any(groovy.lang.Closure), list()
Using the below solution will correctly add the classifier, but will also change the packaging in the pom.xml from <packaging>xml</packaging> to <packaging>pom</packaging>. I don't want that.
publishing {
publications {
beta(MavenPublication) {
artifactId 'feature-file'
artifact source: 'src/main/resources/features.xml', classifier: 'features'
}
}
}

Use the map syntax as specified here.
publishing {
publications {
beta(MavenPublication) {
artifactId 'feature-file'
artifact source: 'src/main/resources/features.xml', classifier: 'features'
}
}
}

Adding pom { packaging 'xml' }
works for me (gradle 3.2.1)
publishing {
publications {
beta(MavenPublication) {
artifactId 'feature-file'
artifact source: 'src/main/resources/features.xml', classifier: 'features'
pom { packaging 'xml' }
}
}
}

Related

How do I suppress POM and IVY related warnings in Gradle 7?

After upgrading to Gradle 7 I have many warnings like:
Cannot publish Ivy descriptor if ivyDescriptor not set in task ':myProject:artifactoryPublish' and task 'uploadArchives' does not exist.
Cannot publish pom for project ':myProject' since it does not contain the Maven plugin install task and task ':myProject:artifactoryPublish' does not specify a custom pom path.
The artifactoryPublish task works fine.
My Gradle script:
buildscript {
repositories{
maven {
url = '...'
credentials {
username '...'
password '...'
}
metadataSources {
mavenPom()
artifact()
}
}
}
dependencies {
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4.24.12"
}
}
apply plugin: 'java'
apply plugin: 'maven-publish'
apply plugin: org.jfrog.gradle.plugin.artifactory.ArtifactoryPlugin
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
suppressAllPomMetadataWarnings()
}
}
}
group = '...'
artifactory {
contextUrl = '...'
publish {
repository {
repoKey = '...'
username = '...'
password = '...'
}
defaults {
publishConfigs('archives')
publishIvy = false
publications("mavenJava")
}
}
}
How do I disable those warnings?
It looks like you mixed between the old Gradle publish-configuration method and the new Gradle publication method.
You applied the maven-publish plugin which allows creating publications. In artifactory.default, you added the "mavenJava" publication as expected.
However, the archives publish-configuration doesn't exist in your build.gradle file. Basically, publish-configurations are created by the legacy maven plugin. The configured mavenJava publication does the same as the archives publish-configuration and therefore all of the JARs are published as expected.
To remove the warning messages you see, remove the publishConfigs('archives') from artifactory.default clause:
artifactory {
publish {
defaults {
publishConfigs('archives') // <-- Remove this line
publishIvy = false
publications("mavenJava")
}
}
}
Read more:
Gradle Artifactory plugin documentation
Example

publish groovy doc with gradle

I have a project with about 50% Java code and 50% Groovy that i try to publish to Sonatype ossrh. Publishing snapshots goes well but the docs jar is missing (both when publishing locally and publishing to Sonatype Nexus). I can create the combined groovy/java docs by defining:
groovydoc {
use = true
groovyClasspath = configurations.compile // http://issues.gradle.org/browse/GRADLE-1391
}
task groovydocJar(type: Jar, dependsOn: groovydoc ) {
classifier 'javadoc' // must use javadoc classifier to be able to deploy to Sonatype
from groovydoc.destinationDir
}
and running ./gradlew groovydocJar produces the intended -javadoc.jar without problems.
My issue is that this docs jar is not included the publish task.
I tried the following
publishing {
publications {
maven(MavenPublication) {
from components.java
artifacts {
archives sourcesJar
archives groovydocJar
}
versionMapping {
usage('java-api') {
fromResolutionOf('runtimeClasspath')
}
usage('java-runtime') {
fromResolutionResult()
}
}
pom {
// omitted for brevity
}
}
}
}
... but e.g. `./gradlew publishToMavenLocal` publishes only the classes jar, the pom, a module and the sources jar.
No sign of a javadoc jar. I thought this was the idea of the artifacts section but maybe something is missing.
How can i tell the publishing task to include publishing of the groovydocs jar?
Gradle version is 6.8.3, jvm version is 1.8 and i depend on `compile 'org.codehaus.groovy:groovy-all:3.0.7'`
The complete build script is available here:
https://github.com/perNyfelt/ProjectDeployer/blob/main/build.gradle
I figured it out:
That artifacts.archives way was not working.
The syntax for adding the groovy doc is like this:
publishing {
publications {
maven(MavenPublication) {
from components.java
artifact(groovydocJar) {
classifier = 'javadoc'
}
// etc...
}
}
}

How to tie publishing of sources to installing to local Maven repository?

To install sources to local Maven repository, I was taught to write
apply plugin: "maven-publish"
task sourceJar(type: Jar) {
from sourceSets.main.allJava
}
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
artifact sourceJar {
classifier "sources"
}
}
}
}
and it copies files as required. Now I wish this work automatically along with install task of maven plugin.
I tried several lines like
install.dependsOn(publishing.publishSources)
or
install.dependsOn(publishSources)
but failed with various errors.
You could use the nebula.source-jar plugin. Or you could at least copy/paste the bolierplate from the readme.
Eg: Eliminates this boilerplate:
tasks.create('sourceJar', Jar) {
dependsOn tasks.classes
from sourceSets.main.allSource
classifier 'sources'
extension '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
}
}
}

How to exclude dependencies in the POM file generated by the Gradle

I'm using the "maven" plugin to upload the artifacts created by Gradle build to Maven central repository. I'm using a task similar to the following one:
uploadArchives {
repositories {
mavenDeployer {
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
pom.project {
name 'Example Application'
packaging 'jar'
url 'http://www.example.com/example-application'
scm {
connection 'scm:svn:http://foo.googlecode.com/svn/trunk/'
url 'http://foo.googlecode.com/svn/trunk/'
}
licenses {
license {
name 'The Apache License, Version 2.0'
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
}
}
}
}
However the POM file created by this task does not report correctly the dependencies that have been excluded in my Gradle build file. For example:
dependencies {
compile('org.eclipse.jgit:org.eclipse.jgit.java7:3.5.2.201411120430-r') { exclude module: 'commons-logging' }
compile('com.upplication:s3fs:0.2.8') { exclude module: 'commons-logging' }
}
How to have excluded dependencies managed correctly in the resulting POM file?
You can simply override the dependencies of the pom by filtering out the unwanted dependencies, e.g. to exclude junit you can add the following lines to the mavenDeployer configuration:
pom.whenConfigured {
p -> p.dependencies = p.dependencies.findAll {
dep -> dep.artifactId != "junit"
}
}
The problem was that in the exclude definition was not specified the group but only the module.
Adding the both of them the exclusions are added correctly in the POM file. For example:
compile('org.eclipse.jgit:org.eclipse.jgit.java7:3.5.2.201411120430-r') {
exclude group: 'commons-logging', module: 'commons-logging'
}
compile('com.upplication:s3fs:0.2.8') {
exclude group: 'commons-logging', module: 'commons-logging'
}
Using 'exclude' on a Gradle dependency is normally the correct answer, but I still needed to remove some of my "runtimeOnly" dependencies from the POM that led me to this StackOverflow page. My testing using Gradle 4.7 seems to show that using "compileOnly" leaves the dependency out of the pom entirely, but "runtimeOnly" adds a "runtime" dependency in the pom, which in my case, is not what I wanted. I couldn't figure out a "standard" Gradle way of leaving runtime dependencies out of the POM.
The pom.whenConfigured method shown in another answer works for legacy "maven" plugin publishing, but doesn't work for the newer "maven-publish" plugin. My experimentation led to this for "maven-publish":
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
pom.withXml {
asNode().dependencies.dependency.each { dep ->
if(dep.artifactId.last().value().last() in ["log4j", "slf4j-log4j12"]) {
assert dep.parent().remove(dep)
}
}
}
}
}
}

Publishing both jar and sources jar to Artifactory from Gradle

Here is my build.gradle:
buildscript {
repositories {
maven {
url 'http://localhost:8081/artifactory/plugins-release'
credentials {
username = "admin"
password = "password"
}
name = "maven-main-cache"
}
}
dependencies {
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:3.0.1"
}
}
apply plugin: 'groovy'
apply plugin: 'maven'
apply plugin: 'codenarc'
apply plugin: 'maven-publish'
apply plugin: "com.jfrog.artifactory"
version="0.0.2"
group = "mylib"
repositories {
mavenCentral()
add buildscript.repositories.getByName("maven-main-cache")
maven {
url "http://localhost:8081/artifactory/myapp-snapshots"
}
}
dependencies {
compile 'commons-validator:commons-validator:1.4.0'
testCompile 'junit:junit:4.11'
}
artifactory {
contextUrl = "http://localhost:8081/artifactory"
publish {
repository {
repoKey = 'myorg-snapshots'
username = "admin"
password = "password"
maven = true
}
defaults {
publications ('mavenJava')
}
}
}
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
}
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
}
artifacts {
archives sourcesJar
}
task dist(type: Zip, dependsOn: build) {
classifier = 'buildreport'
from('build/test-results') {
include '*.xml'
into 'tests'
}
from('build/reports/codenarc') {
into 'reports'
}
from('build/docs') {
into 'api'
}
from(sourcesJar) {
into 'source'
}
from('build/libs') {
exclude '*-sources.jar'
into 'bin'
}
}
Based on this current setup:
To build my JAR I have to run gradle clean build groovydoc sourcesJar dist and then
To publish to Artifactory, I have to run a second command of gradle artifactoryPublish
Two things I'm looking to change here:
gradle artifactoryPublish only publishes my built JAR and a dynamically-created POM to Artifactory. I'd like it to also publish the sources JAR that my build is creating. How?; and
Ideally I'd like to be able to do all of the above by just invoking gradle publish instead of having to run the 2 commands sequentially. Is this possible? If so, how?
When it comes to publishing source you need to modify your script in the following way:
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
artifact (sourcesJar) {
classifier = 'sources'
}
}
}
}
When it comes to a single command what you need to do is to define dependencies between tasks. Unfortunately I can't try the script so it may be redundant but should do the job:
artifactoryPublish.dependsOn('clean', 'build', 'groovydoc', 'sourcesJar', 'dist')
publish.dependsOn(artifactoryPublish)

Resources