SlideShare a Scribd company logo
Improving your Gradle
builds
Peter Ledbrook
e: peter@cacoethes.co.uk
w: http://www.cacoethes.co.uk
t: @pledbrook
“Safety” in build tools
"Straight Razor" by Horst.Burkhardt - Own work.
Licensed under CC BY-SA 3.0 via Wikimedia Commons
Gradle is often treated like a cut-throat razor: unsafe
Code == spaghetti builds (allegedly)
Some people think it’s better to limit build authors to configuration only
Is this a good comparison though?
A better analogy
by Noel C. Hankamer - Creative Commons 2.0
Not all jobs are the same for a workman
Need the right tools for the job
Some tools are dangerous - so you learn to use them
Power drills, heavy duty knives, etc.
Gradle
Yes, you can create spaghetti builds, but…
“A bad workman blames
his tools”
So how do you create
maintainable builds?
First, understand the Gradle
model
Gradle is an API
Project
Task
Repository Dependency
Configuration Source set (Java)
This is just part of the Gradle model, which allows you to model your own build processes.
Show Gradle DSL and API references if possible: http://www.gradle.org/doc/latest/…
A basic Java build
apply	 plugin:	 "java"

version	 =	 "1.0"

repositories	 {	 jcenter()	 }

dependencies	 {

	 	 	 	 compile	 "asm:asm-all:3.3.1",

	 	 	 	 	 	 	 	 	 	 	 	 "commons-io:commons-io:1.4"

}

compileJava.options.incremental	 =	 true
An instance of Task
A Repository
Everything from Project
• project.tasks
• project.configurations
• project.repositories
• project.dependencies
• project.sourceSets (added by Java
plugin)
All the model elements are available from the project
The project itself can be accessed via the `project` property
The three phases
Initialisation
Configuration
Execution
Only relevant to multi-
project builds
Configures tasks and builds
the task graph
Executes the necessary tasks
based on the task graph
Beyond the model that defines the build, this is what happens when you actually run that build
At execution
Y
X
Z
=>
Z
X Y
W
V
Linear execution orderTask graph
W
V
During configuration Gradle builds a Directed Acyclic Graph (DAG) of tasks
Before execution, the graph is turned into an execution order
There is no distinction between targets and tasks like in Apache Ant
Applying that knowledge
Beware the config phase
Beware the config phase
• Configuration always happens
- even just running grade	 tasks!
- this will change soon(ish)
• Avoid expensive work
Profile your build!
gradle	 --profile	 <taskName>
This generates a report with timings for the different phases of each project in the build
Improving your Gradle builds
Example
apply	 plugin:	 "java"

...

jar	 {

	 	 	 version	 =	 new	 URL("http://buildsvr/version").text

}
Evaluated every build!
(This will change soon in Gradle)
Potentially unreliable network call *every* time the build runs
No matter what tasks are executed
Gradle will perform configuration on-demand in the not too distant future, reducing the time cost of the configuration phase
Remember
task	 doSomething	 <<	 {

	 	 	 	 println	 "Doing	 it!"

}
task	 customJar(type:	 Jar)	 {

	 	 	 	 archivePath	 =	 customJarPath

	 	 	 	 doLast	 {

	 	 	 	 	 	 	 	 println	 "Created	 the	 JAR	 file"

	 	 	 	 }

} Execution
Execution
Configuration
Consider always using `doLast()` instead of `<<` to avoid confusion between configuration and implicit execution
Project properties
Project properties
• Useful for build parameterisation
• Equivalent to global variables
- Same problems!
• Provide sensible defaults
• Assume values are strings
Default values
ext	 {

	 	 	 	 jarFilename	 =	 project.hasProperty("jarFilename")

	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ?	 jarFilename	 :	 "myArchive"

}

