How to execute gradle task - intellij-idea

I wanted to execute gradle task from my plugin code.
Any one can suggest me, how can I programmatically execute gradle task from code.
Thanks,
Sumeet.

You can do it as follows
task a {
doLast {
println 'test'
}
}
task b {
doLast {
a.execute()
}
}
So in plugin code it might be something similar to
project.tasks.<taskname>.execute()
But this might be changed in the future. You should rely on the chaining of the tasks rather then invoking them directly.

The answer provided by Martin Linha does not work anymore with recent versions of Gradle, for instance Gradle 7. The Task class does not have an execute method anymore. Instead, the activities have to be executed. In addition, you might want to execute the dependencies as well:
void executeTask(Task task) {
task.taskDependencies.getDependencies(task).each {
subTask -> executeTask(subTask)
}
task.actions.each { it.execute(task) }
}
Note that this is still a hack and not guaranteed to work.

Related

Calling PCEnhancerTask from Kotlin in Gradle

I need to call the OpenJPA PCEnhancerTask class from Kotlin instead of Groovy. The following code works just fine (based on a previous solution documented here):
def openJPAClosure = {
def entityFiles = sourceSets.main.output.classesDirs.asFileTree.matching {
include 'com/company/persist/*Entity.class'
}
println "Enhancing with OpenJPA:"
entityFiles.getFiles().each {
println it
}
ant.taskdef(
name : 'openjpac',
classpath : sourceSets.main.runtimeClasspath.asPath,
classname : 'org.apache.openjpa.ant.PCEnhancerTask'
)
ant.openjpac(
classpath: sourceSets.main.runtimeClasspath.asPath,
addDefaultConstructor: false,
enforcePropertyRestrictions: true) {
entityFiles.addToAntBuilder(ant, 'fileset', FileCollection.AntType.FileSet)
}
}
I was looking at the documentation on how to call Ant tasks from Gradle but I could not translate all the necessary steps using the GroovyBuilder. So instead I tough of calling the PCEnhancer directly:
fun openJPAEnrich() {
val entityFiles = sourceSets.main.get().output.classesDirs.asFileTree.matching {
include("com/company/persist/*Entity.class")
}
println("Enhancing with OpenJPA, the following files...")
entityFiles.getFiles().forEach() {
println(it)
}
org.apache.openjpa.ant.PCEnhancerTask.main(asList(entityFiles))
}
But it complains about not being able to find org.apache.openjpa in the classpath (but is it listed as a compilation dependency)
My questions are:
What is the correct way to translate the original Groovy construct to Kotlin using groovyBuilder
If is not possible, how you can correctly call PCEnhancer from Kotlin in Gradle?
So I ended making it work with a custom JavaExec Gradle task:
tasks.create<JavaExec>("openJPAEnrich") {
val entityFiles = sourceSets.main.get().output.classesDirs.asFileTree.matching {
include("com/company/persist/*Entity.class")
}
println("Enhancing with OpenJPA, the following files...")
entityFiles.files.forEach() {
println(it)
}
classpath = sourceSets.main.get().runtimeClasspath
main = "org.apache.openjpa.enhance.PCEnhancer"
args(listOf("-enforcePropertyRestrictions", "true", "-addDefaultConstructor", "false"))
entityFiles.forEach { classFile -> args?.add(classFile.toString())}
}
I was tempted to build my own custom Gradle task but for this felt overkill.
Thanks.
--Jose

How to add task dependencies in Gradle?

