GRADLE Grégory Boissinot Présentation Gradle 1 • Consultant et formateur chez Zenika • Mes spécialités – Ant/Ivy – Maven – Gradle – Hudson • Contributeur Hudson • Introduction et mis en place de Gradle chez un très grand compte industriel Présentation Gradle 2 • Système de build pour la JVM Java, focalisé sur le build des applications d'entreprise • Modèle de description du build très riche à travers une API • Flexible à la Ant avec les conventions de Maven à la demande • Une gestion avancée d'un projet multi-modules • Support et insertion totale dans des infrastructures Maven et Ant/Ivy existantes Présentation Gradle 3 1ère génération 2000 2ème génération 2005 3ème génération 2008 2 3 1 Présentation Gradle 4 <!–- ANT -- build.xml --> <project> <property name="version" value="1.0"/> <target name="antTask> <echo message="Hello"/> </target> </project> <!–- MAVEN – pom.xml--> <?xml version="1.0" encoding="UTF-8"?> <project> <modelVersion>4.0.0</modelVersion> <groupId>com.zenika</groupId> <artifactId>zenikac-core</artifactId> <version>1.0</version> <dependencies> <!–- GRADLE– build.gradle --> <dependency> apply plugin:'java' <groupId>org.apache.wicket</groupId> <artifactId>wicket</artifactId> repositories { <version>1.4.7</version> mavenCental() <scope>compile</scope> flatDir(dirs:'lib') </dependency> } </dependencies> </project> dependencies { compile "org.apache.wicket:wicket:1.4.7" } Présentation Gradle 5 Distribution Gradle CORE UI WRAPPER OPEN-API DOCS api java groovy maven osgi war jetty scala eclipse code-quality project-reports plugins Ant Ivy Maven Ant Tasks Groovy outils checkstyle codeNarc webdav Autres dépendances Librairies tierces Présentation Gradle 6 Écrire un script Gradle consiste à configurer un objet Gradle Project configurations repositories dependencies build.gradle Project ant artifacts task API Présentation Gradle 7 Un script de build Gradle est défini par un ensemble de tâches sur lesquelles sont ajoutées des actions qui sont des closures Groovy <!-- build.gradle --> task(hello) hello.doFirst{ println "Hello World" for (int i:[1,2,3]){ print i } } > gradle hello :hello Hello World 123 task(distribution).doFirst { println "Print Distribution" } task(release) release.dependsOn(distribution) release.doFirst{ println "Print Release" } Présentation Gradle > gradle distribution :distribution Print Distribution > gradle release :distribution Print Distribution :release Print Release 8 task mycopy (type:Copy){ from(file('resources')) into(file('target')) include('**/*.txt', '**/*.xml') } myCopy.include('**/*.properties') ConventionTask SourceTask Javadoc AbstractCopyTask AbstractArchiveTask Copy Zip public class Copy extends AbstractCopyTask { public AbstractCopyTask from(Object... sourcePaths); public AbstractCopyTask into(Object destDir); } Tar Jar War Présentation Gradle 9 <!– HelloTask.groovy --> class HelloTask extends DefaultTask { def message="Default Message" } @TaskAction public void print(){ println message } > gradle myhello :myhello Default Message > gradle myhello2 :myhello2 Task Message <!-- build.gradle --> task(myhello, type:HelloTask) task(myhello2, type:HelloTask){ message="Task Message" } Présentation Gradle 10 ant { def wsdl2java_classpath = path { fileset(dirs:'lib', includes: '*.jar') } taskdef( name: 'axiswsdl2java', classname: 'org.apache.axis.tools.ant.wsdl.Wsdl2javaAntTask', classpath: wsdl2java_classpath ) } axiswsdl2java( output:"generated", verbose:"true" , url:"Exemple.wsdl" ) ant.echo (message:ANT) Présentation Gradle 11 build.xml build.gradle <project> <target name="antTask"> <echo message="Hello from Ant"/> </target> </project> ant.importBuild('build.xml') antTask.doLast { println('Hello from Gradle') } > gradle antTask :antTask Hello from Ant Hello from Gradle Présentation Gradle 12 import org.junit.Assert task myzip (type:Zip) { from 'somedir' include '*.txt' baseName='zipname' doLast { Assert.assertEquals('zipname.zip', myzip.archiveName) Assert.assertEquals(file('build/distributions'), myzip.destinationDir) Assert.assertTrue( ! zipTree(myzip.archivePath).isEmpty()) ziptxtfiles=zipTree(myzip.archivePath).matching{ include('*.txt') } txtfiles=fileTree('somedir').include('*.txt') Assert.assertEquals ( txtfiles.getFiles().size(), ziptxtfiles.getFiles().size()) } } Présentation Gradle 13 Chaque plugin déclaré apporte un ensemble de tâches et de propriétés CORE UI WRAPPER OPEN-API DOCS api java groovy maven osgi war jetty scala eclipse code-quality project-reports plugins Ant Ivy Maven Ant Tasks Groovy outils Présentation Gradle 14 apply plugin:'java' repositories { mavenCental() flatDir(dirs:'destrepo', name:'ivyrep’) } dependencies { compile "jdom:jdom:1.0", ":qtjambi:4.5.2_01" testCompile "junit:junit:4.7" } > gradle clean build :clean :compileJava :processResources :classes :jar :assemble :compileTestJava :processTestResources :testClasses :test :check :build myLib .jar BUILD SUCCESSFUL Total time: 2.937 secs Présentation Gradle 15 apply plugin:'war' processResources.enabled=false //Add behavior in the lifecycle task(preJar) jar.dependsOn preJar //Predicate test.onlyIf{ !project.hasProperty('skipTests') } //Change the output directory buildDirName='target' //Change the source directory sourceSets{ main{ java.srcDir file('src/main') } } Présentation Gradle > gradle build -PskipTest :compileJava :processResources SKIPPED :classes :preJar :jar :war :assemble :compileTestJava :processTestResources :testClasses :test SKIPPED :check :build BUILD SUCCESSFUL Total time: 2.937 secs 16 Soyez informé de tous les événements de votre chaîne de build class MyTestListener implements TestListener{ void beforeSuite(TestDescriptor suite) { println('suiteStarting: '+suite.getName()) } void afterSuite(TestDescriptor suite, TestResult result) { println 'suiteFinished: '+suite.getName() } void beforeTest(TestDescriptor test) { println 'testStarting: '+test.getName() } } void afterTest(TestDescriptor test, TestResult result) { println 'testFinished: '+test.getName() +', result: '+result.getResultType() } Présentation Gradle 17 <!-- settings.gradle --> include 'api', 'shared', 'services:webservices' <!–- build.gradle --> version='1.0' subprojects { apply plugin: 'java' } project(':api') { dependencies { compile project(':shared') } } <!–- webservices/build.gradle --> apply plugin:'war' dependencies { compile project(':shared'), project(':api'), 'commons-io:commons-io:1.2' } shared webservices api api > gradle buildNeeded :shared:jar :api:jar :api:test :shared:test api > gradle buildDependents :shared:jar :api:jar :api:test :webservices:war :webservices:test Présentation Gradle 18 apply plugin:'java' repositories { mavenCental() flatDir(dirs:'destrepo', name:'ivyrep’) } IVY group='test' version='1.0' status='release' > gradle uploadArchives uploadArchives { repositories { add(repositories.ivyrep) } } Repository Ivy distant Artifacts + meta Ivy Présentation Gradle 19 apply plugin:'java' apply plugin:'maven' Maven Ant Tasks group='test' version='1.0-SNAPSHOT' uploadArchives { repositories { mavenDeployer { repository( url: remoteRepo) } } } > gradle install Repository Maven Artifacts + Local meta Maven Présentation Gradle > gradle uploadArchives Repository Maven distant Artifacts + meta Maven 20 • Amélioration constante de la DSL pour encore plus de richesse et de simplicité • Support amélioré dans les IDE • Une abstraction de Ivy pour encore un gestionnaire de dépendance plus avancé • Parallélisation/Distribution des builds • Réutilisation des plugins Maven et import de projets Maven • Simplification dans la phase de publication des artefacts Présentation Gradle 21 gmock spcok Présentation Gradle 22 • Gradle vous offre toute la richesse pour exprimer vos chaines de build au plus près de vos besoins • Gradle fournit une approche déclarative de premier plan • Gradle est un système de build complet et alternatif pour builder vos applications • Gradle s'insère nativement en lecture et en écriture dans votre existant pour l'enrichir Présentation Gradle 23