GRADLE
                                 Grégory BOISSINOT
                                      (@gboissinot)
                                       14/06/2012




 LavaJUG - Présentation Gradle                        1
•  Architecte Zenika
     – Consultant
     – Formateur
     – Spécialiste sur l'univers de l'usine logicielle

•  Committer Jenkins
    – > 40 plugins
        Grade, xUnit, EnvInject, xTrigger (FSTrigger, URLTrigger,
        ScriptTrigger, ...), BuildContextCapture
        Intégration des outils pour le C++, ADA and .NET

•  Contributor Gradle
    – Conférences
    – Articles
    – Utilisateur Gradle depuis Gradle 0.4

                                 LavaJUG - Présentation Gradle      2
Build
         et
Intégration continue



     LavaJUG - Présentation Gradle   3
•  Transformation d'une production humaine (le code
   source) en une représentation machine (le binaire)




  Fichier                                                        JAR
  Source
                        Build Tool                                 Fichier
                                                                   Binaire
                                                                             JVM


println "Hello World"                       A;^A^@^Am^A^@^T()Ljava/lang/Object;^C^
for (int i:[1,2,3]){                        @^@^@^@^A^@^KHello World^H^@2^A^@-
  print i                                   org/codehaus/groovy/runtime/callsite/
}                                           CallSite^G^@4^A^@^KcallCurrent^A^@@
                                            (Lgroovy/lang/GroovyObject;
                                            Ljava/lang/Object;)Ljava/lang/Object;
                                            ^L^@6^@7^K^@5^@8^C^@^@^@^A^L^@^H^
                                            ....
                           LavaJUG - Présentation Gradle                             4
INTERNET
Event




              Polling




        SVN

        GIT

        ...




                   LavaJUG - Présentation Gradle              5
•  La nature des besoins d'automatisation changent
    Un build peut faire beaucoup plus de choses que la
    simple création d'une archive Java




•  Les besoins d'automatisation ont augmentés
   significativement ces dernières années
     •  La portée des outils existants ne couvrait pas tous les
        besoins ou partiellement
                         LavaJUG - Présentation Gradle            6
1ère génération   2ème génération                  3ème génération
    2000                   2004                           2008

                                                   2008

2001

                                                                      3



                                              2

              1

                   LavaJUG - Présentation Gradle                          7
java.net
                                Central
                                Maven


                                                                …
                                          Codehaus
                         JBoss


                                                         Artifacts +
                                                         maven meta




                     Ivy
                     Repository

                           Artifacts +
                            ivy meta
                                              Other
                                              Repository

                                                      Artifacts +
                                                     custom meta


LavaJUG - Présentation Gradle                                          8
<!–- ANT -- build.xml -->
<project>
   <target name="retrieceDeps>
                               <!–- MAVEN – pom.xml-->
     ...
                               <?xml version="1.0" encoding="UTF-8"?>
   </target>
                               <project>
   <target name="compile" ...
                                 <modelVersion>4.0.0</modelVersion>
</project>
                                 <groupId>org.lyonjug</groupId>
                                 <artifactId>maven</artifactId>
<!–- GRADLE– build.gradle -->    <version>1.0</version>
apply plugin:'java'              <dependencies>
                                   <dependency>
version=1.0                          <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(
    group:'org.apache.wicket',
    name:'wicket',
    version:'1.4.7')
}
                            LavaJUG - Présentation Gradle               9
•  Peut-on anticiper tous les besoins d'automatisation?
    – Est-ce que tous les projets sont identiques?
    – Est-ce que le besoin d'automatisation
    évolue au cours du cycle de vie du projet?

•  Souhaite-on uniformiser l'automatisation
   entre les anciens projets et les nouveaux projets ?

•  Quelles sont les compétences des personnes
    – qui vont mettre en place les processus de build?
    – qui vont maintenir les descripteurs de build?


                            LavaJUG - Présentation Gradle   10
GRADLE



LavaJUG - Présentation Gradle   11
DSL




Conventions         Flexibilité




                    LavaJUG - Présentation Gradle   12
•  Un langage de build (API)
    – A la frontière entre un langage de script et un modèle
      statique

•  Les conventions de Maven à la demande
     – Facilite l'apprentissage et la migration

•  De nombreux cycles de construction (cycle de vie)
   fournies par défaut

•  Build incrémental à tous les niveaux

•  Systèmes de plugins

                          LavaJUG - Présentation Gradle        13
•  Une réutilisation native des tâches Ant

•  Lecture et écriture dans un repository Maven (Nexus,
   Artifactory, Archiva, etc)

•  Gestion de dépendances simple, flexible et puissante
    – Des concepts et des mécanismes issus de Ivy




                         LavaJUG - Présentation Gradle    14
