how can i add a gradle exec task with properties? - bash

i have a problem with a gradle exec task.
code:
task startup {
final GradleVersion gradleVersion = GradleVersion.current()
println "##### start script #####"
println "gradle version: ${gradleVersion}"
println "project: ${project.group}.fmp-${project.name}-${project.version}"
}
task create(type: Exec) {
workingDir "./scripts"
commandLine "./create_service_from_template.sh", sn, gwv
}
So when I execute gradle create -Psn=test -Pgwv=4.0 then it works.
but when I start another task (like gradle startup then an error appears:
Could not get unknown property 'sn' for task ':create' of type org.gradle.api.tasks.Exec.
I thought I can put the lines in the create Task into a doLast block, but then it doesn't work.
Can some one help me please?
Thanks.

This happens because Gradle will run the Configuration phase on all tasks.
One fix is to use local variables which are initialized with a check to see if the property was specified. See the beginning:
def sn = project.hasProperty('sn') ? project.sn : ''
def gwv = project.hasProperty('gwv') ? project.gwv : ''
task startup {
final GradleVersion gradleVersion = GradleVersion.current()
println "##### start script #####"
println "gradle version: ${gradleVersion}"
println "project: ${project.group}.fmp-${project.name}-${project.version}"
}
task create(type: Exec) {
workingDir "./scripts"
commandLine "./create_service_from_template.sh", sn, gwv
}

Related

Custom Gradle exec tasks won't run in parallel

My goal is that I can run ./gradlew deployStaging, and it executes buildDockerStatic, and buildDockerBackend in parallel, and after both tasks have finished, the deployStaging will run. With the code below, the tasks run serially. I've tried a few things, but buildDockerStatic, and buildDockerBackend always run serially.
tasks.register("buildDockerStatic", BuildDockerStatic) {
workingDir rootDir
}
tasks.register("buildDockerBackend", BuildDockerBackend) {
workingDir rootDir
}
//noinspection GroovyAssignabilityCheck
task deployStaging() {
dependsOn tasks.buildDockerStatic
dependsOn tasks.buildDockerBackend
doLast {
exec {
workingDir rootDir
commandLine 'sh', './scripts/build_deploy_staging.sh'
}
}
}
class BuildDockerStatic extends AbstractExecTask<BuildDockerStatic> {
BuildDockerStatic() {
//noinspection GroovyAssignabilityCheck
super(BuildDockerStatic)
commandLine 'sh', './scripts/build_static.sh'
}
}
class BuildDockerBackend extends AbstractExecTask<BuildDockerBackend> {
BuildDockerBackend() {
//noinspection GroovyAssignabilityCheck
super(BuildDockerBackend)
commandLine 'sh', './scripts/build_backend.sh'
}
}
In order to be run in parallel, the build tasks need to be placed in sub-projects.
They should contain doLast; otherwise they will be executed when calling eg. gradle clean. And probably, a definition using the plain task {..} will be enough.
Parallel: from the docs at Gradle:parallel execution
By using the --parallel switch, you can force Gradle to execute tasks in parallel as long as those tasks are in different projects.
See a modified example below; it will run two sub-tasks (to sleep and log), in parallel.
It can be run with gradle clean deployStaging --parallel
Multi project structure
build-backend
+--build.gradle
build-static
+--build.gradle
build.gradle
settings.gradle
build-backend/build.gradle :
apply plugin: 'base'
task buildDockerBackend {
doLast{
exec {
println 'BuildDockerBackend: started at ' + new java.util.Date()
workingDir rootDir
sleep 4000
//commandLine 'sh', './scripts/build_backend.sh'
commandLine 'echo', 'task: build-backend'
println 'BuildDockerBackend: done at ' + new java.util.Date()
}
}
}
build-static/build.gradle
apply plugin: 'base'
task buildDockerStatic {
doLast{
exec {
println 'BuildDockerStatic: started at ' + new java.util.Date()
workingDir rootDir
sleep 8000
//commandLine 'sh', './scripts/build_static.sh'
commandLine 'echo', 'task: build-static'
println 'BuildDockerStatic: done at ' + new java.util.Date()
}
}
}
build.gradle
apply plugin: 'base'
task deployStaging {
doLast {
exec {
workingDir rootDir
//commandLine 'sh', './scripts/build_deploy_staging.sh'
commandLine 'echo', 'task: deploy-staging'
}
}
}
deployStaging.dependsOn ':build-static:buildDockerStatic'
deployStaging.dependsOn ':build-backend:buildDockerBackend'
settings.gradle
include 'build-static'
include 'build-backend'

gradle tasks -all throwing error

I have test build.gradle file as follows
task someTask(type: Sync) {
def folder = new File('fold1/fold2/');
if(!folder.exists()) {
throw new GradleException('Folder Absent');
}
else {
}
}
When I do gradle tasks --all it is running the task and throwing exception. I was thinking that only when this task is run that it will check for folder but it is actually running it for any task I run.
Can someone suggest workaround for this?
Thanks in advance.
Your code is executed during the configuration phase and not during the execution phase. You need to put it in a doFirst or doLast block:
task someTask(type: Sync) {
doLast {
def folder = new File('fold1/fold2/');
if (!folder.exists()) {
throw new GradleException('Folder Absent');
}
else {
}
}
}
See also: Why is my Gradle task always running?

A Gradle task (type: Exec) is not executed during the configuration phase

I am reading about Gradle build lifecycle
Here is my script:
task startTomcat(type:Exec) {
commandLine 'cmd', '/c', 'echo init startTomcat'
}
task stopTomcat(type:Exec) {
// on windows:
commandLine 'cmd', '/c', 'echo init stopTomcat!'
doLast {
commandLine 'cmd', '/c', 'echo doLast stopTomcat!'
}
}
task configured(type:Exec) {
println 'configured. method body'
}
task test2 {
doLast {
println 'test2 doLast'
}
}
task testBoth2 {
doFirst {
println 'testBoth2 doFirst'
}
doLast {
println 'testBoth2 doLast'
}
println 'testBoth2. method body'
}
I run task2:
gradlew test2
This is the output:
Parallel execution with configuration on demand is an incubating feature.
configured. method body
testBoth2. method body
:test2
test2 doLast
BUILD SUCCESSFUL
It looks like the calls to commandLine were ignored. Why?
The Exec task's commandLine properly only configures what to do if the task is executed. As such you don't see the actual command doing anything during the configuration phase.

Gradle, task type: Exec - commandLine not work in onLast

I want execute some command from command line in gradle task(e.g. print all files in dir):
task dir(type: Exec) {
def adbCommand = ["dir", "*.*"]
commandLine adbCommand
standardOutput = new ByteArrayOutputStream()
doLast {
println ("result = " + standardOutput)
}
}
It's work. OK. But when I put it on onLast section it's not work:
task dir(type: Exec) {
doLast {
def adbCommand = ["dir", "*.*"]
commandLine adbCommand
standardOutput = new ByteArrayOutputStream()
println ("result = " + standardOutput)
}
}
I get error:
FAILURE: Build failed with an exception.
What went wrong:
Execution failed for task ':app:dir'.
execCommand == null!
The reason is in the fact, that task of Exec should be configured during configuration phase of the build, otherwise your task will be not configured and fail.
In you first example everything works due to configuration happens at the configuratyion phase. Your second example tries to configure the task within doLast closure - right after the task is executed yet.
If you really need to execute something in doLast, you can use something like this, without creating special task:
task someTaskName {
doLast {
exec {
commandLine adbCommand
}
}
}
Here is exec-specification used to execute some command and it's configured and executed at the same time.

Gradle - How to set dependency tasks for Exec-type tasks?

Say, you have following task:
task commandA() {
doLast {
project.ext.ping = 'PING'
}
}
This will work:
task commandB() {
dependsOn commandA
doLast {
println ping
}
}
This will fail:
task commandC(type: Exec) {
dependsOn commandA
commandLine "echo", ping
}
With Could not find property 'ping' on task 'commandC'. error message.
So, how one can declare dependency for an exec-type task and set some variable in that dependency?
Just don't initialize the variable within the doLast block, since it's getting initialized at the execution phase, but commandLine "echo", ping is trying to get it at the configuration phase of the build.
So, you need something like that:
task commandA() {
project.ext.ping = 'PING'
}
Or even without task, as follows:
project.ext.ping = 'PING'
Because configuration of any task is always executed, even if the task's action won't be executed.
Another solution is to use exec-action, not exec-task, something like this:
task commandA() {
doLast {
project.ext.ping = 'PING'
}
}
task commandC {
dependsOn commandA
doLast {
exec {
commandLine ping, "192.168.100.1"
}
}
}
In this case, exec-closure will be done during execution phase wuth the ping variable already available.
You can read about build lifecycle in the official Gradle user guide

Resources