What's the best way to create a gradle task, which runs a groovy script? I realize that gradle build files are groovy, so I would think it would be possible to do something like this:
task run << {
Script app = new GroovyShell().parse(new File("examples/foo.groovy"))
// or replace .parse() w/ a .evalulate()?
app.run()
}
I get all kinds of whacky errors when I try this if bar.groovy is using #Grab annotations or even doing simple imports. I want to create a gradle task to handle this, so that I can hopefully reuse the classpath definition.
Would it be better to move the examples directory into the src directory somewhere? What's a best practice?
Or you could do:
new GroovyShell().run(file('somePath'))
You could try using GroovyScriptEngine instead of the GroovyShell. I've used it previously with #Grab annotations. You will need all of groovy on the classpath, the groovy-all.jar will not be enough. I'm guessing Ivy isn't packaged in the groovy-all.jar. Something like this should to the trick:
This script presumes a groovy script at /tmp/HelloWorld.groovy
def pathToFolderOfScript = '/tmp'
def gse = new GroovyScriptEngine([pathToFolderOfScript] as String[])
gse.run('HelloWorld.groovy', new Binding())
http://wayback.archive.org/web/20131006153845/http://docs.codehaus.org/display/GRADLE/Cookbook#Cookbook-runningthingsfromGradle
ant.java(classname: 'com.my.classname', fork: true,
classpath: "${sourceSets.main.runtimeClasspath.asPath}")
I think you probably need to run the script as a new process... e.g.,
["groovy","examples/foo.groovy"].execute()
I would guess that the way Gradle is executed is not via invoking groovy, so the setup that makes #Grab work never happens. It could also be the the version of Groovy that Gradle uses doesn't support #Grab.
Related
I have a made my first groovy CLI app with picocli. Now, I want it to be available for use without any JVM installed on the client machine, maybe with the use of GraalVM.
This is for an opensource project:
https://github.com/kchaitanya863/db2csv
Another easy option is to dockerize your script (read this blog about how to do it https://groovy-lang.gitlab.io/101-scripts/docker/basico-en.html)
If you want to build a linux executable you need to change your project:
convert to a gradle project (maven is also an option but gradle has a lot of plugins)
change your script to a class with a tipical main (and move it to the standard directory src/main/groovy/mypackage)
add some tasks into you build.gradle similar to these https://gitlab.com/snippets/1797638
You will need to:
statically compile your groovy script
make the args variable available after static compilation with
final String[] args = getProperty("args") as String[]
specify a reflection configuration file for the classes dynamically loaded/invoked using reflection by Groovy (this may be useful)
specify a reflection configuration file for the classes loaded/invoked using reflection by picocli. The picocli-codegen module provides a picocli.codegen.aot.graalvm.ReflectionConfigGenerator tool to generate the configuration file.
If your script has any #Grape dependencies, you may need to turn off the Grape dependency manager with -Dgroovy.grape.enabled=false and add all dependencies to the classpath manually instead
Credit: I got most of these tips from this article by Szymon Stepniak
If you want to use Graal with Groovy, check out this article:
https://e.printstacktrace.blog/graalvm-and-groovy-how-to-start/
I am writing a set of groovy scripts to be used as part of a Jenkins Pipeline Library. Currently I am using plain old JUnit to test them but would like to switch to Spock. I simply run the tests from the command line by invoking the following groovy script.
import groovy.util.AllTestSuite
import junit.textui.TestRunner
System.setProperty(AllTestSuite.SYSPROP_TEST_DIR, "./tests")
System.setProperty(AllTestSuite.SYSPROP_TEST_PATTERN, "**/*Test.groovy")
TestRunner.run(AllTestSuite.suite())
I am trying to figure what the equivalent script would be to run Spock specifications. My first attempt was to switch the SYSPROP_TEST_PATTERN to "**/*Spec.groovy. I have one ...Spec.groovy file written and sitting under ./tests that looks like this:
#Grab(group='org.spockframework', module='spock-core', version='1.0-groovy-2.3')
import spock.lang.*
class UtilsSpec extends Specification {
def "Just testing"() {
expect:
1 + 1 == 2
}
}
When I invoke my groovy script though I get:
java.lang.RuntimeException: Don't know how to treat
/SourcCode/jenkins/pipeline-utils/tests/JustTestingSpec.groovy as a
JUnit test
That makes sense. I need to be using Sputnik but I've looked at the Spock and Sputnik source, and the Spock example project but these all assume you are using maven or gradle. I can't figured out the right way to invoke Sputnik directly. Any ideas?
Even though what you ask is possible and BalRog has already suggested a solution, in the long run it is better if you just use Gradle or Maven to run your tests from command line.
All Jenkins tutorials you will encounter will talk about Maven and/or Gradle and thus it would make much more sense to use a build system than custom scripts.
I upgraded to groovy 2 release and now my build is broken.
It fails when importing classes: groovy.json.JsonSlurper and XmlSlurper.
I have checked http://groovy.codehaus.org/gapi/ and cannot find these classes anymore. Do they still exist in groovy 2? Or have they moved somewhere?
The groovy.jar distributed with groovy 2 has been split out to contain just the bare minimum, with all the additional modules (XML, SQL, JSON, etc.) in separate jars. However, in the embeddable directory, you'll find a jar file groovy-all-2.0.0.jar which contains groovy and all the modules together, like previous versions. The easiest way to migrate is to use this jar file.
If you're using Maven Central, you can use an artifactId of groovy-all to get everything, or groovy (plus modules) to have finer grained control over your dependencies. Here's a list of the modules available on Maven Central: http://search.maven.org/#search|ga|1|g%3A%22org.codehaus.groovy%22
Never mind. Need to include groovy-xml and groovy-json jars.
These were split from groovy's jar. See: http://www.infoq.com/articles/new-groovy-20
When I import, groovy-json-2.4.3 and groovy-xml-2.4.3 , JsonSlurper is recognized.
Also refer for new code refactor after 1.8.0 version: Parsing array of JSON arrays in Groovy
I faced a similar issue in Gradle build of a Java project (Gradle uses Groovy).
Gradle stopped including the local Groovy libs in classpath automatically. So, I had to include the following lines (marked with +) in my build.gradle file:
buildscript {
ext {
springbootVersion = '2.x.x'
awsVersion = '1.x.x'
...
}
+ dependencies {
+ classpath localGroovy()
+ }
repositories ...
}
Instead of using "groovy.json.jsonSlurper", use "net.sf.json.groovy.JsonSlurper".
Your script must be running.
I'm writing a Groovy script which uses third party java code that I can't change.
This code uses (badly, I think) ClassLoader.getSystemClassLoader().getResourceAsStream("/hard/file/path/in/jar/file")
and expect to read a file.
Everything goes well from Java when using java -cp "/path/to/jar/file" ...
However, the third-party code is now to be integrated with a bunch of Groovy code we've already written, so we wanted to run it from groovy.
So we wrote a Groovy script, let it call test.groovy, and ran it as groovy -cp "/path/to/jar/file" test.groovy.
The problem is that code can't access the file resource, as it seems Groovy doesn't load its jars in the System ClassLoader directly.
For proof, with Thread.currentThread().getContextClassLoader().getResourceAsStream("/hard/file/path/in/jar/file") within the Groovy Script, I can read the file, but with ClassLoader.getSystemClassLoader().getResourceAsStream("/hard/file/path/in/jar/file"), I can't.
So, does anyone know how to load the class in System ClassLoader from a Groovy Script without beginning to try some dirty hacks (like metaclassing getSystemClassloader to return the context classloader)?
You could try adding the jar to the system classloader as well when your script runs, like so:
ClassLoader.systemClassLoader.addURL new File( '/path/to/jar/file' ).toURI().toURL()
PS: I assume you mean ClassLoader.getSystemClassLoader() in your question, rather than System.getSystemClassLoader()
You can try to put your jar into %GROOVY_HOME%\lib folder or make a wrapper around your groovy command and modify %CLASSPATH% variable before you start your Groovy process.
I have
#RunWith(Suite.class)
#Suite.SuiteClasses( [
First.class,Second.class
])
public class MySuite{
}
But eclipse doesn't give me a "Run As Junit4 Test". All the individual test classes work fine with GUnit, the groovy unit test runner built into eclipse.
Any thoughts?
The only way I found to do this was to create a java class with a #Suite.SuiteClasses annotation as usual. You can put in the .class names of the Groovy classes you have for tests and it works well.
Kind of lame if you don't already have some java code to do it this way but I had a mix of Java and Groovy so it wasn't as big a deal.
The other option is to not use Suites at all and to use name patterns to find and run tests. Both ant and maven support this sort of pattern matching. I find it much easier than making sure I keep the suites up to date and Eclipse can just run all tests in a package if I want to do that.
Thanks for the help.
#Suite.SuiteClasses accepts Class[] as its parameter.
You may try:
#RunWith(Suite.class)
#Suite.SuiteClasses([First.class, Second.class] as Class[])
public class MySuite {
}