How to pass text parameters into a Gradle task from another gradle task (not command line) - gradle

I'm wondering how I can pass a parameter (PARAM) to a Gradle task from another Gradle task that depends on it.
For example something along these lines
task buildDist(PARAM) {
copy {
from "$projectDir/src/{PARAM}/ClientBanner.json"
into "$buildDir/${project.name}/"
}
and call this Gradle task from another one like:
task dist(type: Zip) {
from "$buildDir"
include "${project.name}/**/*"
archiveFileName = project.name + '.zip'
destinationDirectory = layout.buildDir.dir('dist')
dependsOn('buildDist(PARAM)')
}

#Shapebuster
The Gradle build script is Groovy (or Kotlin) based and can be extended using the supported syntax of that language. So, in your example, you should be able to use the PARAM like so:
task buildDist(String param1) {
copy {
from "$projectDir/src/$param1/ClientBanner.json"
into "$buildDir/${project.name}/"
}
}
and then:
task dist(type: Zip) {
from "$buildDir"
include "${project.name}/**/*"
archiveFileName = project.name + '.zip'
destinationDirectory = layout.buildDir.dir('dist')
dependsOn buildDist("$param1")
}

Related

gradle zip task only creates zip in configuration phase

When I try to create a zip file in the execution phase of a Zip typed gradle task no zip file is created.
If I perform the same in the configuration phase (leaving out the doLast statement), the zip file is created without problems.
The doLast block is called since the println statement is shown in the output logging.
The reason that we need to generate the zip in the execution phase is because the file which needs to be compressed is the result of the compile execution.
I have also tried to solve this with a jar task, but this gives me similar problems.
Here's the code:
task createClassPathJar(type: Zip) {
dependsOn("createManifest")
from("${projectRoot}") {
include "MANIFEST.MF"
}
archiveName = "dummy.jar"
doLast {
destinationDir(file("${projectRoot}"))
archiveName = "zipfile.jar"
println "executing phase createClassPathJar. archiveName: " + archiveName
}
}
Can someone help me here ? I'm using Gradle v6.4.1.
You cannot use doLast to configure the action of your task, because it will be executed after the particular action (in this case the zipping) has run. Either use a doFirst closure or setup your task configuration in a way that it does not depend on other configurations:
As an example, depending on how properly your task createManifest defines its output, you may use it directly to define the Zip task content using "from createManifest".
I guess your reason for using a doLast closure is the call to destinationDir that is based on a variable. Instead, you may just use a closure that evaluates the variable lazily:
task createManifest {
outputs.file('path/to/MANIFEST.MF')
}
task createClassPathJar(type: Zip) {
from createManifest
archiveName = 'zipfile.jar'
destinationDir = file({ "${projectRoot}" }) // or just file({ projectRoot })
}
Try with doFirst instead of doLast:
task createClassPathJar(type: Zip) {
dependsOn("createManifest")
from("${projectRoot}") {
include "MANIFEST.MF"
}
archiveName = "dummy.jar"
doFirst {
destinationDir(file("${projectRoot}"))
archiveName = "zipfile.jar"
println "executing phase createClassPathJar. archiveName: " + archiveName
}
}
I don't know about your case but I tried myself by changing the archive name to the current time in the doFirst block, and the archive name was effectively matching the time of execution and not of configuration.

How do I get my custom gradle tasks to run?

I have a gradle project from which I want to generate two artifacts - a java jar, and a tarball of additional files.
So I added the following to my build.gradle
def serviceName = "kafka-schemas"
task packageDistribution(type: Copy) {
from "$buildDir/resources/main"
include "*.avsc"
into "$buildDir/schemas"
}
task archive(type: Tar) {
dependsOn 'packageDistribution'
compression = 'GZIP'
from("$buildDir/schemas") {
include "**/*.avsc"
}
into("${serviceName}")
}
project.tasks.findByName('build') dependsOn archive
project.tasks.findByName('build') dependsOn packageDistribution
However when I run gradle clean build it does not run my tasks.
What am I doing wrong?
Try this:
processResources.dependsOn('packageDistribution')
task packageDistribution(type: Zip) {
archiveFileName = "xxxxx.zip"
destinationDirectory = file("$buildDir/dist")
from "xxxx"
}

Gradle: Not able to run zipTree in doFirst block

I am trying to explode some jar files in a doFirst block as follows -
task copyBinaries(type: Copy){
def Jar1 = ""
def Jar2 = ""
def Jar3 = ""
doFirst {
Jar1 = configurations.Lib1.singleFile
Jar2 = configurations.Lib2.singleFile
Jar3 = configurations.Lib3.singleFile
}
inputs.files configurations.Lib1
inputs.files configurations.Lib2
inputs.files configurations.Lib3
from(zipTree(file(Jar1))) {
into('jar_folder1')
}
from(zipTree(file(Jar2))) {
into('jar_folder2')
}
from(zipTree(file(Jar3))) {
into('jar_folder3')
}
into('build/libs/')
}
}
In order the avoid resolution of dependencies in the configuration phase, I am extracting the file names from the configurations in the doFirst block. The problem is, since the Copy task needs the source and destination of copy during configuration phase, gradle sees Jar1, Jar2, Jar3 as empty strings and throws and error.
I am looking for a way to let the Copy task receive arguments (source file) during execution phase (after doFirst block is executed).
How can I address this situation? Thanks.
I've had a similar situation where I had to copy from a path that was created as output of another one.
I solved this with just declaring the copy logic in my task's doLast block:
task copyStuff {
doLast {
copy {
from zipTree('path/to/archive')
into 'destination/dir'
}
}
}
You just have to make sure, that your task runs after the task that creates the needed outputs with using dependsOn for example.

