GRADLE
EX
MACHINA
ANDRES ALMIRAY
@AALMIRAY
@aalmiray
@aalmiray
@aalmiray
POM.XML
• POM stands for Project Object Model.
• A POM file defines both how a project should be built and how
consumers may interact with the published artifacts.
• Maven delivers lots of features out of the box thanks to the
hierarchical nature of the POM.
• The Maven Super POM provides default configuration for
common plugins such as compiler, resources, surefire, etc.
• The strict nature of the structure found in the POM allows
anyone to understand the configuration.
@aalmiray
@aalmiray
BUILD.GRADLE
• Gradle build files only specify how projects should be built.
• The definition for consumers is delivered through a generated
POM file.
• Gradle builds are highly customizable, resulting in a wider
range of build patterns.
CAN WE HAVE A
MAVEN-LIKE
STRUCTURE ON TOP
OF GRADLE?
HTTP://GITHUB.COM/AALMIRAY/KORDAMP-GRADLE-PLUGINS
HTTPS://AALMIRAY.GITHUB.IO/KORDAMP-GRADLE-PLUGINS
FILE
STRUCTURE
@aalmiray
STANDARD (MAVEN)
.
├── pom.xml
├── guide
│ └── pom.xml
├── project1
│ └── pom.xml
└── project2
└── pom.xml
@aalmiray
STANDARD (MAVEN)
<project>
<groupId>com.acme</groupId>
<artifactId>parent</artifactId>
<version>0.0.0</version>
<modules>
<module>guide</module>
<module>project1</module>
<module>project2</module>
</modules>
</project>
<project>
<parent>
<groupId>com.acme</groupId>
<artifactId>parent</artifactId>
<version>0.0.0</version>
</parent>
</project>
@aalmiray
TWO-LEVEL (MAVEN)
.
├── pom.xml
├── docs
│ └── guide
│ └── pom.xml
└── subprojects
├── project1
│ └── pom.xml
└── project2
└── pom.xml
@aalmiray
TWO-LEVEL (MAVEN)
<project>
<groupId>com.acme</groupId>
<artifactId>parent</artifactId>
<version>0.0.0</version>
<modules>
<module>docs/guide</module>
<module>subprojects/project2</module>
<module>subprojects/project3</module>
</modules>
</project>
<project>
<parent>
<groupId>com.acme</groupId>
<artifactId>parent</artifactId>
<version>0.0.0</version>
<path>../../pom.xml</path>
</parent>
</project>
@aalmiray
MULTI-LEVEL (MAVEN)
.
├── pom.xml
├── guide
│ └── pom.xml
└── subprojects
├── project1
│ └── pom.xml
└── project2
└── pom.xml
@aalmiray
MULTI-LEVEL (MAVEN)
<project>
<groupId>com.acme</groupId>
<artifactId>parent</artifactId>
<version>0.0.0</version>
<modules>
<module>project1</module>
<module>subprojects/project2</module>
<module>subprojects/project3</module>
</modules>
</project>
<project>
<parent>
<groupId>com.acme</groupId>
<artifactId>parent</artifactId>
<version>0.0.0</version>
</parent>
</project>
<project>
<parent>
<groupId>com.acme</groupId>
<artifactId>parent</artifactId>
<version>0.0.0</version>
<path>../../pom.xml</path>
</parent>
</project>
@aalmiray
STANDARD (GRADLE)
.
├── build.gradle
├── guide
│ └── build.gradle
├── project1
│ └── build.gradle
├── project2
│ └── build.gradle
└── settings.gradle
.
├── build.gradle
├── guide
│ └── guide.gradle
├── project1
│ └── project1.gradle
├── project2
│ └── project2.gradle
└── settings.gradle
@aalmiray
STANDARD (GRADLE)
$ cat settings.gradle
include 'guide'
include 'project1'
include 'project2'
$ cat settings.gradle
include 'guide'
include 'project1'
include 'project2’
project(':guide').buildFileName =
'guide.gradle'
project(':project1').buildFileName =
'project1.gradle'
project(':project2').buildFileName =
'project2.gradle'
@aalmiray
STANDARD (GRADLE)
$ cat settings.gradle
buildscript {
repositories {
gradlePluginPortal()
}
dependencies {
classpath 'org.kordamp.gradle:settings-gradle-plugin:0.15.0
}
}
apply plugin: 'org.kordamp.gradle.settings'
projects {
layout = 'standard'
}
@aalmiray
TWO-LEVEL (GRADLE)
.
├── build.gradle
├── docs
│ └── guide
│ └── build.gradle
└── subprojects
├── project1
│ └── build.gradle
└── project2
└── build.gradle
.
├── build.gradle
├── docs
│ └── guide
│ └── guide.gradle
└── subprojects
├── project1
│ └── project1.gradle
└── project2
└── project2.gradle
@aalmiray
TWO-LEVEL (GRADLE)
$ cat settings.gradle
include 'guide'
include 'project1'
include 'project2'
project(':guide').projectDir =
new File(“$settingsDir/docs/guide”)
project(':project1').projectDir =
new File(“$settingsDir/subprojects/project1”)
project(':project2').projectDir =
new File(“$settingsDir/subprojects/project2”)
@aalmiray
TWO-LEVEL (GRADLE)
$ cat settings.gradle
buildscript {
repositories {
gradlePluginPortal()
}
dependencies {
classpath 'org.kordamp.gradle:settings-gradle-plugin:0.15.0
}
}
apply plugin: 'org.kordamp.gradle.settings'
projects {
layout = 'two-level'
directories = ['docs', 'subprojects']
}
@aalmiray
MULTI-LEVEL (GRADLE)
.
├── build.gradle
├── guide
│ └── build.gradle
└── subprojects
├── project1
│ └── build.gradle
└── project2
└── build.gradle
.
├── build.gradle
├── guide
│ └── guide.gradle
└── subprojects
├── project1
│ └── project1.gradle
└── project2
└── project2.gradle
@aalmiray
MULTI-LEVEL (GRADLE)
$ cat settings.gradle
buildscript {
repositories {
gradlePluginPortal()
}
dependencies {
classpath 'org.kordamp.gradle:settings-gradle-plugin:0.15.0
}
}
apply plugin: 'org.kordamp.gradle.settings'
projects {
layout = 'multi-level'
directories = [
'guide',
'subprojects/project1',
'subprojects/project2'
]
}
PROJECT
DSL
@aalmiray
THE PROJECT PLUGIN
plugins {
id 'org.kordamp.gradle.project' version ‘0.15.0’
}
config {
release = (rootProject.findProperty('release') ?: false).toBoolean()
info {
name = 'Sample'
vendor = 'Acme'
description = 'Sample project'
links {
website = 'https://github.com/joecool/sample'
issueTracker = 'https://github.com/joecool/sample/issues'
scm = 'https://github.com/joecool/sample.git'
}
people {
person {
id = 'joecool'
name = 'Joe Cool'
roles = ['developer']
}
}
}
…
}
@aalmiray
PROVIDED BEHAVIOR
• The project plugin applies the following plugins
• org.kordamp.gradle.base
• org.kordamp.gradle.build-info
• org.kordamp.gradle.minpom
• org.kordamp.gradle.jar
• org.kordamp.gradle.source-jar
• org.kordamp.gradle.javadoc
• org.kordamp.gradle.license
• org.kordamp.gradle.jacoco
• org.kordamp.gradle.publishing
• org.kordamp.gradle.testing
• org.kordamp.gradle.apidoc
• org.kordamp.gradle.source-stats
• org.kordamp.gradle.source-html
• org.kordamp.gradle.bintray
ORG.KORDAMP.GRADLE.BASE
@aalmiray
DEFAULT TASKS
• Gradle provides the following tasks
• projects
• dependencies
• properties
• tasks
@aalmiray
ADDITIONAL TASKS
• The base plugin provides the following tasks
• extensions
• plugins
• repositories
• projectProperties
• effectiveSettings
@aalmiray
@aalmiray
@aalmiray
ORG.KORDAMP.GRADLE.BUILD-INFO
@aalmiray
BUILD-INFO
• The build-info plugin calculates build data such as
• Build date
• Build time
• Build creator
• SCM revision (git commit hash)
• Build JDK
• This information is used to enrich JAR manifests
@aalmiray
JAR MANIFEST EXAMPLE
Manifest-Version: 1.0
Created-By: Gradle 5.2
Build-By: aalmiray
Build-Jdk: 11 (Oracle Corporation 11+28)
Build-Date: 2019-03-22
Build-Time: 06:59:24.924+0100
Build-Revision: 6604da6d0d79f75c72c812f5017cb8d9bb383fb3
ORG.KORDAMP.GRADLE.MINPOM
@aalmiray
MINPOM
• Generates additional metafiles for Maven compatibility
• META-INF/maven/${project.group}/pom.properties
• META-INF/maven/${project.group}/pom.xml
ORG.KORDAMP.GRADLE.JAR
@aalmiray
JAR
• Includes files generated by minpom plugin
• Enriches JAR manifest with data from build-info
ORG.KORDAMP.GRADLE.SOURCE-JAR
@aalmiray
SOURCE-JAR
• Generates a JAR file with project sources.
• Adds the following tasks
• sourceJar
• artifact is automatically added for publication
• aggregateSourceJar
ORG.KORDAMP.GRADLE.JAVADOC
@aalmiray
JAVADOC
• Configures Javadoc generation with sensible defaults.
• Adds the following tasks
• javadoc
• javadocJar
• artifact is automatically added for publication
ORG.KORDAMP.GRADLE.GROOVYDOC
@aalmiray
GROOVYDOC
• Configures Groovydoc generation with sensible defaults.
• Adds the following tasks
• groovydoc
• groovydocJar
• artifact is automatically added for publication
ORG.KORDAMP.GRADLE.APIDOC
@aalmiray
APIDOC
• Configures aggregate doc tasks at root level.
• Adds the following tasks
• aggregateJavadocs
• aggregateJavadocsJar
• aggregateGroovydocs
• aggregateGroovyDocsJar
• aggregateApidocs
ORG.KORDAMP.GRADLE.LICENSE
@aalmiray
LICENSE
• Configures license reports and file header formatting with
com.github.hierynomus.license
• Adds the following tasks
• aggregateLicenseReport
ORG.KORDAMP.GRADLE.JACOCO
@aalmiray
JACOCO
• Configures JaCoCo on all Test tasks.
• Adds the following tasks
• jacoco<Test>Report
• jacocoRootMerge
• jacocoRootReport
ORG.KORDAMP.GRADLE.SOURCE-HTML
@aalmiray
SOURCE-HTML
• Configures pretty printed API documentation using Java2Html.
• Adds the following tasks
• convertCodeToHtml
• generateSourceHtmlOverview
• sourceHtml
• aggregateConvertCodeToHtml
• aggregateGenerateSourceHtmlOverview
• aggregateSourceHtml
ORG.KORDAMP.GRADLE.SOURCE-STATS
@aalmiray
SOURCE-STATS
• Generates source statistics based on file types and LOC.
• Adds the following tasks
• sourceStats
• aggregateSourceStats
@aalmiray
SOURCE-STATS
> Task :base-gradle-plugin:sourceStats
+------------------------+--------+--------+
| Name | Files | LOC |
+------------------------+--------+--------+
| Groovy Sources | 55 | 5462 |
| Groovy Test Sources | 1 | 102 |
| Java Sources | 4 | 43 |
+------------------------+--------+--------+
| Totals | 60 | 5607 |
+------------------------+--------+--------+
ORG.KORDAMP.GRADLE.TESTING
@aalmiray
TESTING
• Configures quick feedback test reports.
• Adds the following tasks
• aggregateTestReports
• aggregateIntegrationTestReports
• aggregateFunctionalTestReports
• aggregateAllTestReports
@aalmiray
ORG.KORDAMP.GRADLE.PUBLISHING
@aalmiray
PUBLISHING
• Configures publication of main artifact, including source,
javadoc, groovydoc, kotlindoc, scaladoc.
• Configures POM based on data from base & license plugins
• Artifacts may be optionally signed.
• Publication can be deployed to Maven compatible repositories.
ORG.KORDAMP.GRADLE.BINTRAY
@aalmiray
BINTRAY
• Configures publication to Bintray based on data provided by
base, license, and bintray DSL blocks.
• Can push automatically to Maven Central.
• Publishes all artifacts registered by publishing plugin.
@aalmiray
ADDITIONAL PLUGINS
• The following plugins can be applied explicitly
• org.kordamp.gradle.kotlindoc
• org.kordamp.gradle.scaladoc
• org.kordamp.gradle.source-xref
• org.kordamp.gradle.bom
• org.kordamp.gradle.clirr
• org.kordamp.gradle.guide
• org.kordamp.gradle.integration-test
• org.kordamp.gradle.functional-test
SUPER POM
@aalmiray
THE MAVEN SUPER POM
• POMs are hierarchical.
• The chain resolves all the way to the top where you find the
Maven Super POM.
• Super POM configures lots of default & useful behavior.
@aalmiray
THE GRADLE SUPER POM
• Gradle does not offer this behavior out of the box.
• But it can be “faked” using a custom plugin.
• The plugin applies the default behavior that consuming
projects require.
GRADLE
SUPER POM
DEMO
BUILD-SCANS
@aalmiray
X-RAY YOUR BUILDS
• Capture build data on the go.
• Analyze problems on the spot.
• Deep linking enables better sharing.
• Works for both Maven and Gradle.
@aalmiray
https://scans.gradle.com/s/nde2zxpa4xb5w
@aalmiray
https://gradle.com/s/sr5y2ufwamkb2
@aalmiray
@aalmiray
HTTP://ANDRESALMIRAY.COM/NEWSLETTER
HTTP://ANDRESALMIRAY.COM/EDITORIAL
@aalmiray
THANK YOU!
ANDRES ALMIRAY
@AALMIRAY

Gradle ex-machina