task	 customJar(type:	 Jar)	 {

	 	 	 	 archivePath	 =	 file("$buildDir/$jarFilename")

	 	 	 	 doLast	 {

	 	 	 	 	 	 	 	 println	 "Created	 the	 JAR	 file:	 ${archivePath}"

	 	 	 	 }

}
Check property exists first
Default value
Values can be overridden via
-P cmd line option
gradle.properties
Both only support strings
Prefer task properties
task	 customClean(type:	 Delete)	 {

	 	 	 	 delete	 "$buildDir/$jarFilename"

}
task	 customClean(type:	 Delete)	 {

	 	 	 	 delete	 customJar.archivePath

}
Use the path defined
by the task
Don’t let project properties litter your build
If the JAR task stops using the project property, `customClean` will continue to work
Refactoring
Custom tasks
Prefer
task	 doIt(type:	 MyTask)

class	 MyTask	 extends	 DefaultTask	 {

	 	 	 	 @TaskAction

	 	 	 	 def	 action()	 {	 println	 "Hello	 world!"	 }

}
task	 doIt	 <<	 {

	 	 	 	 println	 "Hello	 world!"	 }

}
over
More verbose, but easier to maintain
Easier to incorporate properties in custom task classes
Easier to migrate the task implementation out of the build file
Custom tasks
Where the task class goes:
1. In build.gradle
2. In buildSrc/src/groovy/…
3. In a JAR file
IoC in tasks
class	 MyTask	 extends	 DefaultTask	 {

	 	 	 	 File	 filePath	 =	 project.myArchivePath

	 	 	 	 @TaskAction

	 	 	 	 def	 action()	 {

	 	 	 	 	 	 	 	 println	 filePath.text

	 	 	 	 }

}
Don’t pull values from
the environment
IoC in tasks
task	 doIt(type:	 MyTask)	 {

	 	 	 	 filePath	 =	 project.myArchivePath

}
Leave configuration in the build file
Effectively Inversion of Control - values should always be injected
Last one…
Consider breaking into multiple
smaller projects
Understand your build
Task order vs dependency
task	 functionalTest(type:	 Test,	 dependsOn:	 test)
task	 functionalTest(type:	 Test)	 {

	 	 	 	 mustRunAfter	 test

}
Do the functional tests require the unit tests to run?
Or is it just the order that counts?
Leverage source sets
Instead of
configurations	 {

	 	 	 	 clientCompile

}

task	 compileClient(type:	 JavaCompile)	 {

	 	 	 	 classpath	 ...

	 	 	 	 include	 "src/main/java/**/client/*"

}

//	 Don't	 forget	 the	 test	 tasks	 and	 dependencies!

...
Leverage source sets
Use source sets
sourceSets	 {

	 	 	 	 client	 {

	 	 	 	 	 	 	 	 java	 {

	 	 	 	 	 	 	 	 	 	 	 	 srcDirs	 file("src/main/java")

	 	 	 	 	 	 	 	 	 	 	 	 include	 "src/main/java/**/client/*"

	 	 	 	 	 	 	 	 }

	 	 	 	 }

}

Get:
• clientCompile, clientRuntime configurations
• compileClientJava task
Use incremental build
class	 SignJar	 extends	 DefaultTask	 {

	 	 	 	 @InputFiles	 FileCollection	 jarFiles

	 	 	 	 @OutputDirectory	 File	 outputDir

	 	 	 	 File	 keystore

	 	 	 	 String	 keystorePassword

	 	 	 	 String	 alias

	 	 	 	 String	 aliasPassword

	 	 	 	 @TaskAction

