Gradle JAR Creation Timing - gradle

i have a gradle build that retrieves properties file and such that are remote (to keep passwords out of github) but the remote retrieval doesn't complete by the time the JAR is built.
i figured i either had to get the JAR created in the execution phase instead of configuration phase or add the remote files in the execution phase but i couldn't get either working.
any suggestions?
task fatJar(type: Jar) {
doFirst {
exec {
executable './scripts/getRemoteResources.sh'
}
}
...
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it)
}
//some resources are retrieved remotely & b/c of timing they don't get included here
from ('src/main/java/resources') {
include '*'
}
with jar
//tried this but doesn't work
//doLast {
// jar {
// from ('src/main/java/resources') {
// include '*'
// }
// }
//}
}

You shouldn't use the task graph for this. Also you shouldn't download the file to src/main/
Instead, you should
Create a task to download the remote resources to a directory under $buildDir (so it's cleaned via the "clean" task)
Configure the TaskOutputs so that the result can be cached and re-used.
Wire the task into Gradle's DAG
Add the directory to the "processResources" task so it ends up on the runtime classpath (ie in the jar)
Eg:
tasks.register('remoteResources', Exec) {
inputs.property('environment', project.property('env')) // this assumes there's a project property named 'env'
outputs.dir "$buildDir/remoteResources" // point 2 (above)
commandLine = [
'./scripts/getRemoteResources.sh',
'--environment', project.property('env'),
'--outputdir', "$buildDir/remoteResources"
]
doFirst {
delete "$buildDir/remoteResources"
mkdir "$buildDir/remoteResources"
}
}
processResources {
from tasks.remoteResources // points 3 & 4 (above)
}
See The Java Plugin - Tasks
processResources — Copy
Copies production resources into the production resources directory.

this seems to work so i'm going with it unless someone has a better solution...
gradle.taskGraph.beforeTask { Task task ->
println "just before $task.name"
// i just chose to kick this off with the first task sent through here
if (task.name=="compileJava") {
exec {
executable './scripts/getRemoteResources.sh'
}
}
}
task fatJar(type: Jar) {
...
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it)
}
from ('src/main/java/resources') {
include '*'
}
with jar
}

Related

Execute one gradle task

I've this two tasks:
war {
webInf { from 'src/main/resources/WEB-INF' }
manifest {
attributes 'Implementation-Version': versioning.info.display
}
}
task createDemoWar(type: War, dependsOn: classes) {
archiveName "webapi-demo-${versioning.info.display}.war"
destinationDir = file("$buildDir/dist")
copy {
from 'scopes'
include 'configuration.demo.properties'
into 'src/main/resources/'
}
}
task createDevelopmentWar(type: War, dependsOn: classes) {
archiveName "webapi-dev-${versioning.info.display}.war"
destinationDir = file("$buildDir/dist")
copy {
from 'scopes/'
include 'configuration.development.properties'
into 'src/main/resources/'
}
}
Both tasks are trying to copy a property file fromscopes folder to src/main/resources/ folder.
I only run one task, however two files are copied in src/main/resources/ (configuration.demo.properties and configuration.development,properties.
Any ideas?
You use two copy specifications at the configuration phase (note, copy specification in that case doesn't configure your task, but add some extra action to it's configuration). That means, your files are getting copied during configuration. That's all because of this:
copy {
...
}
You have to run it during execution, to do that, try to move it into the doLast or doFirst closure, like so (for both tasks):
task createDemoWar(type: War, dependsOn: classes) {
archiveName "webapi-demo-${versioning.info.display}.war"
destinationDir = file("$buildDir/dist")
doFirst {
copy {
from 'scopes'
include 'configuration.demo.properties'
into 'src/main/resources/'
}
}
}
In that case, files will be copied only if task will be executed, right before the execution.

Gradle - "apply from" a ZIP dependency

In my Gradle build script I want to import a ZIP dependency that contains static analysis configuration (CheckStyle, PMD etc.) and then "apply from" the files in that ZIP. When anyone runs the "check" task, my custom static analysis configuration should be used then.
I've tried the somewhat convoluted solution below, but I can't get it to work. The files are retrieved and unpacked into the "config" directory, but "apply from" does not work - Gradle complains it cannot find the files; I assume this is due to "apply from" being run during the build configuration phase.
Is there a simpler way to do this?
repositories {
maven { url MY_MAVEN_REPO }
}
configurations {
staticAnalysis {
description = "Static analysis configuration"
}
}
dependencies {
staticAnalysis group:'my-group', name:'gradle-static-analysis-conf', version:'+', ext:'zip'
}
// Unzip static analysis conf files to "config" in root project dir.
// This is the Gradle default location.
task prepareStaticAnalysisConf(type: Copy) {
def confDir = new File(rootProject.projectDir, "config")
if (!confDir.exists()) {
confDir.mkdirs()
}
from {
configurations.staticAnalysis.collect { zipTree(it) }
}
into confDir
apply from: 'config/quality.gradle'
}
check.dependsOn('prepareStaticAnalysisConf')
You are perfectly right: Gradle runs apply during evaluation phase, but the prepareStaticAnalysisConf was not executed yet and the archive is not unpacked.
Instead of a task, just write some top-level code. It should do the trick. Also, you'd better use the buildscript level dependency, so that it is resolved before script is executed.
Here is the full script
buildScript {
repositories {
maven { url MY_MAVEN_REPO }
}
dependencies {
classpath group:'my-group', name:'gradle-static-analysis-conf', version:'+', ext:'zip'
}
}
def zipFile = buildscript.configurations.classpath.singleFile
copy {
from zipTree(it)
into 'config'
}
apply from: 'config/quality.gradle'

Gradle copy build script dependency to folder

We are building one of our applications with gradle and part of the distribution I want to include an external jar which is not a run time dependency in a config folder. That jar is needed as part of the application install and it contains some custom ant tasks.
Our build script dependency looks like below:
buildscript {
...
dependencies {
classpath 'org.jfrog.buildinfo:build-info-extractor-gradle:3.1.1'
classpath 'my-group:custom-tasks:1.2.3'
}
}
How would I access and copy the custom-task-1.2.3.jar into a certain folder so I can include it in my distribution? Something like below:
task copyCustomTasks {
doLast {
copy {
// This below is a make up to express what I want
from buildscript.dependencies
include 'custom-tasks*.jar'
into "$buildDir/config"
}
}
}
If this is not the gradle way of doing things please let me know what alternatives I have.
Thank you in advance for your help.
UPDATE
I solved my problem in a different way by creating an extra configuration. However I would still be interested to find out how you can access build script dependencies at run time. Thanks again for your inputs.
configurations {
install {
description = "application install classpath"
transitive = true
}
}
...
dependencies {
...
install('my-group:custom-tasks:1.2.3')
...
}
...
task copyInstallDeps {
doLast {
copy {
from configurations.install
into "$buildDir/config"
}
}
}
You're quite close:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.google.guava:guava:18.0'
}
}
task copyLibs(type: Copy) {
from buildscript.configurations.classpath
into 'lib'
}

