Precisamos falar
sobre Gradle
Wellington Pinheiro
Quem sou eu
• dev Java desde 2001

• arquiteto de sistemas

• eterno aprendiz

• fanático por automação e
devops

• escritor do blog
thecodeinside.com

• baixista, apreciador de cerveja
e boa música
@wrpinheiro
/in/wrpinheiro/
/wrpinheiro/
/wrpinheiro/
Agenda
• ferramentas de build

• características do gradle

• tasks

• plugins (java e maven)

• exemplo spring boot

• multi-projeto

• mais coisas legais
por que outra ferramenta de build?
imperativo
vs
declarativo
opinativo (convenções)
vs
adaptável
• declarativo, opinativo mas adaptável

• facilmente configurável e extensível

• permite a criação de convenções do próprio
usuário

• possui modelo interno

• baseado em tasks (assim como no ANT)

• open source
Características
Buildfile
https://docs.gradle.org/current/dsl/org.gradle.api.Project.html

• build.gradle é o nome padrão

• a classe Project representa o buildfile

• os tipos principais associados a um Project são:

•tasks
•dependencies
•plugins
•properties
•subproject
• todo buildfile é basicamente um programa em groovy com closures (DSL)
Task
Task
https://docs.gradle.org/current/dsl/
org.gradle.api.Task.html#org.gradle.api.Task

• menor componente de um build

• é um objeto

• possui uma API

• possui uma lista de ações

• possuem relacionamento de dependência
Task
https://docs.gradle.org/current/dsl/
org.gradle.api.Task.html#org.gradle.api.Task:doFirst(groovy.l
ang.Closure)

• possuem uma lista de ações:

• executadas no começo (doFirst)

• intermediárias (a ação da task propriamente)

• executadas no final (doLast)
Task - exemplos
task helloWorld
task anotherHello
helloWorld {
doLast {
print "World "
}
}
helloWorld {
doFirst {
println "Hello"
}
}
helloWorld {
group "Hello"
}
Task - exemplos
helloWorld.doLast {
println "Finalizando task…"
}
helloWorld.doFirst {
println "Inicializando task…"
}
Task
Gradle encontra Groovy
helloWorld.doLast {
[1, 2, 3].each {
println "Finalizando task. Passo $it"
}
}
3.times {
task muitasTasks {
doLast { println "Task: ${name}" }
}
}
Task - dependências
• uma task pode depender de uma ou mais tasks

• dependências são representadas como DAG

• portanto…dependências não podem ser cíclicas

• cada task do grafo é executada uma única vez
Task - dependências (DAG)
task compile {
doLast { println "Compilando classes" }
}
task jar {
doLast { println "Gerando Jarfile" }
}
task test {
doLast { println "Executando test" }
}
task deploy {
doLast { println "Fazendo deploy" }
}
test.dependsOn compile
jar.dependsOn compile, test
deploy.dependsOn jar
compile
test jar
deploy
Tasks - dependências
3.times { index ->
task "muitasTasks$index" {
doLast { println "Task: ${name}" }
}
}
def muitasTasks = tasks.matching { t ->
t.name.startsWith("muitasTasks");
}
task dependeDasMuitas {
dependsOn muitasTasks
}
Trabalhando com Tasks
task ls(type: Exec) {
commandLine 'ls'
args '-Flah'
}
task copyBuild(type: Copy) {
from 'build.gradle'
into 'output/'
}
task renameBuild(type: Copy) {
from 'build.gradle'
into '.'
rename '(.*)', '$1.new'
}
Trabalhando com Tasks
task delete {
delete 'build.gradle.new'
}
task tar(type: Tar) {
from '.'
include '*'
exclude 'output'
archiveName 'project.tar.gz'
compression = Compression.GZIP
destinationDir file('output')
}
Trabalhando com Tasks
task tail(type: Exec) {
commandLine 'tail'
}
// grade customTail -Plines=10
task customTail {
doLast {
tail {
args "-${project.lines}", 'build.gradle'
}.execute()
}
}
Fases de um Build
• inicialização

