Gradle won't run the shell commandLines I want - windows

I've done a lot of Android dev never needing to understand gradle well.
Ideally I'd be running a python script after setting up a virtualenv, but for this question I'm happy with a MWE.
task rem(type: Exec) {
doLast {
exec {
workingDir '.'
commandLine 'dir'
}
}
}
Results in:
> Task :app:rem FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:rem'.
> execCommand == null!
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 2s
1 actionable task: 1 executed
Let's say I go back to how I was declaring my tasks before shelling out:
task rem {
without (type: Exec) I get:
> A problem occurred starting process 'command 'dir''
where before I had
> execCommand == null!
I have only got the following commandLine to work:
task rem(type: Exec) {
commandLine 'python', '--version'
}
replacing body with commandLine 'dir' fails with
...
> A problem occurred starting process 'command 'dir''
...

Eventually stumbled on https://stackoverflow.com/a/37871837/866333 for running windows scripts and found chaining, https://stackoverflow.com/a/50394682/866333, more easily.
task rem(type: Exec) {
commandLine 'cmd', '/c', "cd && virtualenv --python=\"C:\Program Files\Python38\python.exe\" C:\Users\XXX\AndroidStudioProjects\YYY\virtualenvs\ZZZ"
}
Had good success with the above snippet (using double quotes so I could substitute XXX YYY ZZZ from earlier computations. It isn't pretty but the python script will be.
Hopefully this will save another gradle newbie the hours I needed.
Note the cd to begin the (nominal) chain. I was not in the directory I expected.

Related

Cannot call ruby rake with parameter containing spaces in jenkins pipeline

I have Jenkins Pipeline that will deploy a pod with a container using my ruby's application image, and there is a stage that will run a rake command from a $COMMAND parameter like this:
rake db_command:count_data[histories,status IN ("active","pending")] inside the container.
this is the step I wrote on my stage to run the rake command from a $COMMAND parameter:
stage("Rake Task") {
try {
container("ruby-rake-task") {
sh '''
cd /var/www/mos
${COMMAND}
'''
}
} catch(e) {
echo "rake failed"
sh "exit 1"
}
}
but I get this error from console output jenkins:
+ cd /var/www/mos
+ rake 'db_command:count_data[histories,status' IN '("active","pending")]'
rake aborted!
Don't know how to build task 'db_command:count_data[histories,status' (See the list of available tasks with `rake --tasks`)
/usr/local/bundle/gems/rake-13.0.6/exe/rake:27:in `<top (required)>'
(See full trace by running task with --trace)
it seems the jenkins or groovy won't execute the rake command as a whole command, and instead it split the command to three parts. Jenkins is somehow always give a quote for all parameters after 'rake' command this really hard when the parameter is having spaces like above.
I already try adjust my stage step like this:
stage("Rake Task") {
try {
container("ruby-rake-task") {
sh "cd /var/www/mos"
def rakeTask = $/eval ${COMMAND}/$
resultRake = sh(script: "${rakeTask}", returnStdout: true).toString()
echo "${resultRake}"
}
} catch(e) {
echo "rake failed"
sh "exit 1"
}
}
yet the result is produce another error like this:
[Pipeline] stage
[Pipeline] { (Rake Task)
[Pipeline] container
[Pipeline] {
[Pipeline] sh
+ cd /var/www/mos
[Pipeline] sh
/home/jenkins/agent/workspace/RUBY-APP-RAKE-TASK#tmp/durable-c0e8d0d4/script.sh: line 1: syntax error: unexpected "("
[Pipeline] }
[Pipeline] // container
what do I need to do to be able run this rake task as a whole command included the spaces parameter? can someone tell me what am I missing here?
Thank you!
I'm using a node container with entrypoint "bash" and resolved errors like your.
I adapt it for you:
"-c \"cd /var/www/mos && ${command}\""
I hope it helps.

Gradle exec commandLine does not work as expected

I'm currently working on a Gradle project in OSX
My function in a .gradle file looks like this
ext.MyFunction = {
def fastlaneCommand = [
'fastlane',
'-version'
]
def stdout = new ByteArrayOutputStream()
exec {
ignoreExitValue true
standardOutput stdout
workingDir PathsModel.instance.GetDeployerRoot()
commandLine fastlaneCommand
LOG.WARN("YOUR CLI COMMAND: " + commandLine)
}
println "Output:\n$stdout"
}
And then in 'build.gradle'
task jenkins_deploy() {
doFirst {
MyFunction()
}
}
When it comes time for commandLine to be executed
This outputs:
W A R N I N G: YOUR CLI COMMAND: [fastlane, -version]
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':jenkins_deploy'.
> A problem occurred starting process 'command 'fastlane''
I know for a fact that fastlane is in my path as '$HOME/.fastlane/bin' which is where the executable is located. And if I simply open Terminal and type
'fastlane -version'
from any directory, fastlane tools start-up and do what they're supposed to be doing.
I suppose my question is:
What are the possible differences between me opening a terminal and inputting the command manually, and me asking Gradle to do the exact same thing using 'exec'?
Am I misunderstanding what 'exec' and 'commandLine' actually do?
Some info on 'fastlane' is that it's using Ruby, which i don't know a lot about. This may prove relevant.
EDIT: I have attempted 'version' the 2nd element in the fastlaneCommand array, as both 'version' and '-version'
EDIT 2 (ACTUAL SOLUTION): Although the marked answer below is a definite workaround, the solution Actual solution has the full reason as to why this happens and why it works.
TL;DR
I suppose it should be:
['sh', 'fastlane', '-version']
Explanation:
Have not the link under my arm, but if you omit sh it would be executed as a script located in current directory (or directory configured as the second argument). If you prefix it with sh it will be executed with shell and $PATH variable.

test a bash script with gradle

we're using gradle as build tool and for our java and ansible projects. Now I would like to test a bash script from within gradle as well.
Do you have any tipps/resources or better even an example how I can test a bash script using gradle? It can be as simple as executing the script and having the "test" pass, if the return value of the bash script under test is 0 or if the stdout or stderr contain certain strings (or don't contain them).
Thanx a lot in advance for your help!
Here's an example of a Gradle task which stops tomcat server:
task stopTomcat(type:Exec) {
workingDir '../tomcat/bin'
//on windows:
commandLine 'cmd', '/c', 'stop.bat'
//on linux
commandLine './stop.sh'
//store the output instead of printing to the console:
standardOutput = new ByteArrayOutputStream()
//extension method stopTomcat.output() can be used to obtain the output:
ext.output = {
return standardOutput.toString()
}
}
It's also a good example because there are a few useful directives in it.
In your case it would be something like:
task testFile(type:Exec) {
workingDir '/home/user'
commandLine './test.sh'
}
More information can be found here.

How can the Git command be executed on Windows through Gradle?

So I have the following code snippet:
def getVersion = { ->
def stdout = new ByteArrayOutputStream()
exec {
commandLine 'git', 'describe', '--tags'
standardOutput = stdout
}
return stdout.toString().trim()
}
and whenever I call getVersion(), I get the following error:
* What went wrong:
A problem occurred evaluating root project 'ForgeWorkspace'.
> Process 'command 'git'' finished with non-zero exit value 128
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: 6.442 secs
On my MacBook Pro I've never encountered this issue, but do on Windows. Any help is greatly appreciated!
#RaGe is almost correct. Since you indeed need to use the Windows Command Prompt (cmd) to have the OS search the git executable in the system path, the entire git command should be passed as one argument that follows the /c switch (which means 'execute command').
So the following should work:
commandLine 'cmd', '/c', 'git describe --tags'
On windows, the first two arguments of commandLine should be cmd and /c
//on windows:
commandLine 'cmd', '/c', 'git'...
See here.

Gradle exec commandLine not working for me

I am trying to run an executable with arguments from gradle:
task deploy(dependsOn: jar) {
exec {
commandLine "javafxpackager -deploy -native -outdir ${deployDirName} -outfile ${jarBaseName} -srcfiles ./${project.buildDir}/${project.libsDirName}/${jarBaseName}-${project.version}.jar -appclass ${mainClass} -name ${jarBaseName} -title '${project.description}'"
}
}
Gradle complains that the process ended up with non-zero return code, but if I copy the command and run it within bash terminal, it works flawlessly.
So what am I doing wrong?
Regards,
There are two problems with this code: First, the exec call happens outside a task action (doLast { ... }). As a result, exec will get called for every single build invocation (even when typing gradle help), in the configuration phase of the build. Second, commandLine accepts a list of command line arguments, not a single string.
It's almost always better to use a task type than the corresponding method, so this becomes:
task deploy(type: Exec) {
dependsOn jar
commandLine "javafxpackager", "-deploy", "-native", ...
}
To find out how to configure a particular task (type), check the Gradle Build Language Reference.

Resources