Too many tasks in build.gradle


(John Soman) #1

Hi, I have around 25 tasks for various devops things as part of my large multiproject build.

The structure of the project looks like this

RootProject
  -buildSrc
  -DirectoryA
     -SubProjectA1
     -SubProjectA2
     -SubProjectA3
  -DirectoryB
     -SubProjectB1
     -SubProjectB2
  -DirectoryC
     -SubProjectC1
     -SubProjectC2

etc…

Directories are there just to conveniently separate projects. RootProject and all SubProject have build.gradle files.

In the RootProject build.gradle file there are around 25 tasks. These tasks are configured on both root project and subprojects.

They make build.gradle rather long and complicated. So I thought of moving them into separate Tasks.gradle file located under buildSrc directory. And then pulling them in with “apply from”

Is this a good practice or is there a better way?

If I pull them in, there is another issue. Some tasks are configured for SubProjects, and other are configured for RootProject. So I can’t really just put them into single Tasks.gradle file.

Should I then put them into something like RootProjectTasks.gradle and SubProjectsTasks.gradle?

It all feels a little wrong…Would appreciate your feedback.

Thanks!


(Stefan Oehme) #2

I wouldn’t do a single “tasks.gradle”, as that is not very descriptive. Instead, I’d split out multiple scripts for different aspects. This should also address your other question regarding subprojects vs. root project.


(uklance) #3

This is a question of coding style so there’s no correct answer really. You could use plugins or script files. If it were me I wouldn’t split based on root and subprojects, I’d split based the functional area. Keep in mind you can do things like

subprojects {
   xxx
} 

(John Soman) #4

Thanks guys! Appreciate your feedback. And yes, I should probably separate tasks based on features and group them together.

Just a suggestion - would be great if apply from would let me selectively choose the tasks from the file that I want to inject. Something like

apply from 'buildSrc/src/main/gradle/some_tasks.gradle'.'taskX'

The above would only inject taskX from the file.

That would let me selectively import tasks that I need, for example in subprojects that Lance mentioned above. And would allow for some nice separation…

Thanks for your help again! Regards


(uklance) #5

I’ll have to disagree on that one, perhaps you want to create a plugin and configure an extension object. Eg

apply plugin: 'myplugin' 

myPlugin {
   fooEnabled = true
   barEnabled = false
   bazEnabled = false
} 

(John Soman) #6

Plugin sounds like an overkill for my simple tasks. Putting them in separate files is fine. i will have

tasks/release.gradle
tasks/deploy.gradle

The problem is most of the time I want all tasks from release.gradle avaialble in all subprojects

subproject {
   apply from: 'tasks/release.gradle'
   (...) 
}

But there may be task there that I may want to apply to root project too. In which case I could just do

project { 
   apply from: 'tasks/release.gradle'.'doXonRoot'
}

Currently I have to put doXonRoot in root/build.gradle to achieve the above. Being able to selectively pull tasks from files would let me keep them separated even though they don’t seem like a fit for separate plugin.


(uklance) #7

Build scripts can alter the gradle model in many different ways not limited to the addition of tasks. To provide a mechanism to apply a script but exclude some of the task creation logic feels wrong and I doubt the gradle team would consider it.

This really feels like a plugin/extension object use case to me. Or perhaps split your scripts further so that the offending tasks are in a separate file which is included under some circumstances and not in others


(Stefan Oehme) #8

Inside of release.gradle you could just have a subprojects {} block that does the subproject-specific stuff. Then you only apply that script to the root project.

Still, I agree with @Lance that separating these two concerns would be cleaner.


(uklance) #9

Another option is to add some logic to the script to detect if it’s the root.

Eg

def isRoot = (rootProject == project) 
if (isRoot) {
   task foo {...} 
} else {
   task bar {...} 
} 

(John Soman) #10

Thank you guys, it was very useful feedback.


(Matt Myers) #11

I know this is old, but I’m new to Gradle and trying to learn by reading posts related to what I want to do. I wanted to do the same thing as @johny123, apply from ‘somepath/build.gradle’ but only apply certain tasks. Why does it feel wrong to you? When you run a gradle script from the command line you can specify which tasks to run - seems very similar to me.