• instância de Project é criada (no caso de multi-projeto é criado
um Project para cada subprojeto)

• configuração

• os objetos do projeto são criado (tasks, dependências,
repositórios, propriedades)

• execução

• determina o conjunto de tasks configuradas na fase de
configuração e as executa
Plugins
Plugins
• adicionam tasks e objetos de domínio

• configuram o projeto de acordo com convenções

• extensões ou construção de DSLs

• encapsulam lógica imperativa
Standard Plugins
(exemplos)
https://docs.gradle.org/4.1/userguide/standard_plugins.html

• language: java, groovy, scala, c, cpp, …

• integration: application, ear, maven, war, …

• development: eclipse, idea, checkstyle, pmd, jacoco, …

• diversos plugins de terceiros
Plugins - como usar
• DSL tradicional

apply from: 'file.gradle'
apply plugin: 'java'
• plugin DSL (*)

plugins {
id 'com.jfrog.bintray' version '1.7.3'
}
(*) https://plugins.gradle.org/
Plugins - como usar
buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath "gradle.plugin.org.gradle.kotlin:gradle-kotlin-dsl-plugins:0.10.9"
}
}
apply plugin: "org.gradle.kotlin.kotlin-dsl"
Java Plugin
Task
Java Plugin
apply plugin: 'java'
task runApplication(type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
main = 'org.soujava.exemplogradle.Calculadora'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
Dependências e
Repositórios
Dependências
dependencies {
compile ‘commons-lang:commons-lang:2.6’
compile (
'org.apache.commons:commons-lang3:3.6',
'org.slf4j:slf4j-api:1.7.25'
)
testCompile ‘org.mockito:mockito:1.9.0-rc1'
compile group: 'com.google.code.guice', name: ‘guice',
version: ‘1.0'
compile files('hibernate.jar', ‘libs/spring.jar')
compile fileTree(‘libs’)
runtimeOnly('org.slf4j:slf4j-log4j12:1.7.25')
}
Resolução de
Dependências
dependencies {
compile('org.hibernate:hibernate:3.1') {
force = true
exclude module: 'cglib'
exclude group: 'org.jmock'
exclude group: 'org.unwanted', module: 'iAmBuggy'
transitive = false
}
}
Repositórios
repositories {
mavenLocal()
mavenCentral()
jCenter()
maven {
url 'http://artifactory.domain/artifactory/libs-release'
}
maven {
url "${url}"
credentials {
username = 'joe'
password = 'secret'
}
}
}
Repositórios
• Configurado Credenciais através do arquivo gradle.properties

mavenRepo=localhost
mavenUser=admin
mavenPass=pass123
repositories {
maven {
url "${mavenRepo}"
credentials {
username = "${mavenUser}"
password = "${mavenPass}"
}
}
}
Java Plugin
Dependências
apply plugin: 'java'
task runApplication(type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
main = 'org.soujava.exemplogradle.Calculadora'
}
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
repositories {
mavenCentral()
}
dependencies {
compile('org.apache.commons:commons-lang3:3.6')
}
Testes
https://docs.gradle.org/current/userguide/
java_plugin.html#sec:java_test

• o java plugin disponibiliza as tasks para executar diversos
tipos 

gradle test
gradle test --tests "*Calculadora*.*sum*"
gradle test --tests "*Calculadora*.difference*"
gradle test --tests "*Calc*" --rerun-tasks
Test filtering
test {
filter {
includeTestsMatching "*UiCheck"
includeTestsMatching
"org.gradle.internal.*"
includeTestsMatching "*IntegTest"
}
}
Test logging
test {
testLogging {
events "passed", "skipped", "failed"
}
}
• em execuções subsequentes executar com --rerun-
tasks para forçar a execução das tasks de teste
JAR
version = "1.0"
jar {
manifest {
attributes(
"Implementation-Title":"Exemplo Gradle",
"Implementation-Version": version)
}
}
Maven Plugin
• permite instalar pacotes no repositório local do maven

• inclui suporte para fazer deploy de artefatos em
repositórios maven

• permite gerar os metadados do maven associados ao
artefato
Maven Plugin
apply plugin: 'java'
apply plugin: 'maven'
[…]
group = "org.soujava.exemplogradle"
version = "1.0"
uploadArchives {
repositories {
mavenDeployer {
repository(url: "http://localhost:8081/artifactory/libs-release-local") {
authentication(userName: "admin", password: "password")
}
}
}
}
Spring Boot
encontra Gradle
Multiprojeto
Multiprojeto
• composto de um root project e os subprojetos

• configuração pode ser feita do root para os subprojetos

• subprojetos podem depender de outros subprojetos

• gradle recompila subprojetos usados como dependência
quando necessário

• subprojetos podem ser compilados em paralelo

• um "projeto multiprojeto" é identificado pela existência do
arquivo settings.gradle
Multiprojeto
• settings.gradle define quais são os subprojetos

include "services", "api"
• cada subprojeto pode conter seu próprio build.gradle, mas
não é obrigatório

• configurações gerais são feitas no build.gradle do root
project

allprojects { ... }
subprojects { ... }
Multiprojeto
subprojects {
apply plugin: 'java'
repositories() {
mavenCentral()
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
Multiprojeto
• definido no root project

project(":services") {
dependencies {
testCompile('junit:junit:4.12')
}
}
• definido no projeto services

dependencies {
testCompile('junit:junit:4.12')
}
Multiprojeto
• dependência entre projetos

// no subprojeto api
dependencies {
compile project(':services')
}
Mais coisas legais!
• permite rodar o gradle sem ter gradle instalado (*)

• faz download e instala uma versão específica do gradle

• garante que o build será feito sempre com a mesma versão de
gradle

• gradle init já gera o wrapper

(*) é necessário o gradle para gerar o wrapper ou use docker para
isso: http://thecodeinside.com/usando-docker-para-criar-os-scripts-
do-gradle-wrapper/
Daemon
• conceito da Hotspot

• quanto mais executa mais rápido
fica

• melhoria de performance (*):

• 2o. build: 15-75% mais rápido

• 5o. build: 30-90% mais rápido

(*) estatísticas pré versão 3.0 - Eric
Wedelin - https://
www.youtube.com/watch?
v=J5tLSpAZh7w
"The best way to do work faster is to 

not do work that doesn’t need doing"

(Stefan Wolf, Lóránt Pintér)
Incremental Build
Continuous build
• executa uma task continuamente

• é novamente acionada se houver mudança em seus inputs ou outputs

• use o flag --continuous para executar
Build scan
plugins {
id 'com.gradle.build-scan' version '1.8'
}
buildScan {
licenseAgreementUrl = 'https://gradle.com/terms-of-service'
licenseAgree = 'yes'
}
• gradle build --scan
Crie sua própria DSL
plugins {
id 'org.hidetake.ssh'
version '2.9.0'
}
ssh.settings {
knownHosts = allowAnyHosts
}
remotes {
node {
host = ‘192.168.1.101'
user = ‘ubuntu'
password = ‘ubuntu'
}
}
task nodeUptime {
doLast {
ssh.run {
session(remotes.node) {
execute "uptime"
}
}
}
}
https://linchpiner.github.io/gradle-for-devops-1.html
Groovy não é sua praia?
use Kotlin!
open class HelloTask : DefaultTask() {
init {
group = "My"
description = "Prints a description of ${project.name}."
}
@TaskAction
fun run() {
println("I'm ${project.name}")
}
}
fun Project.withHelloTask() = task<HelloTask>("hello")
Obrigado!
Wellington Pinheiro
@wrpinheiro

Precisamos falar sobre Gradle

  • 1.
  • 2.
    Quem sou eu •dev Java desde 2001 • arquiteto de sistemas • eterno aprendiz • fanático por automação e devops • escritor do blog thecodeinside.com • baixista, apreciador de cerveja e boa música @wrpinheiro /in/wrpinheiro/ /wrpinheiro/ /wrpinheiro/
  • 3.
    Agenda • ferramentas debuild • características do gradle • tasks • plugins (java e maven) • exemplo spring boot • multi-projeto • mais coisas legais
  • 4.
    por que outraferramenta de build?
  • 6.
  • 7.
  • 9.
    • declarativo, opinativomas adaptável • facilmente configurável e extensível • permite a criação de convenções do próprio usuário • possui modelo interno • baseado em tasks (assim como no ANT) • open source Características
  • 10.
    Buildfile https://docs.gradle.org/current/dsl/org.gradle.api.Project.html • build.gradle éo nome padrão • a classe Project representa o buildfile • os tipos principais associados a um Project são: •tasks •dependencies •plugins •properties •subproject • todo buildfile é basicamente um programa em groovy com closures (DSL)
  • 11.
  • 12.
    Task https://docs.gradle.org/current/dsl/ org.gradle.api.Task.html#org.gradle.api.Task • menor componentede um build • é um objeto • possui uma API • possui uma lista de ações • possuem relacionamento de dependência
  • 13.
    Task https://docs.gradle.org/current/dsl/ org.gradle.api.Task.html#org.gradle.api.Task:doFirst(groovy.l ang.Closure) • possuem umalista de ações: • executadas no começo (doFirst) • intermediárias (a ação da task propriamente) • executadas no final (doLast)
  • 14.
    Task - exemplos taskhelloWorld task anotherHello helloWorld { doLast { print "World " } } helloWorld { doFirst { println "Hello" } } helloWorld { group "Hello" }
  • 15.
    Task - exemplos helloWorld.doLast{ println "Finalizando task…" } helloWorld.doFirst { println "Inicializando task…" }
  • 16.
    Task Gradle encontra Groovy helloWorld.doLast{ [1, 2, 3].each { println "Finalizando task. Passo $it" } } 3.times { task muitasTasks { doLast { println "Task: ${name}" } } }
  • 17.
    Task - dependências •uma task pode depender de uma ou mais tasks • dependências são representadas como DAG • portanto…dependências não podem ser cíclicas • cada task do grafo é executada uma única vez
  • 18.
    Task - dependências(DAG) task compile { doLast { println "Compilando classes" } } task jar { doLast { println "Gerando Jarfile" } } task test { doLast { println "Executando test" } } task deploy { doLast { println "Fazendo deploy" } } test.dependsOn compile jar.dependsOn compile, test deploy.dependsOn jar compile test jar deploy
  • 19.
    Tasks - dependências 3.times{ index -> task "muitasTasks$index" { doLast { println "Task: ${name}" } } } def muitasTasks = tasks.matching { t -> t.name.startsWith("muitasTasks"); } task dependeDasMuitas { dependsOn muitasTasks }
  • 20.
    Trabalhando com Tasks taskls(type: Exec) { commandLine 'ls' args '-Flah' } task copyBuild(type: Copy) { from 'build.gradle' into 'output/' } task renameBuild(type: Copy) { from 'build.gradle' into '.' rename '(.*)', '$1.new' }
  • 21.
    Trabalhando com Tasks taskdelete { delete 'build.gradle.new' } task tar(type: Tar) { from '.' include '*' exclude 'output' archiveName 'project.tar.gz' compression = Compression.GZIP destinationDir file('output') }
  • 22.
    Trabalhando com Tasks tasktail(type: Exec) { commandLine 'tail' } // grade customTail -Plines=10 task customTail { doLast { tail { args "-${project.lines}", 'build.gradle' }.execute() } }
  • 23.
    Fases de umBuild • inicialização • instância de Project é criada (no caso de multi-projeto é criado um Project para cada subprojeto) • configuração • os objetos do projeto são criado (tasks, dependências, repositórios, propriedades) • execução • determina o conjunto de tasks configuradas na fase de configuração e as executa
  • 24.
  • 25.
    Plugins • adicionam taskse objetos de domínio • configuram o projeto de acordo com convenções • extensões ou construção de DSLs • encapsulam lógica imperativa
  • 26.
    Standard Plugins (exemplos) https://docs.gradle.org/4.1/userguide/standard_plugins.html • language:java, groovy, scala, c, cpp, … • integration: application, ear, maven, war, … • development: eclipse, idea, checkstyle, pmd, jacoco, … • diversos plugins de terceiros
  • 27.
    Plugins - comousar • DSL tradicional apply from: 'file.gradle' apply plugin: 'java' • plugin DSL (*) plugins { id 'com.jfrog.bintray' version '1.7.3' } (*) https://plugins.gradle.org/
  • 28.
    Plugins - comousar buildscript { repositories { maven { url "https://plugins.gradle.org/m2/" } } dependencies { classpath "gradle.plugin.org.gradle.kotlin:gradle-kotlin-dsl-plugins:0.10.9" } } apply plugin: "org.gradle.kotlin.kotlin-dsl"
  • 29.
  • 30.
  • 31.
    Java Plugin apply plugin:'java' task runApplication(type: JavaExec) { classpath = sourceSets.main.runtimeClasspath main = 'org.soujava.exemplogradle.Calculadora' } sourceCompatibility = 1.8 targetCompatibility = 1.8
  • 32.
  • 33.
    Dependências dependencies { compile ‘commons-lang:commons-lang:2.6’ compile( 'org.apache.commons:commons-lang3:3.6', 'org.slf4j:slf4j-api:1.7.25' ) testCompile ‘org.mockito:mockito:1.9.0-rc1' compile group: 'com.google.code.guice', name: ‘guice', version: ‘1.0' compile files('hibernate.jar', ‘libs/spring.jar') compile fileTree(‘libs’) runtimeOnly('org.slf4j:slf4j-log4j12:1.7.25') }
  • 34.
    Resolução de Dependências dependencies { compile('org.hibernate:hibernate:3.1'){ force = true exclude module: 'cglib' exclude group: 'org.jmock' exclude group: 'org.unwanted', module: 'iAmBuggy' transitive = false } }
  • 35.
    Repositórios repositories { mavenLocal() mavenCentral() jCenter() maven { url'http://artifactory.domain/artifactory/libs-release' } maven { url "${url}" credentials { username = 'joe' password = 'secret' } } }
  • 36.
    Repositórios • Configurado Credenciaisatravés do arquivo gradle.properties mavenRepo=localhost mavenUser=admin mavenPass=pass123 repositories { maven { url "${mavenRepo}" credentials { username = "${mavenUser}" password = "${mavenPass}" } } }
  • 37.
    Java Plugin Dependências apply plugin:'java' task runApplication(type: JavaExec) { classpath = sourceSets.main.runtimeClasspath main = 'org.soujava.exemplogradle.Calculadora' } sourceCompatibility = "1.8" targetCompatibility = "1.8" repositories { mavenCentral() } dependencies { compile('org.apache.commons:commons-lang3:3.6') }
  • 38.
    Testes https://docs.gradle.org/current/userguide/ java_plugin.html#sec:java_test • o javaplugin disponibiliza as tasks para executar diversos tipos gradle test gradle test --tests "*Calculadora*.*sum*" gradle test --tests "*Calculadora*.difference*" gradle test --tests "*Calc*" --rerun-tasks
  • 39.
    Test filtering test { filter{ includeTestsMatching "*UiCheck" includeTestsMatching "org.gradle.internal.*" includeTestsMatching "*IntegTest" } }
  • 40.
    Test logging test { testLogging{ events "passed", "skipped", "failed" } } • em execuções subsequentes executar com --rerun- tasks para forçar a execução das tasks de teste
  • 41.
    JAR version = "1.0" jar{ manifest { attributes( "Implementation-Title":"Exemplo Gradle", "Implementation-Version": version) } }
  • 42.
    Maven Plugin • permiteinstalar pacotes no repositório local do maven • inclui suporte para fazer deploy de artefatos em repositórios maven • permite gerar os metadados do maven associados ao artefato
  • 43.
    Maven Plugin apply plugin:'java' apply plugin: 'maven' […] group = "org.soujava.exemplogradle" version = "1.0" uploadArchives { repositories { mavenDeployer { repository(url: "http://localhost:8081/artifactory/libs-release-local") { authentication(userName: "admin", password: "password") } } } }
  • 44.
  • 45.
  • 46.
    Multiprojeto • composto deum root project e os subprojetos • configuração pode ser feita do root para os subprojetos • subprojetos podem depender de outros subprojetos • gradle recompila subprojetos usados como dependência quando necessário • subprojetos podem ser compilados em paralelo • um "projeto multiprojeto" é identificado pela existência do arquivo settings.gradle
  • 47.
    Multiprojeto • settings.gradle definequais são os subprojetos include "services", "api" • cada subprojeto pode conter seu próprio build.gradle, mas não é obrigatório • configurações gerais são feitas no build.gradle do root project allprojects { ... } subprojects { ... }
  • 48.
    Multiprojeto subprojects { apply plugin:'java' repositories() { mavenCentral() } sourceCompatibility = 1.8 targetCompatibility = 1.8 }
  • 49.
    Multiprojeto • definido noroot project project(":services") { dependencies { testCompile('junit:junit:4.12') } } • definido no projeto services dependencies { testCompile('junit:junit:4.12') }
  • 50.
    Multiprojeto • dependência entreprojetos // no subprojeto api dependencies { compile project(':services') }
  • 51.
  • 52.
    • permite rodaro gradle sem ter gradle instalado (*) • faz download e instala uma versão específica do gradle • garante que o build será feito sempre com a mesma versão de gradle • gradle init já gera o wrapper (*) é necessário o gradle para gerar o wrapper ou use docker para isso: http://thecodeinside.com/usando-docker-para-criar-os-scripts- do-gradle-wrapper/
  • 53.
    Daemon • conceito daHotspot • quanto mais executa mais rápido fica • melhoria de performance (*): • 2o. build: 15-75% mais rápido • 5o. build: 30-90% mais rápido (*) estatísticas pré versão 3.0 - Eric Wedelin - https:// www.youtube.com/watch? v=J5tLSpAZh7w
  • 54.
    "The best wayto do work faster is to not do work that doesn’t need doing" (Stefan Wolf, Lóránt Pintér) Incremental Build
  • 55.
    Continuous build • executauma task continuamente • é novamente acionada se houver mudança em seus inputs ou outputs • use o flag --continuous para executar
  • 56.
    Build scan plugins { id'com.gradle.build-scan' version '1.8' } buildScan { licenseAgreementUrl = 'https://gradle.com/terms-of-service' licenseAgree = 'yes' } • gradle build --scan
  • 57.
    Crie sua própriaDSL plugins { id 'org.hidetake.ssh' version '2.9.0' } ssh.settings { knownHosts = allowAnyHosts } remotes { node { host = ‘192.168.1.101' user = ‘ubuntu' password = ‘ubuntu' } } task nodeUptime { doLast { ssh.run { session(remotes.node) { execute "uptime" } } } } https://linchpiner.github.io/gradle-for-devops-1.html
  • 58.
    Groovy não ésua praia? use Kotlin! open class HelloTask : DefaultTask() { init { group = "My" description = "Prints a description of ${project.name}." } @TaskAction fun run() { println("I'm ${project.name}") } } fun Project.withHelloTask() = task<HelloTask>("hello")
  • 59.