Pass $ character to Gradle start scripts (Application plugin) - java

I have a Gradle build script that uses the Application plugin, and I want to pass as JVM argument a string that contains the $ character, but I can't because it always is converted to the \$ sequence of characters...
Here is my configuration:
application {
mainClass = 'example.Main'
application.applicationDefaultJvmArgs = ['-javaagent:$APP_HOME/lib/agent.jar']
}
But then in the start script I get:
DEFAULT_JVM_OPTS='"-javaagent:\$APP_HOME/lib/agent.jar"'
And because of that \ it doesn't work, I need the value to be -javaagent:$APP_HOME/lib/agent.jar. All ways I tried get the same result (using interpolation, passing the $ as \u0024, etc.).

I've found a workaround in this answer for a related question. The code in question is the following:
startScripts {
doLast {
unixScript.text = unixScript.text.replace('\\$APP_HOME', '\$APP_HOME')
//do something like this for Windows scripts if needed too
}
}

Related

How to execute bash script using karate and fail if script fails

I'm trying to execute bash script using karate. I'm able to execute the script from karate-config.js and also from .feature file. I'm also able to pass the arguments to the script.
The problem is, that if the script fails (exits with something else than 0) the test execution continues and finishes as succesfull.
I found out that when the script echo-es something then i can access it as a result of the script so I could possibly echo the exit value and do assertion on it (in some re-usable feature), but this seems like a workaround rather than a valid clean solution. Is there some clean way of accessing the exit code without echo-ing it? Am I missing on something?
script
#!/bin/bash
#possible solution
#echo 3
exit 3;
karate-config.js
var result = karate.exec('script.sh arg1')
feture file
def result = karate.exec('script.sh arg1')
Great timing. We very recently did some work for CLI testing which I am sure you can use effectively. Here is a thread on Twitter: https://twitter.com/maxandersen/status/1276431309276151814
And we have just released version 0.9.6.RC4 and new we have a new karate.fork() option that returns an instance of Command on which you can call exitCode
Here's an example:
* def proc = karate.fork('script.sh arg1')
* proc.waitSync()
* match proc.exitCode == 0
You can get more ideas here: https://github.com/intuit/karate/issues/1191#issuecomment-650087023
Note that the argument to karate.fork() can take multiple forms. If you are using karate.exec() (which will block until the process completes) the same arguments work.
string - full command line as seen above
string array - e.g. ['script.sh', 'arg1']
json where the keys can be
line - string (OR)
args - string array
env - optional environment properties (as JSON)
redirectErrorStream - boolean, true by default which means Sys.err appears in Sys.out
workingDir - working directory
useShell - default false, auto-prepend cmd /c or sh -c depending on OS
And since karate.fork() is async, you need to call waitSync() if needed as in the example above.
Do provide feedback and we can tweak further if needed.
EDIT: here's a very advanced example that shows how to listen to the process output / log, collect the log, and conditionally exit: fork-listener.feature
Another answer which can be a useful reference: Conditional match based on OS
And here's how to use cURL for advanced HTTP tests ! https://stackoverflow.com/a/73230200/143475
In case you need to do a lot of local file manipulation, you can use the karate.toJavaFile() utility so you can convert a relative path or a "prefixed" path to an absolute path.
* def file = karate.toJavaFile('classpath:some/file.txt')
* def path = file.getPath()

A literal string containing escape slashes on groovy

