How can I call an sbt task from Gradle? - gradle

How do I call a task on an sbt project from a Gradle build? I would like to call an existing sbt task, rather than port and duplicate the task's code into my Gradle build.
Ideally, I would like to be able to do this without needing to have sbt installed on the machine I'm running from.
As a simple yet concrete example, assume I have the following project structure:
parent_directory
gradle_project
build.gradle
[...]
sbt_project
build.sbt
[...]
and the following build.sbt file:
val helloTask = TaskKey[Unit]("hello", "Print hello")
helloTask := println("Hello world!")
I would like to call the "hello" sbt task defined in build.sbt from a "helloSbt" Gradle task defined in build.gradle.

The sbt-extras project provides a stand-alone script called sbt which can be directly used to run sbt without having it on the machine first. This can be called via an "Exec" task in the Gradle project, specifying the sbt task to run as a program argument.
First, copy the sbt file from sbt-extras/sbt into the local project. Assuming the sbt script has been copied into project as gradle_project/sbt-extras/sbt, the following Gradle task will execute the "hello" task in build.sbt:
task helloSbt(type: Exec) {
workingDir new File(project.projectDir.parentFile, 'sbt_project')
executable new File(project.projectDir, 'sbt-extras/sbt')
args 'hello'
}

Related

Run go command as a gradle task

I am using gradle as the build tool for a terraform project. I do have unit tests written in go for the project under the ..test/... folder . The way I am running test locally is just on the commandline go test ..test/..' which will run all tests under the test folder. I want to integrate this in the build , so that every build will run this command 'go test ..test/..', How do I achieve this in gradle. Can a custom task be utilized to run a go command?
I am trying to do something like the following
task testExec(type: Exec) {
workingDir "${buildDir}/test"
commandLine 'go','test'
} doLast {
println "Test Executed!"
}
But I get the error
> A problem occurred starting process 'command 'go''
For what its worth , I tried other commands and get the same erorr for ex
task testExec(type: Exec) {
workingDir "${buildDir}/test"
commandLine 'echo','${}buildDir'
} doLast {
println "Test Executed!"
}
gives similar error
> A problem occurred starting process 'command 'echo''
You can use the gradle plugin. First you can follow the starting guide and add the plugin:
plugins {
id 'com.github.blindpirate.gogradle' version '0.11.4'
}
golang {
packagePath = 'github.com/your/package' // go import path of project to be built, NOT local file system path!
}
Then you can run the following command to execute all go files that follow the file name convention <name>_test.go:
gradlew goTest
Otherwise you can also create a complete custom task or a custom task with the plugin.
EDIT:
I found the cause of your error. The variable buildDir refers to the build folder in your project: <project_folder>/build. The problem now is that the folder test does not exists and the exception is thrown. Instead, you can use the variable projectDir.

Gradle task is broken - cannot execute

import org.apache.tools.ant.filters.ReplaceTokens
task genScript(type:Copy){
copy{
from "../../scripts/script.txt"
into projectDir
filter ReplaceTokens, tokens: [baseName: jar.baseName, version: jar.version, prefix: 'x']
}
}
jar.doLast{
tasks.genScript.execute()
}
genScript executes fine if I just click on it and run. But when I do ..\gradlew clean jar, it gives me the following error:
Could not find method execute() for arguments [] on task ':myModule:genScript' of type org.gradle.api.tasks.Copy.
How to fix it?
I am using Gradle 6.0.1.
You can't programatically execute tasks from other tasks in newer versions of Gradle. Instead, you are supposed to declare task dependencies and Gradle will ensure they get executed in the correct order.
The quick fix is just to make jar depend on your task like this:
jar.dependsOn('genScript')
Alternatively, you could move your logic into the doLast block in the jar task.

How to use Gretty integrationTestTask with a war file?

Is it possible to use gretty integrationTestTask with a project that uses a war folder?
It seems from the documentation appBeforeIntegrationTest does not have access to the war. Is there another way to run test cases so that it uses the war folder?
Ideally, I want jettyStart -> test -> jettyStop to run. Although when I run it straight jettyStart hangs indefinitely, until jettyStop is run. Is there a way to run jettyStart in Gradle in the background or something?
Regardless what file structure your application has, the integrationTestTask is supposed to be configured with the name of an exsiting gradle task to execute when gradle integrationTest is run:
gretty {
// ...
integrationTestTask = 'integrationTest' // name of existing gradle task
// ...
}
What you want to archive is this:
gretty {
integrationTestTask = 'test'
}
Gretty's workflow when calling integrationTest is as follows:

How to run gradle script from gradle

How can I run another gradle script from gradle. I have multiple gradle scripts to run tests under <root_project>/test directory. The <root_project>/build.gradle is invoked with the name of the test gradle file to be run. For example
gradle run_test -PtestFile=foobar
This should run <root_project>/test/foobar.gradle (default tasks of it)
What I'm currently doing is invoking project.exec in the run_test task. This works but now I need to pass the project properties from the gradle process running run_test to the one which runs foobar.gradle
How can I do this ? Is there a more gradle-integrated way to run a gradle script from another, passing all the required info to the child gradle script ?
I do something similar where a "construct" task in one gradle hands off to a "perform" task in another gradle file in a dir it has created (called the artefact), and it passes through all the project properties through too.
Here's the relevant code for the handoff:
def gradleTask = "yourTaskToEventuallyRun"
def artefactBuild = project.tasks.create([name: "artefactBuild_$gradleTask", type: GradleBuild])
artefactBuild.buildFile = project.file("${artefactDir}/build.gradle")
artefactBuild.tasks = [gradleTask]
// inject all parameters passed to this build through to artefact build
def artefactProjectProperties = artefactBuild.startParameter.projectProperties
def currentProjectProperties = project.gradle.startParameter.projectProperties
artefactProjectProperties << currentProjectProperties
// you can add more here
// artefactProjectProperties << [someKey: someValue]
artefactBuild.execute()
If you want to specify another gradle script, you can use:
gradle --build-file anotherBuild.gradle taskName
or
gradle -b anotherBuild.gradle taskName

Gradle multi project, scope task

I have a multi project in the following way:
rootProject
Subproject1
Subproject2
task whatever << {
println "WHATEVER"
}
I want to be able to configure task 'whatever' once and execute it from any scope (root or subproject) and be executed only once!
This means:
If I run /gradle whatever, I should get: "WHATEVER"
If I run /subproject1/gradle whatever, I should get: "WHATEVER"
In summary, I don't what to execute the same task several tasks according to the number of projects.
I haven't been able to get such a simple result. Please let me know if you can offer any help! Thanks!
gradle whatever searches for whatever in the current subproject and below. Instead, use gradle :whatever and declare the task in the root project.

Resources