•  Gradle tente de résoudre les problèmes Maven suivants:
    •  Difficulté de personnalisation du cycle de vie
        •  Mauvaise granularité entre phase et plugins

   •  Gestion des dépendances difficile
       •  Non distinction des dépendances de type projet et
          de type externes
       •  Lié strictement à un pattern de version
       •  Pas de possibilité les algorithmes de résolution

   •  1 seul artefact par projet (par défaut)

   •  Difficulté de mise en place des tests d'intégration

   •  Difficulté de packaging -complexe
                          LavaJUG Présentation Gradle         15
•  Spécification du 'quoi' et pas du 'comment'
                            iture
                       Fourn le
                             yc
                       d'un c
                          de vie
                                                                              Même
                                                                                  ntion
                      > gradle clean build                                  conve en
                                                                                   av
apply plugin:'java'   :clean                                                 que M
                      :compileJava
                                                                                 src
repositories {        :processResources
}                     :classes                                      myLib              main
                      :jar                                          .jar
dependencies {                                                                                java
                      :assemble
}                     :compileTestJava                                                        resources
                      :processTestResources
                      :testClasses
                      :test                                                            test
                      :check
                                                                                              java
                      :build

                      BUILD SUCCESSFUL                                                        resources




                                    LavaJUG - Présentation Gradle                                         16
Écrire un script Gradle consiste à configurer un élément Project



                                                  configurations
build.gradle
                          repositories
                                                                    dependencies




                                  Project                                  ant



                                                                Eléments
                        task                                    personnalisés


                                          artifacts



                                                    Public
                                                     API
                                LavaJUG - Présentation Gradle                      17
apply plugin:'java'

version = 1.0
                                           API
repositories{
                                          Gradle
  mavenCentral()
}
                                            API
                                           Java/
dependencies{                             Groovy
  compile "log4j:log4j:1.2.16"
  testCompile "junit:junit:4.7"                     > gradle build
                                                    :compileJava
}                                                   :processResources
                                                    :classes
task release << {                                   :jar
  println "Release"                                 :assemble
}                                                   :compileTestJava
                                                    :processTestResources
void printMessage(String message){                  :testClasses
  println "Print " + message                        :test
                                                    :check
}                                                   :build
                         LavaJUG - Présentation Gradle                      18
apply plugin:'java'

processResources.enabled=false
test.onlyIf{
 !project.hasProperty('skipTests')}

task(preJar)                                             > gradle build –PskipTests
jar.dependsOn preJar                                     :compileJava
                                                         :processResources SKIPPED
//Change the source directory                            :classes
sourceSets{                                              :preJar
  main{                                                  :jar
                                                         :assemble
    java.srcDirs file('src/java'),                       :compileTestJava
                 file('src/java2')                       :processTestResources
  }                                                      :testClasses
}                                                        :test SKIPPED
                                                         :check
//Création d'un uberjar                                  :build
jar {
  configurations.compile.each {                          BUILD SUCCESSFUL
      from zipTree (it) }
}
                         LavaJUG - Présentation Gradle                           19
ConventionTask                                         Mise à disposition d'un ensemble
                                                        de tâches prédéfinies


 AbstractCopyTask     SourceTask

                                                                     Facile à   Facile à
                                                                     utiliser   étendre

AbstractArchiveTask     Copy                Javadoc



                                   public class Copy extends AbstractCopyTask {
                                      public AbstractCopyTask from(Object... sourcePaths);
   Zip          Tar
                                      public AbstractCopyTask into(Object destDir);
                                      public AbstractCopyTask include(String... includes);
                                      . . .
                                   }

   Jar
                                   task mycopy (type:Copy){
                                     description ='Copies the resources dir'
                                     from(file('resources'))
                                     into(file('destination'))
  War
                                     include('**/*.txt', '**/*.xml')
                                   }

                                     LavaJUG - Présentation Gradle                           20
<!– HelloTask.groovy -->
class HelloTask extends DefaultTask {

    def message="Default Message"

    @TaskAction
    public void print(){                                   > gradle myhello
      println message                                      :myhello
    }                                                      Default Message
}                                                          > gradle myhello2
                                                           :myhello2
<!-- build.gradle -->                                      Task Message

task(myhello, type:HelloTask)

task(myhello2, type:HelloTask){
   message="Task Message"
}



                           LavaJUG - Présentation Gradle                       21
java                  Java Configuration
                                Object




public class JavaPluginConvention {
   public SouceSetContainer sourceSets();
   public void setSourceCompatibility(Object value);
   public void setTargetCompatibility(Object value);
   public Manifest manifest()

    . . .
}

           <!-- build.gradle -->
                                                             Facile à
           apply plugin:'java'                               mettre en
                                                                         Simple à
                                                             place et
                                                                         apprendre
                                                              facile à
           sourceCompatibility = 1.6                         maintenir
           targetCompatibility = 1.6


                             LavaJUG - Présentation Gradle                           22