whenReady not setting gradle property before task runs

I have a a version property in my gradle.properties file that gives the version I am building. I have a task in the build called release that if present in the task graph will upload to the snapshot repo. However what is happening is that even though I include the release task in the build tasks, snapshot is not appended to my version property when uploadArchives runs so it attempts to upload to the wrong repository and fails. The when ready runs, but it does not seem to run before uploadArchives. Can anyone explain what is happening here?
uploadArchives {
repositories {
ivy {
credentials {
username nexusUser
password nexusPassword
}
if (version.endsWith("-SNAPSHOT")) {
url nexusSnapshotRepository
} else {
url nexusReleaseRepository
}
}
}
}
gradle.taskGraph.whenReady {taskGraph ->
if (!taskGraph.hasTask(release)) {
version = version + '-SNAPSHOT'
}
println "release task not included - version set to $version"
}
task release(){
doLast{
println "Releasing"
}
}
This is very similar to the example on the gradle site so I don't see what is going wrong.
http://www.gradle.org/docs/current/userguide/tutorial_using_tasks.html
The script is checking the project.version value in the configuration phase (not when the task executes), but only modifying it after the task execution graph has been built. One way to fix this is to override the repository url from inside the taskGraph.whenReady callback:
uploadArchives {
repositories {
ivy {
name "nexus"
url nexusReleaseRepository
...
}
}
}
gradle.taskGraph.whenReady { taskGraph ->
if (!taskGraph.hasTask(release)) {
version += '-SNAPSHOT'
uploadArchives.repositories.nexus.url nexusSnapshotRepository
// ps: println has to go inside here
}
}

Gradle: 'clone' original jar task to create a new task for a jar including dependencies

I would like to create a new task in my project that creates a jar archive with the class files of my project and the class files of the dependencies (also called 'shaded jar' or 'fat jar').
The solution proposed by the Gradle cookbook modifies the standard jar task of the JavaPlugin:
jar {
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
However, I would like to keep the original jar taks as it is and have an additional task for the shaeded jar, i.e. a task that behaves exactly like the jar task, but includes the additional files according to
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
and has another classifier ('shaded').
I tried to take over the configuration of the jar task by copying properties like this:
task shadedJar(type: Jar, dependsOn: configurations.compile) {
dependencies = tasks.jar.taskDependencies
source = tasks.jar.source
manifest = tasks.jar.manifest
includes = tasks.jar.includes
classifier = 'shaded'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
But the resulting tasks does not take over the dependencies of 'jar' and the resulting jar does not include the project's class files. Additionally, this approach seems to cumbersome to be the recommended way of using an existing task as a template for a new one.
What would a recommendable approach to my specific need (the seperate shadedJar task) and for 'cloning' tasks to use them as templates for additional tasks in general?
(I am currently still on Gradle 1.3,but solutions for the current Gradle version are also welcome)
There is no built-in way to clone tasks. However, it's easy to configure the fatJar task to include the same files as the java plugin's jar task:
task fatJar(type: Jar) {
appendix = "fat"
from sourceSets.main.output // that's it
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
Task autowiring will automatically establish the necessary task dependencies.
If the build script goes on to customize the jar task, you can apply the customizations to both tasks simultaneously:
configure([jar, fatJar]) {
version = "2.0"
entryCompression = "STORED"
}
If, unlike in the jar task's case, you are defining the "template" yourself, you can "instantiate" it with a factory method:
def getMeAnotherOne(String name) {
task(name, type: Jar) {
version = "2.0"
entryCompression = "STORED"
}
}
getMeAnotherOne("jar1")
getMeAnotherOne("jar2")

Resources