Overview
The tool offers the ability to run arbitrary groovy scripts on the sources prior to running the build. This allows GME to be extensible by the user and to carry out non-generic modifications.
Configuration
If the property -DgroovyScripts=<value>,....
is set, it will load the remote Groovy script file.
The argument should a comma separated list of HTTP / HTTPS URLs.
Groovy Scripts
Each groovy script will be run on the execution root (i.e. where Gradle is invoked).
Each script must use the following annotations:
import org.commonjava.maven.ext.core.groovy.GMEBaseScript
import org.commonjava.maven.ext.core.groovy.InvocationPoint
import org.commonjava.maven.ext.core.groovy.InvocationStage
import org.jboss.gm.common.groovy.BaseScript
@InvocationPoint(invocationPoint = InvocationStage.FIRST)
@GMEBaseScript BaseScript gmeScript
NOTE : Prior to GME 1.4, the annotations used the simpler BaseScript annotation e.g. @BaseScript GMEBaseScript gmeScript
|
Invocation Stages
In the example script, we saw the use of the @InvocationPoint
annotation which controls when the script is run. It
takes a single argument, invocationPoint
, with the type InvocationStage
. The possible values for InvocationStage
are PREPARSE
, FIRST
, LAST
, and ALL
. These values are relative to when the manipulations to the build files are
made. The table below provides a description of the invocation stages available for running a script.
Stage | Description | Since |
---|---|---|
PREPARSE |
Alias for FIRST . |
2.10 |
FIRST |
Runs the script before any other manipulators. It is safe to modify build files on disk during this stage. | 1.5 |
LAST |
Runs the script after any other manipulators. | 1.5 |
BOTH |
Runs the script during stages FIRST and LAST . Note that as of version 2.10, BOTH has been replaced by ALL . |
[1.5, 2.9] |
ALL |
Runs the script during all possible stages: FIRST , and LAST . The getInvocationStage() API can be used to determine in which stage the script is currently running. |
2.10 |
API
The following API is made available:
Method | Description | Since | Valid in Stage |
---|---|---|---|
Project getProject() | Return the root Project. | 1.0 | LAST |
ManipulationModel getModel() | Return the current ManipulationModel. | 1.0 | LAST |
Properties getUserProperties() | Get the user properties. | 1.4 | ALL |
File getBaseDir() | Get the working directory (the execution root). | 1.4 | ALL |
InvocationStage getInvocationStage() | Return the current stage of the groovy manipulation. | 1.4 | ALL |
Logger getLogger() | Get the Logger. | 2.1 | ALL |
Translator getRESTAPI() | Get the REST Version Translator. | 2.1 | ALL |
When running as FIRST
, Gradle has not parsed and created the Project which means the getModel
/getProject
calls are not available. However, it is possible to amend the Gradle scripts directly on disk which will then be read as part of the following alignment process.
The API can then be invoked by e.g.
gmeScript.getProject()
A typical groovy script that alters a JSON file on disk might be:
import org.commonjava.maven.ext.core.groovy.GMEBaseScript
import org.commonjava.maven.ext.core.groovy.InvocationPoint
import org.commonjava.maven.ext.core.groovy.InvocationStage
import org.jboss.gm.common.groovy.BaseScript
import org.apache.commons.lang.StringUtils
import org.jboss.gm.common.model.ManipulationModel
import org.commonjava.maven.atlas.ident.ref.SimpleProjectRef
@InvocationPoint(invocationPoint = InvocationStage.LAST)
@GMEBaseScript BaseScript gmeScript
println "Running Groovy script on " + gmeScript.getProject()
println "\tgroovy found new version is " + gmeScript.getModel().getVersion()
String newVersion = gmeScript.getModel().getVersion()
File information = new File(gmeScript.getProject().getRootDir(), "gradle/base-information.gradle")
def newContent = information.text.replaceAll( "(new HibernateVersion[(]\\s')(.*)(',\\sproject\\s[)])", "\$1$newVersion\$3")
information.text = newContent
def newJpaVersion = gmeScript.getModel().getAllAlignedDependencies().values().find {it.asProjectRef() == new SimpleProjectRef("javax.persistence", "javax.persistence-api")}.getVersionString()
newContent = information.text.replaceAll( "(new JpaVersion[(]')(.*)('[)])", "\$1$newJpaVersion\$3")
information.text = newContent
newContent = information.text.replaceAll( "version \\+ \"\\.0\"", "version")
information.text = newContent
It is possible to use the Translator
API to call onto the Dependency Anlalyser to make adjustments beyond what GME already provides e.g.
import org.commonjava.maven.atlas.ident.ref.ProjectVersionRef
import org.commonjava.maven.atlas.ident.ref.SimpleProjectRef
import org.commonjava.maven.atlas.ident.ref.SimpleProjectVersionRef
import org.commonjava.maven.ext.io.rest.Translator
...
Translator translator = gmeScript.getRESTAPI();
ProjectVersionRef pvr = SimpleProjectVersionRef.parse("org.hibernate:hibernate-core:5.3.7.Final")
Map<ProjectVersionRef, String> result = translator.translateVersions(Collections.singletonList(pvr))
gmeScript.getLogger().warn("Alignment result is {}", result)
File target = gmeScript.getProject().getBuildFile()
newContent = target.text.replaceFirst("classpath \"org.hibernate:hibernate-core:5.3.7.Final", "classpath \"org.hibernate:hibernate-core:" + result.get(pvr))
target.text = newContent
Grab Annotations
NOTE : Supported from GME 3.6 |
It is possible to use Grab annotations (e.g. @Grab('org.zeroturnaround:zt-exec:1.10')
) to utilise other API beyond what is already available via GME and Gradle. Note this is only supported in FIRST
phase.
Developing Groovy Scripts
To make it easier to develop scripts for both GME (this project) and PME an example project has been set up. The manipulator-groovy-examples provides a framework to develop and test such scripts.
Note: To debug Groovy scripts, while it is possible to use a debugger on the CLI for those scripts with invocation point FIRST
, for those scripts with LAST
it is not possible to run the CLI and debug on the Groovy script. Instead, run Gradle directly and invoke the plugin like
gradle
--no-daemon
--info
--stacktrace
--init-script=<....analyzer-init.gradle>
...
-DgroovyScripts=file://...../script.groovy
-Dorg.gradle.debug=true
There are two crucial aspects - you need to activate Groovy debugging via org.gradle.debug=true
and the source must be added to your IDE so it can see it.