I'm trying to write a task named stage like this:
plugins {
base
}
val clean = "clean"
val build = "build"
tasks.register("stage") {
dependsOn(clean, build)
}
tasks[build].dependsOn(clean)
The problem is that when I run ./gradlew stage it doesn't run clean, nor build. This is a multiproject build and I have 3 subprojects with Kotlin code.
How do I get Gradle to run ./gradlew clean build whenever I type ./gradlew stage? This is clearly not a solution, and I don't see what I'm doing wrong.
I also tried this, but it didn't work either. It runs the tasks I want but at the end it runs clean and I end up with no build folder:
tasks.register("stage") {
subprojects.forEach { project ->
val clean = project.tasks.first { it.name.contains("clean") }
val build = project.tasks.first { it.name.contains("build") }
build.dependsOn(clean)
dependsOn(build)
}
}
I think one of the issues in your code is running the command:
build.dependsOn(clean)
Instead try:
tasks{
register("stage"){
dependsOn(clean, build)
}
}
Remember that tasks{} is a container and by scoping the code inside we have access to the other tasks as well.
You likely need to define the ordering using mustRunAfter
tasks.register("stage") {
subprojects.forEach { project ->
val clean = project.tasks.first { it.name.contains("clean") }
val build = project.tasks.first { it.name.contains("build") }
build.dependsOn(clean)
build.mustRunAfter(clean)
dependsOn(build)
}
}
From the docs of Task Dependencies and Task Ordering:
Dependencies to a task are controlled using Task.dependsOn(java.lang.Object[]) or Task.setDependsOn(java.lang.Iterable), and Task.mustRunAfter(java.lang.Object[]), Task.setMustRunAfter(java.lang.Iterable), Task.shouldRunAfter(java.lang.Object[]) and Task.setShouldRunAfter(java.lang.Iterable) are used to specify ordering between tasks.
This documentation in Gradle about ordering tasks can explain tasks ordering, and why you need a combination of dependsOn and mustRunAfter for your use case:
Note that “B.mustRunAfter(A)” or “B.shouldRunAfter(A)” does not imply any execution dependency between the tasks:
It is possible to execute tasks A and B independently. The ordering rule only has an effect when both tasks are scheduled for execution.
its much simpler
plugins {
base
}
allprojects {
task stage() {
dependsOn(clean, build)
}
}
so when you run stage - it should do clean and build

Adds an implementation dependency only to the "free" product flavor in Kotlin DSL

I am in process of migrating our Groovy based scripts to Kotlin. I have been able to get most of done except not sure how to add a dependency for a particular flavour.
This is how looks like in Kotlin DSL so far but not sure why the freeImplementation("bar:2.2.8")
productFlavors {
create("free") {
...
...
}
create("paid") {
...
...
}
}
dependencies {
implementation("foo:1.2.0")
// This is not working when migrated to Kotlin DSL
freeImplementation("bar:2.2.8")
//Below was the code in Groovy which was working fine earlier
//freeImplementation "bar:2.2.8"
}
Below is the solution for it.
val freeImplementation by configurations
dependencies {
freeImplementation("bar:2.2.8")
}
Alternatively, a string literal can be used to denote a dynamic configuration:
dependencies {
"freeImplementation"("bar:2.2.8")
}

Programmatically execute Gatling tests

