How to handle a conditional artifact?

Consider a project with multiple sub-projects. Each subproject is configured to create a publish an artifact, however, is rare cases one of the sub-projects cannot create the defined artifact as it does not apply (for example: in this case, the subproject does not contain any JSPs). When publishing, get an error indicating the artifact is missing.

How can I conditionally publish the artifact if one was created (or skip)? In most circumstances the artifact is relevant, there a few cases where that particular artifact is not relevant.

gradlew.bat publish :buildSrc:compileJava UP-TO-DATE … :buildSrc:build UP-TO-DATE :mrc-widget:web:generatePomFileForJavaPublication :mrc-widget:web:compileJava UP-TO-DATE :mrc-widget:web:processResources UP-TO-DATE :mrc-widget:web:classes UP-TO-DATE :mrc-widget:web:compileGwt UP-TO-DATE :mrc-widget:web:webContentZip :mrc-widget:web:jar UP-TO-DATE :mrc-widget:web:sourcesJar UP-TO-DATE :mrc-widget:web:compileJavaServerPages :mrc-widget:web:webApplicationArtifact UP-TO-DATE :mrc-widget:web:publishJavaPublicationToMavenRepository FAILED

FAILURE: Build failed with an exception.

  • What went wrong: Execution failed for task ‘:mrc-widget:web:publishJavaPublicationToMavenRepository’. > Failed to publish publication ‘java’ to repository ‘maven’

Invalid publication ‘java’: artifact file does not exist: ‘mrc-widget\web\build\distributions\sc-mrc-widget-web-4.1-SNAPSHOT-webApplication.zip’ BUILD FAILED

In the sample above, webApplicationArtifact task is up-to-date.

/build.gradle Each leaf project is configured like this: apply from: “$rootDir/gradle/web.gradle”

/gradle/web.gradle task compileJavaServerPages(group: ‘Web’, type: JavaExec) {

configurations { crunch }

dependencies { crunch libraries.jspcruncher }

inputs.dir webApplicationSourceDirectory

outputs.dir webApplicationBuildDirectory

main = ‘crunch.crunchAll.CrunchAll’

classpath = configurations.crunch

standardOutput = new ByteArrayOutputStream()

errorOutput = standardOutput

args = [

‘-mod’,

‘D’,

file(webApplicationBuildDirectory).absolutePath,

minifyJavaServerPagesBuildDirectory

]

doFirst {

delete webApplicationBuildDirectory, minifyJavaServerPagesBuildDirectory

copy {

from webApplicationSourceDirectory

into webApplicationBuildDirectory

}

}

doLast {

copy {

from minifyJavaServerPagesBuildDirectory

into webApplicationBuildDirectory

}

file(getTemporaryDir().absolutePath + ‘/crunch.log’).text = errorOutput.toString()

} }

task webApplicationArtifact(group: ‘Web’, type: Zip) {

from compileJavaServerPages

includeEmptyDirs = false

duplicatesStrategy = DuplicatesStrategy.EXCLUDE

baseName = jar.baseName

classifier = ‘webApplication’ }

artifacts {

webApplication webApplicationArtifact }

publishing {

publications {

java(MavenPublication) {

artifact source: webApplicationArtifact, classifier: ‘webApplication’ // sometimes relevant

artifact source: otherA, classifier: ‘otherA’ // always relevant

artifact source: otherB, classifier: ‘otherB’ // always relevant

}

} }

It’s pretty simple to conditionally add configuration to your build script. Quite simply, just wrap the configuration in a conditional. I’m not quite certain what the most appropriate condition to key off of would be in this case, but for the sake of example, let’s just say we don’t want to add that artifact of the ‘projectB’ project.

publishing {

publications {

java(MavenPublication) {

if(project.path != ‘:projectB’) {

artifact source: webapplicationArtifact, classifier: ‘webApplication’

}

}

}

}

Thanks - that could help, but I need something that is not as ‘hardcoded’.

I would like behavior to be similar to that of having a ‘java’ project with no source code. An empty jar is created.

Interestingly enough, when I changed the webApplicationArtirfact task type from ‘Jar’ to ‘Zip’, that is what I get - an empty jar. But when a change back to ‘Zip’, the task is marked up-to-date. Could this be related to: https://issues.gradle.org/browse/GRADLE-2827. Any workarounds?

You could key off of whether the artifact contains anything.

if (zipTree(webApplicationArtifact).files.size() > 0)) {

}

Also, I believe the difference in the behavior you are seeing with ‘Jar’ vs ‘Zip’ is that the ‘Jar’ task generates a manifest, so it will always have at least one file in it, even if there are no other inputs.

Thanks… This worked…

if (webApplicationArtifact.outputs.files.singleFile.exists()) {

artifact source: webApplicationArtifact, classifier: ‘webApplication’

}

You could simplify this to ‘webApplicationArtifact.archivePath.exists()’.