	 	 	 	 void	 sign()	 {

	 	 	 	 	 	 	 	 ...

	 	 	 	 }

}
Changes to these input
files or output force the
task to run again
Plugins
• Encapsulate your conventions
• Package common features
• Lightweight alternative:
- apply	 from:	 "modules/check.gradle"
Know your users
Questions to ask
• Do you have only one type of user?
• What things can each type of user do?
• What do they want from the build?
• What should they see?
Example
compile
test
package/install
publish
project
lead only
Lazybones
project
If the project is published, require credentials
Fail fast
Other users don’t require credentials
Interrogate task graph
gradle.taskGraph.whenReady	 {	 graph	 ->

	 	 	 	 if	 (graph.hasTask(":lazybones-app:uploadDist"))	 {

	 	 	 	 	 	 	 	 verifyProperty(project,	 'repo.url')

	 	 	 	 	 	 	 	 verifyProperty(project,	 'repo.username')

	 	 	 	 	 	 	 	 verifyProperty(project,	 'repo.apiKey')

	 	 	 	 	 	 	 	 uploadDist.repositoryUrl	 =	 project.'repo.url'

	 	 	 	 	 	 	 	 uploadDist.username	 =	 project.'repo.username'

	 	 	 	 	 	 	 	 uploadDist.apiKey	 =	 project.'repo.apiKey'

	 	 	 	 }

}
Only check for credentials if user is trying to
publish:
Only fail fast if `uploadTask` will be executed
Fail slow would require integration tests to run - adding minutes to deployment
Other uses
• Include class obfuscation conditionally
• Limit visibility of tasks based on role
• Update version based on ‘release’ task
Summary
• Understand the Gradle model
• Keep refactoring
• Understand your build
• Know your users
Thank you!
e: peter@cacoethes.co.uk
w: http://www.cacoethes.co.uk
t: @pledbrook

More Related Content

PDF
Why your build matters
Peter Ledbrook
 
PDF
Why Gradle?
Peter Ledbrook
 
PDF
Make Your Build Great Again (DroidConSF 2017)
Jared Burrows
 
PDF
Idiomatic Gradle Plugin Writing - GradleSummit 2016
Schalk Cronjé
 
PDF
Gradle - the Enterprise Automation Tool
Izzet Mustafaiev
 
PDF
Basic Gradle Plugin Writing
Schalk Cronjé
 
PDF
Gradle in 45min
Schalk Cronjé
 
Why your build matters
Peter Ledbrook
 
Why Gradle?
Peter Ledbrook
 
Make Your Build Great Again (DroidConSF 2017)
Jared Burrows
 
Idiomatic Gradle Plugin Writing - GradleSummit 2016
Schalk Cronjé
 
Gradle - the Enterprise Automation Tool
Izzet Mustafaiev
 
Basic Gradle Plugin Writing
Schalk Cronjé
 
Gradle in 45min
Schalk Cronjé
 

What's hot (20)

PDF
Efficient JavaScript Unit Testing, May 2012
Hazem Saleh
 
PDF
Managing big test environment and running tests with Jenkins, Jenkins Job bui...
Timofey Turenko
 
PPTX
Exploring the power of Gradle in android studio - Basics & Beyond
Kaushal Dhruw
 
PDF
Cool JVM Tools to Help You Test
Schalk Cronjé
 
PDF
Introduction of React.js
Jyaasa Technologies
 
PDF
Modularizing your Grails Application with Private Plugins - SpringOne 2GX 2012
kennethaliu
 
PPT
Continuous Integration using Cruise Control
elliando dias
 
PDF
Gradle in 45min - JBCN2-16 version
Schalk Cronjé
 
PDF
Idiomatic gradle plugin writing
Schalk Cronjé
 
PDF
Workshop React.js
Commit University
 
PPTX
Dsc Charusat Learning React Part 1
JainamMehta19
 
PDF
Introducing Playwright's New Test Runner
Applitools
 
PDF
Cool Jvm Tools to Help you Test - Aylesbury Testers Version
Schalk Cronjé
 
PDF
The Gist of React Native
Darren Cruse
 
PDF
Gradle - Build system evolved
Bhagwat Kumar
 
PDF
Building an Extensible, Resumable DSL on Top of Apache Groovy
jgcloudbees
 
PDF
Automated Testing in Angular Slides
Jim Lynch
 
ODP
Gradle: The Build System you have been waiting for!
Corneil du Plessis
 
PDF
Lunch and learn: Cucumber and Capybara
Marc Seeger
 
PDF
Gradle by Example
Eric Wendelin
 
Efficient JavaScript Unit Testing, May 2012
Hazem Saleh
 
Managing big test environment and running tests with Jenkins, Jenkins Job bui...
Timofey Turenko
 
Exploring the power of Gradle in android studio - Basics & Beyond
Kaushal Dhruw
 