LavaJUG - Présentation Gradle   23
CONFIGURATION PHASE

                                t1        t2        t3
                                                                            t1           t2    t3




                                                                                                    EXECUTION PHASE
GRADLE                               t4
                                                                                    t4




                                                               HOOK
SCRIPT


                                       Project                                        Project                         Engine
                                     Convention 1                                   Convention 2




gradle   properties                                 gradle.taskGraph.whenReady { taskGraph ->
gradle   tasks                                        if (taskGraph.hasTask(':release')){
gradle   dependencies                                       status = 'release'
gradle   –-dry-run build                              }
                                                    }

                                                    // Other hooks
                                                    gradle.taskGraph.beforeTask { task -> .. .
                                                    gradle.beforeProject { project -> .. .
                                                    ...
                                                    LavaJUG - Présentation Gradle                                              24
Soyez informé des événements: TestListener,
     BuildListener, TaskActionListener, …

class MyTestListener implements TestListener{
                                                                       beforeTest
    void beforeTest(TestDescriptor test) {




                                                              GRADLE
      println 'testStarting: '+test.getName()
    }                                                                   Test
                                                                          (junit)
    void afterTest(TestDescriptor test,
                   TestResult result) {
      println 'testFinished: '+test.getName()                          afterTest
           +', result: '+result.getResultType()
    }
}




                              LavaJUG - Présentation Gradle                         25
Les scripts d'initialisation permettent d'invoquer différents
 listeners au chargement du script

//Script d'initialisation

addListener(new ApplyEclipsePlugin())

class ApplyEclipsePlugin extends BuildAdapter {                  Invoquer
                                                               par défaut
    public void projectsEvaluated(Gradle gradle){                 si placé
                                                                  dans le
      gradle.rootProject.allprojects {                           home de
          apply plugin:'eclipse'                               l'utilisateur
      }
    }
}


gradle eclipse –I init.gradle



                               LavaJUG - Présentation Gradle                   26
import org.junit.Assert
                                                                  > gradle myzip
task myzip (type:Zip) {                                           :myzip
  from('somedir')
  include('*.txt')
  baseName='zipname'
  doLast {
   Assert.assertEquals('zipname.zip',
                         myzip.archiveName)                        createZip
   Assert.assertEquals(file('build/distributions'),
                        myzip.destinationDir)

        Assert.assertTrue(                                                     zipname
                                                                               .zip
                 !zipTree(myzip.archivePath).isEmpty())

        txtfiles = fileTree('somedir').include('*.txt')
                                                                    check
        ziptxtfiles=zipTree(myzip.archivePath).matching{
                include('*.txt')
              }
        Assert.assertEquals (
              txtfiles.getFiles().size(),                         BUILD SUCCESSFUL
              ziptxtfiles.getFiles().size())                      >
    }
}




                                  LavaJUG - Présentation Gradle                          27
LavaJUG - Présentation Gradle   28
task generateTask(dependsOn:preSchemaGen) << {
  ant.echo (message:"Generating ...")
  ant {
     def schemagenTaskPath = path {
       fileset(dirs:'lib', includes: '*.jar')
     }
     taskdef (
       name: "xjc", classname: "com.sun.tools.xjc.XJCTask",
       classpath: schemagenTaskPath
     )
     xjc(destdir:generatedSources,
         package:"com.zenika.lib.model"){
           schema(dir:"src/main/resources", includes:"**/*.xsd")
     }
   }
}




                        LavaJUG - Présentation Gradle          29
build.xml
                 <project>
                   <target name="antTarget">
                     <echo message="Hello from Ant"/>
                   </target>
                 </project>



 build.gradle
                 ant.importBuild('build.xml')
                 antTarget.doLast {
                    println('Hello from Gradle')
                 }



> gradle antTarget
:antTarget
Hello from Ant
Hello from Gradle

                LavaJUG - Présentation Gradle           30
apply plugin:'java'

repositories {
  mavenCental()
  flatDir(dirs:'destrepo',                                  IVY
          name:'ivyrep’)
}

group='com.zenika.gradledemos'                                > gradle uploadArchives
version='1.0'
status='release'

uploadArchives {
  repositories {
    add(repositories.ivyrep)
  }
}                                                        Repository
                                                         Ivy
                                                         distant
                                                                      Artifacts +
                                                                       meta Ivy



                         LavaJUG - Présentation Gradle                                  31
apply plugin:'java'
apply plugin:'maven'                                        Maven
                                                             Ant
group='test'                                                Tasks
version='1.0-SNAPSHOT'

uploadArchives {
  repositories {
    mavenDeployer {
      repository(                           > gradle           > gradle
                                              install            uploadArchives
         url: remoteRepo)
    }
  }
}



                                Repository                   Repository
                                Maven                        Maven
                                Local      Artifacts +       distant
                                                                          Artifacts +
                                               meta Maven
                                                                          meta Maven


                            LavaJUG - Présentation Gradle                               32
• Gestion avancée d'un multi projet

• Utilisation d'un cache

• Exécution parallèle des tests

• Build daemon


                    LavaJUG - Présentation Gradle   33
// settings.gradle                                                  shared
include 'api',
        'shared',
        'services:webservices'
                                                           webservices       api
// root build.gradle
subprojects {                                 api > gradle buildNeeded
  apply plugin: 'java'                        :shared:jar
}                                             :api:jar
project(':api') {                             :api:test
  dependencies {                              :shared:test
    compile project(':shared')
  }
}                                             api > gradle buildDependents
                                              :shared:jar
                                              :api:jar
// webservices/build.gradle
apply plugin:'war'                            :api:test
                                              :webservices:war
dependencies {
                                              :webservices:test
  compile
    project(':shared'),
    project(':api'),                          api > gradle jar –-no-rebuild
   'commons-io:commons-io:1.2'                api:jar
}
                           LavaJUG - Présentation Gradle                           34
1.  Le script Gradle est compilé uniquement en cas de
    changement


2.  Détection des changements pour chaque entrée et
    chaque sortie pour la plupart des tâches fournies

                         > gradle myzip
                         :myzip

                         > gradle myzip
                         :myzip UP-TO-DATE

                         > gradle myzip –-cache rebuild
                         :myzip



                       LavaJUG - Présentation Gradle      35
class GenerateSchemaType extends DefaultTask {

    String depsPath

    @InputFiles
    SourceDirectorySet inputXsdDirs

    @OutputDirectory
    File outputFile
                                      > gradle build
                                      :generateTask UP-TO-DATE
    @TaskAction                       :compileGeneratedJava UP-TO-DATE
    void generate() {                 :processGeneratedResources UP-TO-DATE
      ant { ...}                      :generatedClasses UP-TO-DATE
    }                                 :compileJava UP-TO-DATE
}                                     ...

task generateTask(type:GenerateSchemaType) {
  inputXsdDirs = sourceSets.main.resources
  outputFile = generatedSources
  depsPath = configurations.jaxb.asPath
}
                          LavaJUG - Présentation Gradle                   36
EXECUTION


                                                         Process 1                                             Process 6
                   TEST    TEST    TEST    TEST    TEST                  TEST       TEST    TEST    TEST    TEST
                  CLASS   CLASS   CLASS   CLASS   CLASS                 CLASS      CLASS   CLASS   CLASS   CLASS
PARALLELISATION




                                                         Process 2                                             Process 7
                   TEST    TEST    TEST    TEST    TEST                  TEST       TEST
                  CLASS   CLASS   CLASS   CLASS   CLASS                 CLASS      CLASS

                                                          Process 3
                   TEST    TEST    TEST    TEST    TEST
                  CLASS   CLASS   CLASS   CLASS   CLASS
                                                                          apply plugin:'java'
                                                          Process 4
                   TEST    TEST    TEST    TEST    TEST
                  CLASS   CLASS   CLASS   CLASS   CLASS                   test {
                                                                            forkEvery = 5
                                                                            maxParallelForks = 4
                                                                          }




                                                   LavaJUG - Présentation Gradle                                      37
•  Utilisation d'un processus parallèle pour éviter le cout de
   lancement
             > gradle build
             ...
             Total time: 3s

             > gradle build –daemon
             ...
             Total time: 3s

             > gradle build
             ...
             Total time: 1s



•  Va favoriser l'intégration de Gradle avec Gradle UI et les
   IDE (Eclipse, IDEA, ...)


                         LavaJUG - Présentation Gradle           38
IDE                               Maturité
NetBeans
Eclipse                           +
Eclipse STS                       ++
Idea IntelliJ                     ++

                LavaJUG - Présentation Gradle   39
HUDSON                         JENKINS

Fonctionnalités:
- Installation automatique de Gradle (via URL, Run Script)
- Wizard de configuration
- Utilisation possible du Gradle wrapper
- Dry-Run
- Coloration syntaxique

                          LavaJUG - Présentation Gradle      40
Environment


                                                        Instancie




                      Processus identifié (traçabilité) et répétable




                                  DEPLOY                      TEST
              BUILD                                                     RELEASE
                                  INSTALL                  VALIDATION




                                       LavaJUG - Présentation Gradle              41
gmock

                                                  security
 spock



                                         integration




                                                       4



         LavaJUG - Présentation Gradle                       42
•  Mailing List très active

•  User guide très riche (400 pages)

•  Nombreuses contributions de plugins

•  Le nombre d'articles et de conférences augmentent




                              LavaJUG - Présentation Gradle   43
LavaJUG - Présentation Gradle   44
•  Des besoins spécifiques de construction
    •  Structure de répertoires propre au projet
    •  Définition d'un cycle de vie personnalisé
    •  Plusieurs artefacts par projet

•  Des besoins spécifiques de tests
    •  Tests d'intégration complexe
    •  Tests sur plusieurs JDK
    •  Beaucoup de tests à paralléliser

•  Gestion fine des dépendances

•  Build incrémental à plusieurs niveaux

•  Définition de modèle de build (proche des concepts de Maven)
                           LavaJUG - Présentation Gradle          45
•  Comme tous les outils, un outil de build ne s'impose pas

•  Ne pas l'opposer à Maven ou à Ant mais l'utiliser comme
   complément
     •  Construction avec Gradle et déploiement dans un repo
        Maven
     •  Réutilisation des scripts Ant existants et surcharge/
        réécriture des cible Ant existantes (sans modifications
        des scripts actuels)

•  Solution parfaite pour construire son propre modèle de
   build entreprise adapté à ses besoins
    •  Gradle est utilisé comme un framework
    •  L'utilisation de Gradle est caché (GradleWrapper)

                          LavaJUG - Présentation Gradle           46
•  Utiliser Gradle comme un langage de build (API,
   réutilisabilité de modules, orientation objet, ...) et pas
   juste un langage de script de luxe

•  Cadrer les descripteurs Gradle d'un projet à un autre
    •  Des revues de code des scripts sont à prévoir
    •  Comme tout code source, le build évolue et donc est
       soumis à des refactoring réguliers
    •  Essayer d'abstraire des modèles de build réutilisables

•  Utiliser une version stable




                          LavaJUG - Présentation Gradle         47
Questions?



  LavaJUG - Présentation Gradle   48
LavaJUG - Présentation Gradle   49

gradle_lavajug

  • 1.
    GRADLE Grégory BOISSINOT (@gboissinot) 14/06/2012 LavaJUG - Présentation Gradle 1
  • 2.
    •  Architecte Zenika – Consultant – Formateur – Spécialiste sur l'univers de l'usine logicielle •  Committer Jenkins – > 40 plugins Grade, xUnit, EnvInject, xTrigger (FSTrigger, URLTrigger, ScriptTrigger, ...), BuildContextCapture Intégration des outils pour le C++, ADA and .NET •  Contributor Gradle – Conférences – Articles – Utilisateur Gradle depuis Gradle 0.4 LavaJUG - Présentation Gradle 2
  • 3.
    Build et Intégration continue LavaJUG - Présentation Gradle 3
  • 4.
    •  Transformation d'uneproduction humaine (le code source) en une représentation machine (le binaire) Fichier JAR Source Build Tool Fichier Binaire JVM println "Hello World" A;^A^@^Am^A^@^T()Ljava/lang/Object;^C^ for (int i:[1,2,3]){ @^@^@^@^A^@^KHello World^H^@2^A^@- print i org/codehaus/groovy/runtime/callsite/ } CallSite^G^@4^A^@^KcallCurrent^A^@@ (Lgroovy/lang/GroovyObject; Ljava/lang/Object;)Ljava/lang/Object; ^L^@6^@7^K^@5^@8^C^@^@^@^A^L^@^H^ .... LavaJUG - Présentation Gradle 4
  • 5.
    INTERNET Event Polling SVN GIT ... LavaJUG - Présentation Gradle 5
  • 6.
    •  La naturedes besoins d'automatisation changent Un build peut faire beaucoup plus de choses que la simple création d'une archive Java •  Les besoins d'automatisation ont augmentés significativement ces dernières années •  La portée des outils existants ne couvrait pas tous les besoins ou partiellement LavaJUG - Présentation Gradle 6
  • 7.
    1ère génération 2ème génération 3ème génération 2000 2004 2008 2008 2001 3 2 1 LavaJUG - Présentation Gradle 7
  • 8.
    java.net Central Maven … Codehaus JBoss Artifacts + maven meta Ivy Repository Artifacts + ivy meta Other Repository Artifacts + custom meta LavaJUG - Présentation Gradle 8
  • 9.
    <!–- ANT --build.xml --> <project> <target name="retrieceDeps> <!–- MAVEN – pom.xml--> ... <?xml version="1.0" encoding="UTF-8"?> </target> <project> <target name="compile" ... <modelVersion>4.0.0</modelVersion> </project> <groupId>org.lyonjug</groupId> <artifactId>maven</artifactId> <!–- GRADLE– build.gradle --> <version>1.0</version> apply plugin:'java' <dependencies> <dependency> version=1.0 <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( group:'org.apache.wicket', name:'wicket', version:'1.4.7') } LavaJUG - Présentation Gradle 9
  • 10.
    •  Peut-on anticipertous les besoins d'automatisation? – Est-ce que tous les projets sont identiques? – Est-ce que le besoin d'automatisation évolue au cours du cycle de vie du projet? •  Souhaite-on uniformiser l'automatisation entre les anciens projets et les nouveaux projets ? •  Quelles sont les compétences des personnes – qui vont mettre en place les processus de build? – qui vont maintenir les descripteurs de build? LavaJUG - Présentation Gradle 10
  • 11.
  • 12.
    DSL Conventions Flexibilité LavaJUG - Présentation Gradle 12
  • 13.
    •  Un langagede build (API) – A la frontière entre un langage de script et un modèle statique •  Les conventions de Maven à la demande – Facilite l'apprentissage et la migration •  De nombreux cycles de construction (cycle de vie) fournies par défaut •  Build incrémental à tous les niveaux •  Systèmes de plugins LavaJUG - Présentation Gradle 13
  • 14.
    •  Une réutilisationnative des tâches Ant •  Lecture et écriture dans un repository Maven (Nexus, Artifactory, Archiva, etc) •  Gestion de dépendances simple, flexible et puissante – Des concepts et des mécanismes issus de Ivy LavaJUG - Présentation Gradle 14
  • 15.
    •  Gradle tentede résoudre les problèmes Maven suivants: •  Difficulté de personnalisation du cycle de vie •  Mauvaise granularité entre phase et plugins •  Gestion des dépendances difficile •  Non distinction des dépendances de type projet et de type externes •  Lié strictement à un pattern de version •  Pas de possibilité les algorithmes de résolution •  1 seul artefact par projet (par défaut) •  Difficulté de mise en place des tests d'intégration •  Difficulté de packaging -complexe LavaJUG Présentation Gradle 15
  • 16.
    •  Spécification du'quoi' et pas du 'comment' iture Fourn le yc d'un c de vie Même ntion > gradle clean build conve en av apply plugin:'java' :clean que M :compileJava src repositories { :processResources } :classes myLib main :jar .jar dependencies { java :assemble } :compileTestJava resources :processTestResources :testClasses :test test :check java :build BUILD SUCCESSFUL resources LavaJUG - Présentation Gradle 16
  • 17.
    Écrire un scriptGradle consiste à configurer un élément Project configurations build.gradle repositories dependencies Project ant Eléments task personnalisés artifacts Public API LavaJUG - Présentation Gradle 17
  • 18.
    apply plugin:'java' version =1.0 API repositories{ Gradle mavenCentral() } API Java/ dependencies{ Groovy compile "log4j:log4j:1.2.16" testCompile "junit:junit:4.7" > gradle build :compileJava } :processResources :classes task release << { :jar println "Release" :assemble } :compileTestJava :processTestResources void printMessage(String message){ :testClasses println "Print " + message :test :check } :build LavaJUG - Présentation Gradle 18
  • 19.
    apply plugin:'java' processResources.enabled=false test.onlyIf{ !project.hasProperty('skipTests')} task(preJar) > gradle build –PskipTests jar.dependsOn preJar :compileJava :processResources SKIPPED //Change the source directory :classes sourceSets{ :preJar main{ :jar :assemble java.srcDirs file('src/java'), :compileTestJava file('src/java2') :processTestResources } :testClasses } :test SKIPPED :check //Création d'un uberjar :build jar { configurations.compile.each { BUILD SUCCESSFUL from zipTree (it) } } LavaJUG - Présentation Gradle 19
  • 20.
    ConventionTask Mise à disposition d'un ensemble de tâches prédéfinies AbstractCopyTask SourceTask Facile à Facile à utiliser étendre AbstractArchiveTask Copy Javadoc public class Copy extends AbstractCopyTask { public AbstractCopyTask from(Object... sourcePaths); Zip Tar public AbstractCopyTask into(Object destDir); public AbstractCopyTask include(String... includes); . . . } Jar task mycopy (type:Copy){ description ='Copies the resources dir' from(file('resources')) into(file('destination')) War include('**/*.txt', '**/*.xml') } LavaJUG - Présentation Gradle 20
  • 21.
    <!– HelloTask.groovy --> classHelloTask extends DefaultTask { def message="Default Message" @TaskAction public void print(){ > gradle myhello println message :myhello } Default Message } > gradle myhello2 :myhello2 <!-- build.gradle --> Task Message task(myhello, type:HelloTask) task(myhello2, type:HelloTask){ message="Task Message" } LavaJUG - Présentation Gradle 21
  • 22.
    java Java Configuration Object public class JavaPluginConvention { public SouceSetContainer sourceSets(); public void setSourceCompatibility(Object value); public void setTargetCompatibility(Object value); public Manifest manifest() . . . } <!-- build.gradle --> Facile à apply plugin:'java' mettre en Simple à place et apprendre facile à sourceCompatibility = 1.6 maintenir targetCompatibility = 1.6 LavaJUG - Présentation Gradle 22
  • 23.
  • 24.
    CONFIGURATION PHASE t1 t2 t3 t1 t2 t3 EXECUTION PHASE GRADLE t4 t4 HOOK SCRIPT Project Project Engine Convention 1 Convention 2 gradle properties gradle.taskGraph.whenReady { taskGraph -> gradle tasks if (taskGraph.hasTask(':release')){ gradle dependencies status = 'release' gradle –-dry-run build } } // Other hooks gradle.taskGraph.beforeTask { task -> .. . gradle.beforeProject { project -> .. . ... LavaJUG - Présentation Gradle 24
  • 25.
    Soyez informé desévénements: TestListener, BuildListener, TaskActionListener, … class MyTestListener implements TestListener{ beforeTest void beforeTest(TestDescriptor test) { GRADLE println 'testStarting: '+test.getName() } Test (junit) void afterTest(TestDescriptor test, TestResult result) { println 'testFinished: '+test.getName() afterTest +', result: '+result.getResultType() } } LavaJUG - Présentation Gradle 25
  • 26.
    Les scripts d'initialisationpermettent d'invoquer différents listeners au chargement du script //Script d'initialisation addListener(new ApplyEclipsePlugin()) class ApplyEclipsePlugin extends BuildAdapter { Invoquer par défaut public void projectsEvaluated(Gradle gradle){ si placé dans le gradle.rootProject.allprojects { home de apply plugin:'eclipse' l'utilisateur } } } gradle eclipse –I init.gradle LavaJUG - Présentation Gradle 26
  • 27.
    import org.junit.Assert > gradle myzip task myzip (type:Zip) { :myzip from('somedir') include('*.txt') baseName='zipname' doLast { Assert.assertEquals('zipname.zip', myzip.archiveName) createZip Assert.assertEquals(file('build/distributions'), myzip.destinationDir) Assert.assertTrue( zipname .zip !zipTree(myzip.archivePath).isEmpty()) txtfiles = fileTree('somedir').include('*.txt') check ziptxtfiles=zipTree(myzip.archivePath).matching{ include('*.txt') } Assert.assertEquals ( txtfiles.getFiles().size(), BUILD SUCCESSFUL ziptxtfiles.getFiles().size()) > } } LavaJUG - Présentation Gradle 27
  • 28.
  • 29.
    task generateTask(dependsOn:preSchemaGen) <<{ ant.echo (message:"Generating ...") ant { def schemagenTaskPath = path { fileset(dirs:'lib', includes: '*.jar') } taskdef ( name: "xjc", classname: "com.sun.tools.xjc.XJCTask", classpath: schemagenTaskPath ) xjc(destdir:generatedSources, package:"com.zenika.lib.model"){ schema(dir:"src/main/resources", includes:"**/*.xsd") } } } LavaJUG - Présentation Gradle 29
  • 30.
    build.xml <project> <target name="antTarget"> <echo message="Hello from Ant"/> </target> </project> build.gradle ant.importBuild('build.xml') antTarget.doLast { println('Hello from Gradle') } > gradle antTarget :antTarget Hello from Ant Hello from Gradle LavaJUG - Présentation Gradle 30
  • 31.
    apply plugin:'java' repositories { mavenCental() flatDir(dirs:'destrepo', IVY name:'ivyrep’) } group='com.zenika.gradledemos' > gradle uploadArchives version='1.0' status='release' uploadArchives { repositories { add(repositories.ivyrep) } } Repository Ivy distant Artifacts + meta Ivy LavaJUG - Présentation Gradle 31
  • 32.
    apply plugin:'java' apply plugin:'maven' Maven Ant group='test' Tasks version='1.0-SNAPSHOT' uploadArchives { repositories { mavenDeployer { repository( > gradle > gradle install uploadArchives url: remoteRepo) } } } Repository Repository Maven Maven Local Artifacts + distant Artifacts + meta Maven meta Maven LavaJUG - Présentation Gradle 32
  • 33.
    • Gestion avancée d'unmulti projet • Utilisation d'un cache • Exécution parallèle des tests • Build daemon LavaJUG - Présentation Gradle 33
  • 34.
    // settings.gradle shared include 'api', 'shared', 'services:webservices' webservices api // root build.gradle subprojects { api > gradle buildNeeded apply plugin: 'java' :shared:jar } :api:jar project(':api') { :api:test dependencies { :shared:test compile project(':shared') } } api > gradle buildDependents :shared:jar :api:jar // webservices/build.gradle apply plugin:'war' :api:test :webservices:war dependencies { :webservices:test compile project(':shared'), project(':api'), api > gradle jar –-no-rebuild 'commons-io:commons-io:1.2' api:jar } LavaJUG - Présentation Gradle 34
  • 35.
    1.  Le scriptGradle est compilé uniquement en cas de changement 2.  Détection des changements pour chaque entrée et chaque sortie pour la plupart des tâches fournies > gradle myzip :myzip > gradle myzip :myzip UP-TO-DATE > gradle myzip –-cache rebuild :myzip LavaJUG - Présentation Gradle 35
  • 36.
    class GenerateSchemaType extendsDefaultTask { String depsPath @InputFiles SourceDirectorySet inputXsdDirs @OutputDirectory File outputFile > gradle build :generateTask UP-TO-DATE @TaskAction :compileGeneratedJava UP-TO-DATE void generate() { :processGeneratedResources UP-TO-DATE ant { ...} :generatedClasses UP-TO-DATE } :compileJava UP-TO-DATE } ... task generateTask(type:GenerateSchemaType) { inputXsdDirs = sourceSets.main.resources outputFile = generatedSources depsPath = configurations.jaxb.asPath } LavaJUG - Présentation Gradle 36
  • 37.
    EXECUTION Process 1 Process 6 TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST CLASS CLASS CLASS CLASS CLASS CLASS CLASS CLASS CLASS CLASS PARALLELISATION Process 2 Process 7 TEST TEST TEST TEST TEST TEST TEST CLASS CLASS CLASS CLASS CLASS CLASS CLASS Process 3 TEST TEST TEST TEST TEST CLASS CLASS CLASS CLASS CLASS apply plugin:'java' Process 4 TEST TEST TEST TEST TEST CLASS CLASS CLASS CLASS CLASS test { forkEvery = 5 maxParallelForks = 4 } LavaJUG - Présentation Gradle 37
  • 38.
    •  Utilisation d'unprocessus parallèle pour éviter le cout de lancement > gradle build ... Total time: 3s > gradle build –daemon ... Total time: 3s > gradle build ... Total time: 1s •  Va favoriser l'intégration de Gradle avec Gradle UI et les IDE (Eclipse, IDEA, ...) LavaJUG - Présentation Gradle 38
  • 39.
    IDE Maturité NetBeans Eclipse + Eclipse STS ++ Idea IntelliJ ++ LavaJUG - Présentation Gradle 39
  • 40.
    HUDSON JENKINS Fonctionnalités: - Installation automatique de Gradle (via URL, Run Script) - Wizard de configuration - Utilisation possible du Gradle wrapper - Dry-Run - Coloration syntaxique LavaJUG - Présentation Gradle 40
  • 41.
    Environment Instancie Processus identifié (traçabilité) et répétable DEPLOY TEST BUILD RELEASE INSTALL VALIDATION LavaJUG - Présentation Gradle 41
  • 42.
    gmock security spock integration 4 LavaJUG - Présentation Gradle 42
  • 43.
    •  Mailing Listtrès active •  User guide très riche (400 pages) •  Nombreuses contributions de plugins •  Le nombre d'articles et de conférences augmentent LavaJUG - Présentation Gradle 43
  • 44.
  • 45.
    •  Des besoinsspécifiques de construction •  Structure de répertoires propre au projet •  Définition d'un cycle de vie personnalisé •  Plusieurs artefacts par projet •  Des besoins spécifiques de tests •  Tests d'intégration complexe •  Tests sur plusieurs JDK •  Beaucoup de tests à paralléliser •  Gestion fine des dépendances •  Build incrémental à plusieurs niveaux •  Définition de modèle de build (proche des concepts de Maven) LavaJUG - Présentation Gradle 45
  • 46.
    •  Comme tousles outils, un outil de build ne s'impose pas •  Ne pas l'opposer à Maven ou à Ant mais l'utiliser comme complément •  Construction avec Gradle et déploiement dans un repo Maven •  Réutilisation des scripts Ant existants et surcharge/ réécriture des cible Ant existantes (sans modifications des scripts actuels) •  Solution parfaite pour construire son propre modèle de build entreprise adapté à ses besoins •  Gradle est utilisé comme un framework •  L'utilisation de Gradle est caché (GradleWrapper) LavaJUG - Présentation Gradle 46
  • 47.
    •  Utiliser Gradlecomme un langage de build (API, réutilisabilité de modules, orientation objet, ...) et pas juste un langage de script de luxe •  Cadrer les descripteurs Gradle d'un projet à un autre •  Des revues de code des scripts sont à prévoir •  Comme tout code source, le build évolue et donc est soumis à des refactoring réguliers •  Essayer d'abstraire des modèles de build réutilisables •  Utiliser une version stable LavaJUG - Présentation Gradle 47
  • 48.
    Questions? LavaJUG- Présentation Gradle 48
  • 49.