My groovy script calls other commands via vagrant. One of those commands is to echo some quotes on a file within docker.
The goal is, so that within the container, i want to have BB_GENERATE_MIRROR_TARBALLS = "1". Now to do this on a bash script, i would need something like this:
BB_GENERATE_MIRROR_TARBALLS = \"1\"
The issue manifests itself when i have to escape double quotations on the groovy as well.
If i call vagrant("echo BB_GENERATE_MIRROR_TARBALLS = \\\"1\\\" >> ${yoctoDir}/build/conf/local.conf" on my groovy file, the outcome on the local.conf will be BB_GENERATE_MIRROR_TARBALLS=1 (without quotes).
The correct way to do this would be to include an extra backslash on both sides (3 for the groovy, 1 for the bash script), however when i do that, groovy doesnt run and gives me syntax errors.
What would be the correct way to insert this literal string(BB_GENERATE_MIRROR_TARBALLS=\"1\") on the groovy?
In groovy you can do the following:
def my_var = /BB_GENERATE_MIRROR_TARBALLS = "1"/
echo my_var >> ${yoctoDir}/build/conf/local.conf

Why is java_executable_exec_path giving me a legacy "external" runfiles path

Suppose I've got a minimal Scala WORKSPACE file like this:
workspace(name = "scala_example")
git_repository(
name = "io_bazel_rules_scala",
commit = "e9e65ada59823c263352d10c30411f4739d5df25",
remote = "https://github.com/bazelbuild/rules_scala",
)
load("#io_bazel_rules_scala//scala:scala.bzl", "scala_repositories")
scala_repositories()
load("#io_bazel_rules_scala//scala:toolchains.bzl", "scala_register_toolchains")
scala_register_toolchains()
And then a BUILD:
load("#io_bazel_rules_scala//scala:scala.bzl", "scala_binary")
scala_binary(
name = "example-bin",
srcs = glob(["*.scala"]),
main_class = "Example",
)
And an Example.scala:
object Example { def main(args: Array[String]): Unit = println("running") }
I can run bazel run example-bin and everything works just fine. My problem is that this recent rules_scala PR changed the way the Java binary path is set to use the following:
ctx.attr._java_runtime[java_common.JavaRuntimeInfo].java_executable_exec_path
…instead of the previous ctx.executable._java.short_path.
After this change the Java binary path includes an external directory in the path, which seems to be a legacy thing (?). This means that after this change, if I run the following:
bazel run --nolegacy_external_runfiles example-bin
It no longer works:
INFO: Running command line: bazel-bin/example-bin
.../.cache/bazel/_bazel_travis/03e97e9dbbfe483081a6eca2764532e8/execroot/scala_example/bazel-out/k8-fastbuild/bin/example-bin.runfiles/scala_example/example-bin_wrapper.sh: line 4: .../.cache/bazel/_bazel_travis/03e97e9dbbfe483081a6eca2764532e8/execroot/scala_example/bazel-out/k8-fastbuild/bin/example-bin.runfiles/scala_example/external/local_jdk/bin/java: No such file or directory
ERROR: Non-zero return code '127' from command: Process exited with status 127
It also breaks some scripts I have that expect non-external paths.
Why is java_executable_exec_path giving me this external path? Is there some option I can give bazel to convince it not to do this?
Sorry for the slow reply -- it appears that this is because the Scala rules erroneously used java_executable_exec_path whereas they should have used java_executable_runfiles_path.
I sent a pull request to fix it, then I realized that you already did in https://github.com/bazelbuild/rules_scala/commit/4235ef58782ce2ec82981ea70b808397b64fe7df
Since the latter is now available at HEAD with Bazel, I'll remove the ugly if at least.

Jenkinsfile not passing parameter to Maven

When I launch a build with parameters, I have this 'choice parameter' named "modeDebug"; the choice can be "true" or "false" (I did not choose the boolean type because I'll add more options some day). I need to use this parameter in my Java code but, for some reason, it's not retrieved.
I have this step in my Jenkinsfile in order to run the tests with parameters:
sh 'mvn -gs "$MAVEN_SETTINGS" -Dta.test.suite="{\\"filter\\":\\"'+newTestList+'\\",\\"param\\":{\\"env.devEnv\\":\\"${environnement}\\",\\"env.browser\\":\\"${browser}\\",\\"env.modeDebug\\":\\"${modeDebug}\\"}}"
-Denv.devEnv="${environnement}"
-Denv.browser="${browser}"
-Denv.modeDebug="${modeDebug}"
-Dlog4j.configurationFile="${log4j2ConfigurationFile}"
-Dstatus.update.events.url="${notificationURL}"
-Dsquash.ta.external.id="${externalJobId}" -Djobname="${JOB_NAME}"
-Dhostname="${HOSTNAME}" -Dsquash.ta.conf.file="taLinkConf.properties"
-Dta.tmcallback.reportbaseurl="${JENKINS_URL}job"
-Dta.tmcallback.jobexecutionid="${BUILD_NUMBER}"
-Dta.tmcallback.reportname=Squash_TA_HTML_Report
-Dta.delete.json.file=true squash-ta:"${operation}"'
Then, in my code, I call some of these Maven parameters...
protected String getScreenshotIfFail = java.lang.System.getProperty("env.modeDebug");
protected String devEnv = java.lang.System.getProperty("env.devEnv");
protected String browser = java.lang.System.getProperty("env.browser");
String devEnv and browser get populated but not ggetScreenshotIfFail!
Notes: In my Jenkinsfile, echo "${modeDebug}" outputs "true" or "false". This part is working.
In my code when the tests are run via Jenkins, System.out.println(getScreenshotIfFail); outputs "null".
In my IDE, I run the following command with success (getScreenshotIfFail is correctly populated):
-Denv.modeDebug=true -Denv.devEnv=qualif -Denv.browser=chrome -Dlog4j.configurationFile=src/log4j2.xml -Dta.test.suite=squash/**.ta squash-ta:run
Any idea?
Thanks!
RTM - String interpolation.
sh 'mvn ...'
^
that single quote should be double quote.
And of course you'll have to change many other quotes in your string.

Gradle task - pass arguments to Java application

I have a Java application that runs with a custom gradle task and the application requires some arguments upon being invoked. These are:
programName ( string | -f filename | -d key | -h)
Options:
string Message to be used.
-d key Use default messages, key must be s[hort], m[edium] or l[ong].
-f filename Use specified file as input.
-h Help dialog.
Gradle task looks like:
task run (type: JavaExec){
description = "Secure algorythm testing"
main = 'main.Test'
classpath = sourceSets.main.runtimeClasspath
}
I've tried running gradle run -h and it does not work.
Gradle 4.9+
gradle run --args='arg1 arg2'
This assumes your build.gradle is configured with the Application plugin. Your build.gradle should look similar to this:
plugins {
// Implicitly applies Java plugin
id: 'application'
}
application {
// URI of your main class/application's entry point (required)
mainClassName = 'org.gradle.sample.Main'
}
Pre-Gradle 4.9
Include the following in your build.gradle:
run {
if (project.hasProperty("appArgs")) {
args Eval.me(appArgs)
}
}
Then to run: gradle run -PappArgs="['arg1', 'args2']"
Since Gradle 4.9, the command line arguments can be passed with --args. For example, if you want to launch the application with command line arguments foo --bar, you can use
gradle run --args='foo --bar'
See Also Gradle Application Plugin
How to upgrade Gradle wrapper
If you want to use the same set of arguments all the time, the following is all you need.
run {
args = ["--myarg1", "--myarg2"]
}
Sorry for answering so late.
I figured an answer alike to #xlm 's:
task run (type: JavaExec, dependsOn: classes){
if(project.hasProperty('myargs')){
args(myargs.split(','))
}
description = "Secure algorythm testing"
main = "main.Test"
classpath = sourceSets.main.runtimeClasspath
}
And invoke like:
gradle run -Pmyargs=-d,s
You can find the solution in Problems passing system properties and parameters when running Java class via Gradle . Both involve the use of the args property
Also you should read the difference between passing with -D or with -P that is explained in the Gradle documentation
Of course the answers above all do the job, but still i would like to use something like
gradle run path1 path2
well this can't be done, but what if we can:
gralde run --- path1 path2
If you think it is more elegant, then you can do it, the trick is to process the command line and modify it before gradle does, this can be done by using init scripts
The init script below:
Process the command line and remove --- and all other arguments following '---'
Add property 'appArgs' to gradle.ext
So in your run task (or JavaExec, Exec) you can:
if (project.gradle.hasProperty("appArgs")) {
List<String> appArgs = project.gradle.appArgs;
args appArgs
}
The init script is:
import org.gradle.api.invocation.Gradle
Gradle aGradle = gradle
StartParameter startParameter = aGradle.startParameter
List tasks = startParameter.getTaskRequests();
List<String> appArgs = new ArrayList<>()
tasks.forEach {
List<String> args = it.getArgs();
Iterator<String> argsI = args.iterator();
while (argsI.hasNext()) {
String arg = argsI.next();
// remove '---' and all that follow
if (arg == "---") {
argsI.remove();
while (argsI.hasNext()) {
arg = argsI.next();
// and add it to appArgs
appArgs.add(arg);
argsI.remove();
}
}
}
}
aGradle.ext.appArgs = appArgs
Limitations:
I was forced to use '---' and not '--'
You have to add some global init script
If you don't like global init script, you can specify it in command line
gradle -I init.gradle run --- f:/temp/x.xml
Or better add an alias to your shell:
gradleapp run --- f:/temp/x.xml
You need to pass them as args to the task using project properties, something like:
args = [project.property('h')]
added to your task definition (see the dsl docs)
Then you can run it as:
gradle -Ph run

Categories

Resources