Cool JVM Tools to Help You Test
Schalk Cronjé
 
Introduction of React.js
Jyaasa Technologies
 
Modularizing your Grails Application with Private Plugins - SpringOne 2GX 2012
kennethaliu
 
Continuous Integration using Cruise Control
elliando dias
 
Gradle in 45min - JBCN2-16 version
Schalk Cronjé
 
Idiomatic gradle plugin writing
Schalk Cronjé
 
Workshop React.js
Commit University
 
Dsc Charusat Learning React Part 1
JainamMehta19
 
Introducing Playwright's New Test Runner
Applitools
 
Cool Jvm Tools to Help you Test - Aylesbury Testers Version
Schalk Cronjé
 
The Gist of React Native
Darren Cruse
 
Gradle - Build system evolved
Bhagwat Kumar
 
Building an Extensible, Resumable DSL on Top of Apache Groovy
jgcloudbees
 
Automated Testing in Angular Slides
Jim Lynch
 
Gradle: The Build System you have been waiting for!
Corneil du Plessis
 
Lunch and learn: Cucumber and Capybara
Marc Seeger
 
Gradle by Example
Eric Wendelin
 
Ad

Similar to Improving your Gradle builds (20)

PDF
Gradle - small introduction
Igor Popov
 
PDF
Gradle
Andrii Khaisin
 
PDF
Gradle For Beginners (Serbian Developer Conference 2013 english)
Joachim Baumann
 
PDF
Gradle Introduction
Dmitry Buzdin
 
PDF
Gradleintroduction 111010130329-phpapp01
Tino Isnich
 
PDF
Introduction to gradle
NexThoughts Technologies
 
PDF
Making the Most of Your Gradle Build
Andres Almiray
 
PDF
Gradle build tool that rocks with DSL JavaOne India 4th May 2012
Rajmahendra Hegde
 
PDF
Making the most of your gradle build - Gr8Conf 2017
Andres Almiray
 
PDF
Making the most of your gradle build - Greach 2017
Andres Almiray
 
PDF
An Introduction to Gradle for Java Developers
Kostas Saidis
 
PPTX
A brief guide to android gradle
Leonardo YongUk Kim
 
PDF
Gradle - From minutes to seconds: minimizing build times
Rene Gröschke
 
PPT
An introduction to maven gradle and sbt
Fabio Fumarola
 
PDF
Making the Most of Your Gradle Build
Andres Almiray
 
PPTX
GradleFX
Christophe Herreman
 
PDF
Enter the gradle
Parameswari Ettiappan
 
PPTX
Gradle build capabilities
Zeinab Mohamed Abdelmawla
 
PPTX
Gradle basics
Pedro Borrayo
 
PDF
Idiomatic Gradle Plugin Writing
Schalk Cronjé
 
Gradle - small introduction
Igor Popov
 
Gradle For Beginners (Serbian Developer Conference 2013 english)
Joachim Baumann
 
Gradle Introduction
Dmitry Buzdin
 
Gradleintroduction 111010130329-phpapp01
Tino Isnich
 
Introduction to gradle
NexThoughts Technologies
 
Making the Most of Your Gradle Build
Andres Almiray
 
Gradle build tool that rocks with DSL JavaOne India 4th May 2012
Rajmahendra Hegde
 
Making the most of your gradle build - Gr8Conf 2017
Andres Almiray
 
Making the most of your gradle build - Greach 2017
Andres Almiray
 
An Introduction to Gradle for Java Developers
Kostas Saidis
 
A brief guide to android gradle
Leonardo YongUk Kim
 
Gradle - From minutes to seconds: minimizing build times
Rene Gröschke
 
An introduction to maven gradle and sbt
Fabio Fumarola
 
Making the Most of Your Gradle Build
Andres Almiray
 
Enter the gradle
Parameswari Ettiappan
 
Gradle build capabilities
Zeinab Mohamed Abdelmawla
 
Gradle basics
Pedro Borrayo
 
Idiomatic Gradle Plugin Writing
Schalk Cronjé
 
Ad

