Global variable declaration on Gradle - go

I have a gradle task as follows. Setting the GOPATH before I start the build. When I run the second task, that is runUnitTest and GOPATH is not set inside that block and I see this error "$GOPATH not set".
task goBuild(type:Exec) {
environment 'GOPATH', projectDir.toString().split("/src")[0]
commandLine "go", "build", "main.go"
}
task runUnitTest(type:Exec) {
dependsOn goBuild
commandLine "go", "get", "github.com/AlekSi/gocov-xml"
commandLine "go", "test", "-v"
}
I can of course, set the GOPATH again inside the second task. But, I am curious on how to have globally set in gradle.

You can set the environmental property for all tasks of type Exec:
tasks.withType(Exec) {
environment 'GOPATH', 'hello'
}
task first(type:Exec) {
commandLine 'CMD', '/C', 'echo', "%GOPATH%"
}
task second(type:Exec) {
commandLine 'CMD', '/C', 'echo', "%GOPATH%"
}

Related

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, commandLine 'cmd', '/c', 'echo doLast!' does nothing

I'm reading about Gradle Exec and created the following build.gradle:
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!'
}
}
When I run gradlew stopTomcat, the output looks like this:
Parallel execution with configuration on demand is an incubating feature.
:stopTomcat
init stopTomcat!
I don't see the line doLast stopTomcat! Why can't I execute a command in doLast?
Your task is of type Exec. The commandLine method call configures the task by passing the cmd, /c and echo init stopTomcat! to it. This happens in the config phase.
Then the task runs in execution phase and prints:
init stopTomcat!
Then the doLast blocks starts and configures the task, passing cmd, /c and echo doLast stopTomcat! to it. This configuration has no effect as the taks already ran.
To get the second print out, you could do:
task stopTomcat(type:Exec) {
// on windows:
commandLine 'cmd', '/c', 'echo init stopTomcat!'
doLast {
exec {
commandLine 'cmd', '/c', 'echo doLast stopTomcat!'
}
}
}
This is another way how to invoke the exec task.

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

Gradle start scripts env

In gradle run task I have info about lib path:
run {
systemProperty "java.library.path", "lib/native"
}
Is it possible to add the same variable to some gradle task that will include variable to the bin scripts, for now I have to put them manualy but I would like to automate this with gradle:
CLASSPATH=$APP_HOME/lib/***.jar:$APP_HOME/lib/***.jar: ...
>>> LD_LIBRARY_PATH=$APP_HOME/lib
You can use some text, such as MY_APP_HOME, to define java.library.path in JVM arguments:
applicationDefaultJvmArgs = ['-Djava.library.path=MY_APP_HOMElib/native']
And then substitute it by start scripts APP_HOME variable in each script:
startScripts {
doLast {
unixScript.text = unixScript.text.replace('MY_APP_HOME', '\$APP_HOME/')
windowsScript.text = windowsScript.text.replace('MY_APP_HOME', '%APP_HOME%\\')
}
}

Optional Gradle properties

I have a Gradle build file where one of the the tasks is to login into docker. In this task I want that the user/CI provides the parameter docker_username, docker_password and docker_email.
task loginDockerHub(group: "Docker", type:Exec) {
executable "docker"
args "login","-u", docker_username, "-p", docker_password, "-e", docker_email
}
Executing gradle loginDockerHub -Pdocker_username=vad1mo ... all is working as expected.
But when I execute for example gradle build I get the error:
Could not find property 'docker_username' on task ':loginDockerHub'.
I would expect this error on executing gradle loginDockerHub without providing the -P parameter, but not on other tasks that don't access docker_username/password parameters.
How can I have optional parameters for my loginDockerHub task in Gradle that don't make the parameter mandatory for any other task.
You can check if the property exists and if not return a default.
args "login", "-u", project.hasProperty("docker_username") ? docker_username : ""
Update: Starting with Gradle 2.13 you can simplify this somewhat.
args "login", "-u", project.findProperty("docker_username") ?: ""
I was not able to find a solution to the problem. This description had a hint about about declaring actions within a task. Putting the shell exec into the action task has the behavior I was expecting, because actions are evaluated when the task executes.
task loginDockerHub(group: "Docker", type:Exec) {
doFirst{
executable "docker"
args "login","-u", docker_username, "-p", docker_password, "-e", docker_email
}
}
Executing the loginDockerHub without providing the docker_* parameters will yelled an error. Executing any other task will work as expected.
I had to do this and didn't want my build to fail with an error. I solved it by doing this:
ext.shouldLoginDockerHub = project.hasProperty("docker_username");
task loginDockerHub(group: "Docker") {
doLast{
if(shouldLoginDockerHub) {
exec {
executable "docker"
args "login","-u", docker_username, "-p", docker_password, "-e", docker_email
}
} else {
println "Not logging in to docker hub because docker_username was not provided.";
}
}
}
You could expand the first line to look for docker_password, docker_email, etc.

Resources