Gradle task to create a zip archive of a directory

I have a gradle task to create a zip archive of a directory.
The gradle task is:
task archiveReports(type: Zip) {
from '/projects/Reports/*'
archiveName 'Reports.zip'
}
When I am running the command 'gradle archiveReports', its showing the build is successful. However, no zip file is getting created.
Am I missing something here?
I figured out a way for this:
Its working for me now.
task myZip(type: Zip) {
from 'Reports/'
include '*'
include '*/*' //to include contents of a folder present inside Reports directory
archiveName 'Reports.zip'
destinationDir(file('/dir1/dir2/dir3/'))
}
With Gradle 6.7,
task packageDistribution(type: Zip) {
archiveFileName = "my-distribution.zip"
destinationDirectory = file("$buildDir/dist")
from "$buildDir/toArchive"
}
Note : archiveName is deprected.
With Kotlin DSL
tasks.register<Zip>("packageDistribution") {
archiveFileName.set("my-distribution.zip")
destinationDirectory.set(layout.buildDirectory.dir("dist"))
from(layout.buildDirectory.dir("toArchive"))
}
With Groovy
tasks.register('packageDistribution', Zip) {
archiveFileName = "my-distribution.zip"
destinationDirectory = layout.buildDirectory.dir('dist')
from layout.buildDirectory.dir("toArchive")
}
Taken from the official docs
Just in case anyone will come here to find out how to zip your project e.g. to use it as an AWS lambda zip, here you go:
tasks {
val zipTask by register("createZip", Zip::class) {
from(processResources)
from(compileKotlin)
archiveFileName.set("app.zip")
into("lib") {
from(configurations.runtimeClasspath)
}
}
build {
dependsOn(zipTask)
}
}

Gradle task should not execute automatically

I'm defining a task in gradle:
task releaseCandidate(type: Exec) {
commandLine 'git', 'checkout', 'develop'
// Increment version code in Manifest
String manifest = new File('AndroidManifest.xml').getText('UTF-8')
Pattern pattern = Pattern.compile('android:versionCode="([0-9]+)"')
Matcher matcher = pattern.matcher(manifest)
matcher.find()
int newVersionCode = Integer.parseInt(matcher.group(1)) + 1
manifest = manifest.replaceAll(
"android:versionCode=\"([0-9]+)\"", "android:versionCode=\"$newVersionCode\""
)
new File('AndroidManifest.xml').write(manifest, 'UTF-8')
commandLine 'git', 'diff'
}
Which I want to execute only when I explicitly call it as gradle releaseCandidate. However, when I run any other task, such as gradle assembleDebug, it also runs task releaseCandidate. I don't want that behaviour to happen. There is no task depending on releaseCandidate or vice-versa.
My project is an Android app, so I am using android gradle plugin.
A common pitfall. Add an action to the task otherwise code will run at configuration phase. Sample task with action:
task sample << {
}
As I see You'd rather need to write a custom task than using Exec type. I suppose it's not valid to define commandLine twice.
EDIT
You can read this post to get the general idea how it all works.
You are mixing Task configuration and groovy code. Everything that is part of the main body of a task definition will be executed in the configuration phase. The task task1 << { code } is a shorthand for
task task1 {
doLast {
code
}
}
commandLine is part of the Exec Task but your other code is not and should be wrapped into a doLast this will execute the commandline first and then execute your additional code. If you need another exec commandLine then you'll need another task.
task releaseCandidate(type: Exec) {
commandLine 'git', 'checkout', 'develop'
doLast {
// Increment version code in Manifest
String manifest = new File('AndroidManifest.xml').getText('UTF-8')
Pattern pattern = Pattern.compile('android:versionCode="([0-9]+)"')
Matcher matcher = pattern.matcher(manifest)
matcher.find()
int newVersionCode = Integer.parseInt(matcher.group(1)) + 1
manifest = manifest.replaceAll(
"android:versionCode=\"([0-9]+)\"", "android:versionCode=\"$newVersionCode\""
)
new File('AndroidManifest.xml').write(manifest, 'UTF-8')
}
}
Just to complete #Opal answer for cases when Exec is really used (for example CommandLine reference) :
task task1 << {
exec {
List<String> arguments = new ArrayList<String>()
//..
commandLine arguments
}
}

Resources