More from Peter Ledbrook (9)

PDF
Groovy for Java Developers
Peter Ledbrook
 
PDF
Application Architectures in Grails
Peter Ledbrook
 
PDF
Open source-and-you-gr8conf-us-2013
Peter Ledbrook
 
PDF
Groovy & Grails for Spring/Java developers
Peter Ledbrook
 
PDF
Grails & the World of Tomorrow
Peter Ledbrook
 
PDF
Migrating to Cloud Foundry
Peter Ledbrook
 
PDF
Grails 2.0 Update
Peter Ledbrook
 
PDF
Grails and the World of Tomorrow
Peter Ledbrook
 
PDF
Cloud Foundry for Java devs
Peter Ledbrook
 
Groovy for Java Developers
Peter Ledbrook
 
Application Architectures in Grails
Peter Ledbrook
 
Open source-and-you-gr8conf-us-2013
Peter Ledbrook
 
Groovy & Grails for Spring/Java developers
Peter Ledbrook
 
Grails & the World of Tomorrow
Peter Ledbrook
 
Migrating to Cloud Foundry
Peter Ledbrook
 
Grails 2.0 Update
Peter Ledbrook
 
Grails and the World of Tomorrow
Peter Ledbrook
 
Cloud Foundry for Java devs
Peter Ledbrook
 

Recently uploaded (20)

PDF
The Future of Mobile Is Context-Aware—Are You Ready?
iProgrammer Solutions Private Limited
 
PDF
Accelerating Oracle Database 23ai Troubleshooting with Oracle AHF Fleet Insig...
Sandesh Rao
 
