How do I create my own configuration block with a Gradle script plugin? - gradle

Our company has a Gradle script plugin with a number of tasks in it. For instance, it includes the Jacoco afterEvaluate block from this answer:
def pathsToExclude = ["**/*Example*"]
jacocoTestReport {
afterEvaluate {
classDirectories = files(classDirectories.files.collect {
fileTree(dir: it, exclude: pathsToExclude)
})
}
}
We would like to take that pathsToExclude variable and define that in our build.gradle file and have the rest of the logic in a script plugin (let's call it company-script-plugin.gradle. For instance:
apply from: http://example.com/company-script-plugin.gradle
companyConfiguration {
pathsToExclude = ["**/*Example*"]
}
Our initial thought was to add a task in the build script so that we could get a companyConfiguration
task companyConfiguration {
ext.pathsToExclude = []
}
However, we think that this is a hacky workaround because running the task doesn't do anything. What is the proper way to create my own configuration block?
We'd like it to be as simple as possible, and to be a script plugin (rather than binary plugin) if possible.

Here you've an example how it can be done:
apply plugin: CompanyPlugin
companyConfiguration {
pathsToExclude = ['a', 'b', 'c']
}
class CompanyPlugin implements Plugin<Project> {
void apply(Project p) {
println "Plugin ${getClass().simpleName} applied"
p.extensions.create('companyConfiguration', CompanyConfigurationExtension, p)
}
}
class CompanyConfigurationExtension {
List<String> pathsToExclude
CompanyConfigurationExtension(Project p) {
}
}
task printCompanyConfiguration {
doLast {
println "Path to exclide $companyConfiguration.pathsToExclude"
}
}
Also, please have a look at the docs.

Related

Methods for a gradle file accesses another gradle file

I have two gradle files:
first file:
def sendMessage(String appName,String versionCode){
println("${appName}---${versionCode}")
}
second file:
afterEvaluate {
android.applicationVariants.each { variant ->
String variantName = variant.name.capitalize()
def task = tasks.create("apkUploadPGY${variantName}")
task.dependsOn("resguard${variantName}")
task.doLast {
//in this how can i use sendMessage function
}
}
}
I want to use the method defined in the first file in the second file. How do I do this?
You can do it in the following way:
build.gradle:
apply from: 'first.gradle'
task whatever {
doLast {
sendMessage("lol", "v1")
}
}
first.gradle:
ext.sendMessage = { String appName, String versionCode ->
println("${appName}--${versionCode}")
}
You also need to change sendMessage declaration. It should be defined as a groovy closure and stored within ext - this is how "methods" are used in gradle.

refer to Gradle task which is defined later in build

Our build has some generic logic to create tasks from configuration data. There are also several Gradle files on whose execution order I do not want to depend.
Now I need to add a task dependency to a task without knowing if that task will be defined before my part of the build script runs (at configuration time) or after my part.
[Edit: as #canillas writes I can say myTask.dependsOn "otherTask" and "lazily" depend on yet undefined "otherTask", but I need it the other way around.]
Since I can't write tasks["otherTask"].dependsOn myNewTask before "otherTask" is defined, I made the following helper function:
void safelyDoWithTask(String taskName, Closure func) {
def task = tasks.findByName(taskName)
if (task != null) {
func(task)
} else {
project.tasks.whenTaskAdded { task_ ->
if (taskName.equals(task_.getName())) {
func(task_)
}
}
}
}
safelyDoWithTask('otherTask', { it.dependsOn myNewTask })
Now I wonder if there is more canonical way to achieve this?
Consider the following:
// section 1
def dynamicDependencies = [:]
dynamicDependencies['otherTask'] = 'myNewTask'
// section 2
afterEvaluate { project ->
// taskA dependsOn taskB
dynamicDependencies.each { taskA, taskB ->
def task = project.tasks.findByName(taskA)
if (task) { task.dependsOn "${taskB}" }
}
}
// section 3
task myNewTask() {
doLast {
println 'myNewTask !'
}
}
task otherTask() {
doLast {
println 'otherTask !'
}
}
The gist is:
section 1 defines our dependency info in a custom map
section 2 uses the afterEvaluate hook to process the map
because the above is decoupled from the task definitions, we can simply put them in section 3 (or wherever)

Can I create gradle task in plugin with dependsOn parameter?

I'm creating a gradle plugin as below
class MyPlugin implements Plugin<Project> {
void apply(Project project) {
project.extensions.create('testCoverageVerificationTask', TestCoverageVerificationPluginExtension)
project.tasks.create('testCoverageVerification', TestCoverageVerificationTask)
}
}
And to use it, I need to add these to my build.gradle
apply plugin: my.package.MyPlugin
testCoverageVerificationTask {
myreport = "testing report"
}
testCoverageVerification.dependsOn "myDependentTask"
However, I'm thinking it would be better to have the dependsOn as another parameter within the testCoverageVerificationTask so that it doesn't need to be defined separately. Is that feasible?
note: normal Task Definition could do this
task myTask(dependsOn: 'compile') {
doLast {
println 'I am not affected'
}
}
But I can't do
testCoverageVerificationTask(dependsOn: "myDependentTask") {
myreport = "testing report"
}
Use:
Task task = project.tasks.create('testCoverageVerification', TestCoverageVerificationTask)
task.dependsOn("compile")

Communication between gradle methods and tasks

I can't seem to get my collection from the method to a state where generateWadleTasks can iterate over it. At least not in a way such that I can access it. I've tried properties, parameters and return values. What's wrong with this picture? I seem to have some misconceptions about how information is passed around either in Groovy or in Gradle... or perhaps both. An explanation of the scopes involved might help. This is a subproject.
buildscript{
...
}
ext.collectionOfObjects = []
class WadleProfile {
def File wadleFile;
def wadlArgs;
}
ext.factoryMethod = {
//supposed to create and add WadleProfiles to collectionOfWadleProfiles
}
compileJava {
doFirst { factoryMethod() }
}
task generateWadlTasks {
println "Executing generateWadlTasks"
project.ext.collectionOfObjects.each { wadlProfile ->
task("wadl2java" + wadlProfile.id, type: JavaExec, dependsOn: 'classes') {
main = project.wadlBaseMain
...
}
}
}

Gradle test task is not run after specifying a group

I'm setting up some tests. I have the following entries in my build.gradle file:
integTest {
useTestNG() {
}
}
integTest2 (type: Test){
useTestNG() {
include 'Group2'
}
}
And in my test I have the following annotation:
#Test (groups={"Group2"})
public void testMethod() {
// Test code here
}
When I run the second task (integTest2) with gradle it only builds my directory and doesn't actually pick up any tests to run (integTest works fine and runs all the tests but I want to be able to run separate suites individually too).
Is there something obvious I have missed?
Figured out the answer. I was using our company's internal version of gradle which only recognized "integTest" as the main task. So as a workaround I had to do something like this:
def allTestGroups = ['all', 'Group1', 'Group2']
def testGroup = project.hasProperty("testGroup") ? project.testGroup : 'all'
integTest {
useTestNG() {
includeGroups "${testGroup}"
excludeGroups allTestGroups.findAll { it != "${testGroup}" }.collect { "'${it}'" }.join(',')
}
}
Just try to change include 'Group2' to includeGroups 'Group2', like this:
integTest2 (type: Test) {
useTestNG {
includeGroups 'Group2'
}
}

Resources