lightweight developer provisioning with gradle and seu as-code
TRANSCRIPT
![Page 1: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/1.jpg)
Lightweight Developer
Provisioning with Gradle
and SEU-as-code| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 1
![Page 2: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/2.jpg)
About me
Mario-Leander ReimerChief Technologist, QAware [email protected]
twitter://@LeanderReimerhttp://speakerdeck.com/lreimerhttp://github.com/lreimerhttp://github.com/seu-as-codehttp://seu-as-code.iohttp://www.qaware.de
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 2
![Page 3: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/3.jpg)
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 3
![Page 4: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/4.jpg)
SEU: a German acronym;software development environment
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 4
![Page 5: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/5.jpg)
Definition of Software Industrialization
• This has nothing to do with cheap labor!
• Automation of repetitive and laborious tasks
• Better software quality through standardized, streamlined tooling
• Well integrated tool chain leads to a higher productivity and happiness of your team
• Better cost efficiency and competitiveness
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 5
![Page 6: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/6.jpg)
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 6
![Page 7: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/7.jpg)
The ideal.
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 7
![Page 8: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/8.jpg)
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 8
![Page 9: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/9.jpg)
The reality?
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 9
![Page 10: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/10.jpg)
What are the problems?
• Manual and error prone creation and update procedure of individual SEUs
• Individual SEUs produce different results and strange bugs
• Old versions of a SEU can't easily be restored
• The SEU for a new project is often a copy of a
previous project. ! Broken windows! !
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 10
![Page 11: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/11.jpg)
The solution ...
• Use a build tool for the automated creation and update of a SEU
• Software packages are expressed as dependencies
• Gradle tasks and Groovy are used instead of shell scripting
• Everything is version controlled just like ordinary source code
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 11
![Page 12: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/12.jpg)
Demo.
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 12
![Page 13: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/13.jpg)
The most minimalistic SEU
plugins { id 'de.qaware.seu.as.code.base' version '2.4.0'}
seuAsCode { seuHome = 'J:' projectName = 'JavaOne 2016'}
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 13
![Page 14: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/14.jpg)
Multi platform SEUs for mixed teams
plugins { id 'de.qaware.seu.as.code.base' version '2.4.0'}
import static de.qaware.seu.as.code.plugins.base.Platform.isMac
seuAsCode { // use closure or Elvis operator (no syntax highlighting :( seuHome = { if (isMac()) '/Volumes/JavaOne-2016' else 'J:' } projectName = 'JavaOne 2016'}
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 14
![Page 15: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/15.jpg)
Software packages are dependencies
• Gradle has built-in support for dependencies
• Gradle supports different artifact repositories (Maven, Ivy, Directory)
• Transitive dependencies between software packages are supported
• Use dependency configurations to determine installation directory
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 15
![Page 16: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/16.jpg)
Software dependencies and configurations
repositories {
maven { url 'https://dl.bintray.com/seu-as-code/maven' }
jcenter()
}
dependencies {
seuac 'org.codehaus.groovy.modules.scriptom:scriptom:1.6.0'
seuac 'com.h2database:h2:1.4.188'
home 'de.qaware.seu.as.code:seuac-home:2.4.0'
software 'de.qaware.seu.as.code:seuac-environment:2.4.0:jdk8'
software 'org.gradle:gradle:2.14.1'
software "net.java:openjdk8:8u40:$osClassifier"
}
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 16
![Page 17: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/17.jpg)
Secure passwords with Credentials plugin
plugins { id 'de.qaware.seu.as.code.credentials' version '2.4.0' }
repositories {
maven {
url 'https://your.company.com/nexus/repo'
credentials {
// access stored credentials via extra property
username project.credentials['Nexus'].username
password project.credentials['Nexus'].password
}
}
}
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 17
![Page 18: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/18.jpg)
Platform plugin for OS specific builds
plugins { id 'de.qaware.seu.as.code.platform' version '1.0.0' }
platform { win { task helloSeuAsCode(group: 'Example') << { println 'Hello SEU-as-code on Windows.' } } mac { task helloSeuAsCode(group: 'Example') << { println 'Hello SEU-as-code on MacOS.' } }}
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 18
![Page 19: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/19.jpg)
Manage sources with Git or SVN plugin
plugins { id 'de.qaware.seu.as.code.credentials' version '2.4.0' id 'de.qaware.seu.as.code.git' version '2.3.0'}
git { plugins { url 'https://github.com/seu-as-code/seu-as-code.plugins.git' directory file("$seuHome/codebase/plugins/") username project.credentials['Github'].username password project.credentials['Github'].password }}
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 19
![Page 20: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/20.jpg)
Manage sources with Git or SVN plugin
plugins { id 'de.qaware.seu.as.code.credentials' version '2.4.0' id 'de.qaware.seu.as.code.svn' version '2.1.1'}
subversion { usersGuide { url 'https://github.com/seu-as-code/seu-as-code.users-guide.git' directory file("$seuHome/docbase/users-guide/") username project.credentials['Subversion'].username password project.credentials['Subversion'].password }}
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 20
![Page 21: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/21.jpg)
Implement scripts using plain Gradle
• Gradle build scripts are code! Be creative.
• Gradle provides useful predefined tasks: Copy, Exec, Sync, Delete, ...
• Gradle tasks can easily reuse Ant tasks.
• Gradle tasks can be implemented in Groovy code.
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 21
![Page 22: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/22.jpg)
Example 1: Init and delete Derby DB
ext.derbyHome = System.env['DERBY_HOME']
// import SQL file via the provided Derby command line tooltask initDemoDb(type: Exec, group: 'Database') { workingDir "$derbyHome/bin" commandLine 'cmd', '/B', '/C', 'ij.bat', "$rootDir/scripts/init.sql"}
task deleteDemoDb(type: Delete, group: 'Database') { delete "$derbyHome/demo"}
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 22
![Page 23: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/23.jpg)
Example 1: The Groovy SQL way
import groovy.sql.*
task initDemoDb(group: 'Database') << {
def derby = [
url: 'jdbc:derby://localhost:1527/demo;create=true',
driver: 'org.apache.derby.jdbc.ClientDriver',
user: 'admin',
password: 'secret'
]
Sql.withInstance(derby) {
execute file("$rootDir/scripts/database/init.sql").text
}
}
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 23
![Page 24: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/24.jpg)
Example 2: Restore Solr index data
ext.cores = ['de_DE', 'en_GB', 'zh_CN']
task solrRestoreAll(group: 'Solr') { }
cores.each { coreName -> def name = coreName.replaceAll("_", "").capitalize()
task "solrRestore${name}"(type: Sync, group: 'Solr') { from zipTree("$rootDir/scripts/solr/${coreName}.zip") into "$seuHome/software/solr-4.7.2/example/solr/${coreName}" }
solrRestoreAll.dependsOn "solrRestore${name}"}
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 24
![Page 25: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/25.jpg)
Don't use shell scripts. Use
Gradle instead!
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 25
![Page 26: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/26.jpg)
Building software packages is easy
• Software packages are essentially plain JAR files (software + customizations)
• 26 packages available via a Bintray repository https://bintray.com/seu-as-code/maven
• 44 package build blue-prints are available at Github, continuously growing.
• Software packages can be build with Gradle!
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 26
![Page 27: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/27.jpg)
Let's build our first package using Gradle!
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 27
![Page 28: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/28.jpg)
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 28
![Page 29: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/29.jpg)
Download the original binary distribution
plugins {
id 'de.undercouch.download' version '1.2'
}
import de.undercouch.gradle.tasks.download.Download
task downloadArchive(type: Download) {
src 'https://services.gradle.org/distributions/gradle-3.0-all.zip'
dest "$buildDir"
}
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 29
![Page 30: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/30.jpg)
Unpack archive using simple Gradle task
task extractArchive(type: Copy, dependsOn: downloadArchive) { from { zipTree("$buildDir/${project.name}-${version}-all.zip") } into "$buildDir/files"}
// Best practice: directory name matches the package name// optionally rename the extracted directory if required
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 30
![Page 31: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/31.jpg)
Customize with additional files and hooks
// plain Groovy, place as a file under META-INF/hooks/
import org.codehaus.groovy.scriptom.*
Scriptom.inApartment{ def wshShell = new ActiveXObject("WScript.Shell") def shortcut = wshShell.CreateShortcut("$seuHome\\gradle.lnk") shortcut.TargetPath = "${seuLayout.software}\\go-gradle.bat" shortcut.WorkingDirectory = "${seuLayout.codebase}" shortcut.Save()}
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 31
![Page 32: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/32.jpg)
Repackage all files as a normal JAR file
task buildPackage(type: Jar, dependsOn: extractArchive) { baseName project.name version version extension 'jar' // classifier 'x86' destinationDir buildDir from "$buildDir/files" // the extracted files from "files" // some extra files}
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 32
![Page 33: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/33.jpg)
Publish JAR artifact to a repository server
publishing {
publications {
gradle(MavenPublication) {
artifact "${buildDir}/${project.name}-${version}.jar"
}
}
repositories {
maven {
// alternatively, use your private company repository server
url 'https://bintray.com/seu-as-code/maven'
credentials { ... }
}
}
}
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 33
![Page 34: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/34.jpg)
What's next?
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 34
![Page 35: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/35.jpg)
More features to come ...
• Continuously add more software packages
• Create plugin to build software packages
• Support for self-downloading packages
• Add support for other package managers
• Add Vault support for Credentials plugin
• Improve documentation and user’s guide
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 35
![Page 36: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/36.jpg)
Star SEU-as-code on Github!
$ git clone https://github.com/seu-as-code/seu-as-code.archetype.git
$ git clone https://github.com/seu-as-code/seu-as-code.plugins.git
$ git clone https://github.com/seu-as-code/seu-as-code.packages.git
$ git clone https://github.com/seu-as-code/seu-as-code.examples.git
$ git clone https://github.com/seu-as-code/seu-as-code.documentation.git
$ git clone https://github.com/seu-as-code/seu-as-code.users-guide.git
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 36
![Page 37: Lightweight developer provisioning with gradle and seu as-code](https://reader031.vdocuments.us/reader031/viewer/2022030305/58720ddd1a28ab176b8b7e31/html5/thumbnails/37.jpg)
Q & A
| JavaOne 2016 | task seuAsCode() << { println "created with ❤ and ☕ by @LeanderReimer" } 37