PDF
Orbitly Pitch Deck|A Mission-Driven Platform for Side Project Collaboration (...
zz41354899
 
PPTX
AI and Robotics for Human Well-being.pptx
JAYMIN SUTHAR
 
PDF
Unlocking the Future- AI Agents Meet Oracle Database 23ai - AIOUG Yatra 2025.pdf
Sandesh Rao
 
PDF
Trying to figure out MCP by actually building an app from scratch with open s...
Julien SIMON
 
PDF
Doc9.....................................
SofiaCollazos
 
PDF
MASTERDECK GRAPHSUMMIT SYDNEY (Public).pdf
Neo4j
 
PDF
GDG Cloud Munich - Intro - Luiz Carneiro - #BuildWithAI - July - Abdel.pdf
Luiz Carneiro
 
PDF
OFFOFFBOX™ – A New Era for African Film | Startup Presentation
ambaicciwalkerbrian
 
PDF
Structs to JSON: How Go Powers REST APIs
Emily Achieng
 
PDF
Get More from Fiori Automation - What’s New, What Works, and What’s Next.pdf
Precisely
 
PDF
Make GenAI investments go further with the Dell AI Factory
Principled Technologies
 
PDF
How ETL Control Logic Keeps Your Pipelines Safe and Reliable.pdf
Stryv Solutions Pvt. Ltd.
 
PDF
Data_Analytics_vs_Data_Science_vs_BI_by_CA_Suvidha_Chaplot.pdf
CA Suvidha Chaplot
 
PDF
AI-Cloud-Business-Management-Platforms-The-Key-to-Efficiency-Growth.pdf
Artjoker Software Development Company
 
PDF
Google I/O Extended 2025 Baku - all ppts
HusseinMalikMammadli
 
PDF
The Future of Artificial Intelligence (AI)
Mukul
 
PPTX
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
PDF
Presentation about Hardware and Software in Computer
snehamodhawadiya
 
The Future of Mobile Is Context-Aware—Are You Ready?
iProgrammer Solutions Private Limited
 
Accelerating Oracle Database 23ai Troubleshooting with Oracle AHF Fleet Insig...
Sandesh Rao
 
Orbitly Pitch Deck|A Mission-Driven Platform for Side Project Collaboration (...
zz41354899
 
AI and Robotics for Human Well-being.pptx
JAYMIN SUTHAR
 
Unlocking the Future- AI Agents Meet Oracle Database 23ai - AIOUG Yatra 2025.pdf
Sandesh Rao
 
Trying to figure out MCP by actually building an app from scratch with open s...
Julien SIMON
 
Doc9.....................................
SofiaCollazos
 
MASTERDECK GRAPHSUMMIT SYDNEY (Public).pdf
Neo4j
 
GDG Cloud Munich - Intro - Luiz Carneiro - #BuildWithAI - July - Abdel.pdf
Luiz Carneiro
 
OFFOFFBOX™ – A New Era for African Film | Startup Presentation
ambaicciwalkerbrian
 
Structs to JSON: How Go Powers REST APIs
Emily Achieng
 
Get More from Fiori Automation - What’s New, What Works, and What’s Next.pdf
Precisely
 
Make GenAI investments go further with the Dell AI Factory
Principled Technologies
 
How ETL Control Logic Keeps Your Pipelines Safe and Reliable.pdf
Stryv Solutions Pvt. Ltd.
 
Data_Analytics_vs_Data_Science_vs_BI_by_CA_Suvidha_Chaplot.pdf
CA Suvidha Chaplot
 
AI-Cloud-Business-Management-Platforms-The-Key-to-Efficiency-Growth.pdf
Artjoker Software Development Company
 
Google I/O Extended 2025 Baku - all ppts
HusseinMalikMammadli
 
The Future of Artificial Intelligence (AI)
Mukul
 
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
Presentation about Hardware and Software in Computer
snehamodhawadiya
 

Improving your Gradle builds

  • 1. Improving your Gradle builds Peter Ledbrook e: [email protected] w: http://www.cacoethes.co.uk t: @pledbrook
  • 2. “Safety” in build tools "Straight Razor" by Horst.Burkhardt - Own work. Licensed under CC BY-SA 3.0 via Wikimedia Commons Gradle is often treated like a cut-throat razor: unsafe Code == spaghetti builds (allegedly) Some people think it’s better to limit build authors to configuration only Is this a good comparison though?
  • 3. A better analogy by Noel C. Hankamer - Creative Commons 2.0 Not all jobs are the same for a workman Need the right tools for the job Some tools are dangerous - so you learn to use them Power drills, heavy duty knives, etc.
  • 4. Gradle Yes, you can create spaghetti builds, but… “A bad workman blames his tools”
  • 5. So how do you create maintainable builds?
  • 6. First, understand the Gradle model
  • 7. Gradle is an API Project Task Repository Dependency Configuration Source set (Java) This is just part of the Gradle model, which allows you to model your own build processes. Show Gradle DSL and API references if possible: http://www.gradle.org/doc/latest/…
  • 8. A basic Java build apply plugin: "java" version = "1.0" repositories { jcenter() } dependencies { compile "asm:asm-all:3.3.1", "commons-io:commons-io:1.4" } compileJava.options.incremental = true An instance of Task A Repository
  • 9. Everything from Project • project.tasks • project.configurations • project.repositories • project.dependencies • project.sourceSets (added by Java plugin) All the model elements are available from the project The project itself can be accessed via the `project` property
  • 10. The three phases Initialisation Configuration Execution Only relevant to multi- project builds Configures tasks and builds the task graph Executes the necessary tasks based on the task graph Beyond the model that defines the build, this is what happens when you actually run that build
  • 11. At execution Y X Z => Z X Y W V Linear execution orderTask graph W V During configuration Gradle builds a Directed Acyclic Graph (DAG) of tasks Before execution, the graph is turned into an execution order There is no distinction between targets and tasks like in Apache Ant
  • 14. Beware the config phase • Configuration always happens - even just running grade tasks! - this will change soon(ish) • Avoid expensive work
  • 15. Profile your build! gradle --profile <taskName> This generates a report with timings for the different phases of each project in the build
  • 17. Example apply plugin: "java" ... jar { version = new URL("http://buildsvr/version").text } Evaluated every build! (This will change soon in Gradle) Potentially unreliable network call *every* time the build runs No matter what tasks are executed Gradle will perform configuration on-demand in the not too distant future, reducing the time cost of the configuration phase
  • 18. Remember task doSomething << { println "Doing it!" } task customJar(type: Jar) { archivePath = customJarPath doLast { println "Created the JAR file" } } Execution Execution Configuration Consider always using `doLast()` instead of `<<` to avoid confusion between configuration and implicit execution
  • 20. Project properties • Useful for build parameterisation • Equivalent to global variables - Same problems! • Provide sensible defaults • Assume values are strings
  • 21. Default values ext { jarFilename = project.hasProperty("jarFilename") ? jarFilename : "myArchive" } task customJar(type: Jar) { archivePath = file("$buildDir/$jarFilename") doLast { println "Created the JAR file: ${archivePath}" } } Check property exists first Default value Values can be overridden via -P cmd line option gradle.properties Both only support strings
  • 22. Prefer task properties task customClean(type: Delete) { delete "$buildDir/$jarFilename" } task customClean(type: Delete) { delete customJar.archivePath } Use the path defined by the task Don’t let project properties litter your build If the JAR task stops using the project property, `customClean` will continue to work
  • 24. Custom tasks Prefer task doIt(type: MyTask) class MyTask extends DefaultTask { @TaskAction def action() { println "Hello world!" } } task doIt << { println "Hello world!" } } over More verbose, but easier to maintain Easier to incorporate properties in custom task classes Easier to migrate the task implementation out of the build file
  • 25. Custom tasks Where the task class goes: 1. In build.gradle 2. In buildSrc/src/groovy/… 3. In a JAR file
  • 26. IoC in tasks class MyTask extends DefaultTask { File filePath = project.myArchivePath @TaskAction def action() { println filePath.text } } Don’t pull values from the environment
  • 27. IoC in tasks task doIt(type: MyTask) { filePath = project.myArchivePath } Leave configuration in the build file Effectively Inversion of Control - values should always be injected
  • 28. Last one… Consider breaking into multiple smaller projects
  • 30. Task order vs dependency task functionalTest(type: Test, dependsOn: test) task functionalTest(type: Test) { mustRunAfter test } Do the functional tests require the unit tests to run? Or is it just the order that counts?
  • 31. Leverage source sets Instead of configurations { clientCompile } task compileClient(type: JavaCompile) { classpath ... include "src/main/java/**/client/*" } // Don't forget the test tasks and dependencies! ...
  • 32. Leverage source sets Use source sets sourceSets { client { java { srcDirs file("src/main/java") include "src/main/java/**/client/*" } } } Get: • clientCompile, clientRuntime configurations • compileClientJava task
  • 33. Use incremental build class SignJar extends DefaultTask { @InputFiles FileCollection jarFiles @OutputDirectory File outputDir File keystore String keystorePassword String alias String aliasPassword @TaskAction void sign() { ... } } Changes to these input files or output force the task to run again
  • 34. Plugins • Encapsulate your conventions • Package common features • Lightweight alternative: - apply from: "modules/check.gradle"
  • 36. Questions to ask • Do you have only one type of user? • What things can each type of user do? • What do they want from the build? • What should they see?
  • 37. Example compile test package/install publish project lead only Lazybones project If the project is published, require credentials Fail fast Other users don’t require credentials
  • 38. Interrogate task graph gradle.taskGraph.whenReady { graph -> if (graph.hasTask(":lazybones-app:uploadDist")) { verifyProperty(project, 'repo.url') verifyProperty(project, 'repo.username') verifyProperty(project, 'repo.apiKey') uploadDist.repositoryUrl = project.'repo.url' uploadDist.username = project.'repo.username' uploadDist.apiKey = project.'repo.apiKey' } } Only check for credentials if user is trying to publish: Only fail fast if `uploadTask` will be executed Fail slow would require integration tests to run - adding minutes to deployment
  • 39. Other uses • Include class obfuscation conditionally • Limit visibility of tasks based on role • Update version based on ‘release’ task
  • 40. Summary • Understand the Gradle model • Keep refactoring • Understand your build • Know your users
  • 41. Thank you! e: [email protected] w: http://www.cacoethes.co.uk t: @pledbrook