I want to use something like Cucumber JVM to drive performance tests written for Gatling.
Ideally the Cucumber features would somehow build a scenario dynamically - probably reusing predefined chain objects similar to the method described in the "Advanced Tutorial", e.g.
val scn = scenario("Scenario Name").exec(Search.search("foo"), Browse.browse, Edit.edit("foo", "bar")
I've looked at how the Maven plugin executes the scripts, and I've also seen mention of using an App trait but I can't find any documentation for the later and it strikes me that somebody else will have wanted to do this before...
Can anybody point (a Gatling noob) in the direction of some documentation or example code of how to achieve this?
EDIT 20150515
So to explain a little more:
I have created a trait which is intended to build up a sequence of, I think, ChainBuilders that are triggered by Cucumber steps:
trait GatlingDsl extends ScalaDsl with EN {
private val gatlingActions = new ArrayBuffer[GatlingBehaviour]
def withGatling(action: GatlingBehaviour): Unit = {
gatlingActions += action
}
}
A GatlingBehaviour would look something like:
object Google {
class Home extends GatlingBehaviour {
def execute: ChainBuilder =
exec(http("Google Home")
.get("/")
)
}
class Search extends GatlingBehaviour {...}
class FindResult extends GatlingBehaviour {...}
}
And inside the StepDef class:
class GoogleStepDefinitions extends GatlingDsl {
Given( """^the Google search page is displayed$""") { () =>
println("Loading www.google.com")
withGatling(Home())
}
When( """^I search for the term "(.*)"$""") { (searchTerm: String) =>
println("Searching for '" + searchTerm + "'...")
withGatling(Search(searchTerm))
}
Then( """^"(.*)" appears in the search results$""") { (expectedResult: String) =>
println("Found " + expectedResult)
withGatling(FindResult(expectedResult))
}
}
The idea being that I can then execute the whole sequence of actions via something like:
val scn = Scenario(cucumberScenario).exec(gatlingActions)
setup(scn.inject(atOnceUsers(1)).protocols(httpConf))
and then check the reports or catch an exception if the test fails, e.g. response time too long.
It seems that no matter how I use the 'exec' method it tries to instantly execute it there and then, not waiting for the scenario.
Also I don't know if this is the best approach to take, we'd like to build some reusable blocks for our Gatling tests that can be constructed via Cucumber's Given/When/Then style. Is there a better or already existing approach?
Sadly, it's not currently feasible to have Gatling directly start a Simulation instance.
Not that's it's not technically feasible, but you're just the first person to try to do this.
Currently, Gatling is usually in charge of compiling and can only be passed the name of the class to load, not an instance itself.
You can maybe start by forking io.gatling.app.Gatling and io.gatling.core.runner.Runner, and then provide a PR to support this new behavior. The former is the main entry point, and the latter the one can instanciate and run the simulation.
I recently ran into a similar situation, and did not want to fork gatling. And while this solved my immediate problem, it only partially solves what you are trying to do, but hopefully someone else will find this useful.
There is an alternative. Gatling is written in Java and Scala so you can call Gatling.main directly and pass it the arguments you need to run the Gatling Simulation you want. The problem is, the main explicitly calls System.exit so you have to also use a custom security manager to prevent it from actually exiting.
You need to know two things:
the class (with the full package) of the Simulation you want to run
example: com.package.your.Simulation1
the path where the binaries are compiled.
The code to run a Simulation:
protected void fire(String gatlingGun, String binaries){
SecurityManager sm = System.getSecurityManager();
System.setSecurityManager(new GatlingSecurityManager());
String[] args = {"--simulation", gatlingGun,
"--results-folder", "gatling-results",
"--binaries-folder", binaries};
try {
io.gatling.app.Gatling.main(args);
}catch(SecurityException se){
LOG.debug("gatling test finished.");
}
System.setSecurityManager(sm);
}
The simple security manager i used:
public class GatlingSecurityManager extends SecurityManager {
#Override
public void checkExit(int status){
throw new SecurityException("Tried to exit.");
}
#Override
public void checkPermission(Permission perm) {
return;
}
}
The problem is then getting the information you want out of the simulation after it has been run.

Executing SQL files using Groovy in Gradle

I have a bunch of sql files which I want to execute in my gradle build. I came up with this.
def sqlDir = new File('src/main/resources/')
task testSql << {
sqlDir.eachDirRecurse() { dir ->
dir.eachFileMatch(~/.*\.sql$/) {
// sql.execute(it.text)
println it
}
}
}
I however, also want to exclude some files, and I can probably do that using if blocks and hardcoding filenames inside the code. Can someone give me a cleaner solution to exclude files?
As you pointed, there is a [fileTree] solution in Gradle
You can use it somehow like that. Please refer link to details.
def sqlDir = file 'src/main/resources/'
task testSql << {
fileTree(dir: sqlDir, include: "**.sql", exclude: ["somefilename.sql", "otherfilename.sql"]).each {
sql.execute(it.text)
}
}