présentation gradle au lyonjug par grégory boissinot - zenika
TRANSCRIPT
![Page 1: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/1.jpg)
1 Lyon JUG - Présentation Gradle
GRADLE Gregory BOISSINOT
23/11/2010
![Page 2: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/2.jpg)
2 Lyon JUG - Présentation Gradle
• Consultant et formateur Zenika – Mes spécialités: le build et l'intégration continue – Responsable technique de la solution d'intégration continue
chez Thales • Introduction et déploiement de Gradle à grande échelle
• Commiter Hudson – Intégration des châines de build Java (Gradle), C/C++, ADA
![Page 3: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/3.jpg)
3 Lyon JUG - Présentation Gradle
INTERNET
![Page 4: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/4.jpg)
4 Lyon JUG - Présentation Gradle
• Transformation d'une production humaine (le code source) en une représentation machine (le binaire)
Fichier Source JAR
JVM
println "Hello World" for (int i:[1,2,3]){ print i }
A;^A^@^Am^A^@^T()Ljava/lang/Object;^C^ @^@^@^@^A^@^KHello World^H^@2^A^@- 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^ ....
Fichier Binaire
![Page 5: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/5.jpg)
5 Lyon JUG - Présentation Gradle
• Les besoins d'automatisation ont augmentés significativement ces dernières années
• La nature des besoins d'automatisation a changé Un build peut faire beaucoup plus de choses que la simple création d'une archive Java
![Page 6: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/6.jpg)
6 Lyon JUG - Présentation Gradle
1ère génération
2008
2001
2
1
3
2ème génération 3ème génération 2000 2005 2008
![Page 7: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/7.jpg)
7 Lyon JUG - Présentation Gradle
<!–- ANT -- build.xml --> <project> <target name="retrieceDeps> ... </target> <target name="compile" ... </project>
<!–- GRADLE– build.gradle --> apply plugin:'java'
version=1.0
repositories { mavenCental() flatDir(dirs:'lib') }
dependencies { compile( group:'org.apache.wicket', name:'wicket', version:'1.4.7') }
<!–- MAVEN – pom.xml--> <?xml version="1.0" encoding="UTF-8"?> <project> <modelVersion>4.0.0</modelVersion> <groupId>org.lyonjug</groupId> <artifactId>maven</artifactId> <version>1.0</version> <dependencies> <dependency> <groupId>org.apache.wicket</groupId> <artifactId>wicket</artifactId> <version>1.4.7</version> <scope>compile</scope> </dependency> </dependencies> </project>
![Page 8: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/8.jpg)
8 Lyon JUG - Présentation Gradle
• Système de build complet focalisé sur le build des applications d'entreprise Java, Web, Groovy, Scala et OSGI
• Modèle de description du build très riche à travers une API et une DSL Groovy
• Flexible à la Ant avec les conventions de Maven à la demande
• Support et insertion totale dans des infrastructures Maven et Ant/Ivy existantes
![Page 9: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/9.jpg)
9 Lyon JUG - Présentation Gradle
• Spécification du 'quoi' et pas du 'comment'
Même
convention
que Maven apply plugin:'java'
repositories { mavenCental() }
dependencies { compile "jdom:jdom:1.1" testCompile "junit:junit:4.8" }
myLib .jar
src
main
java
test
java
> gradle clean build :clean :compileJava :processResources :classes :jar :assemble :compileTestJava :processTestResources :testClasses :test :check :build
BUILD SUCCESSFUL resources
resources
![Page 10: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/10.jpg)
10 Lyon JUG - Présentation Gradle
On ne peut pas anticiper tous les besoins
Il est nécessaire de fournir le même niveau de support entre les anciens projets et les nouveaux projets
![Page 11: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/11.jpg)
11 Lyon JUG - Présentation Gradle
Project
repositories dependencies
task
configurations
artifacts
API
ant
Écrire un script Gradle consiste à configurer un objet Project
build.gradle
Eléments personnalisés
![Page 12: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/12.jpg)
12 Lyon JUG - Présentation Gradle
• Conçu pour répondre à tous les scénarios possibles – Plusieurs répertoires de sources par projet – Une version de JDK par répertoire – Plusieurs artefacts par projet – ....
• De nombreux points d'extension pour enrichir les éléments existant
• La possibilité de fournir ses propres éléments qui vont former un modèle de build
![Page 13: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/13.jpg)
13 Lyon JUG - Présentation Gradle
<!-- build.gradle --> task(boucleTask).doFirst{ for (int i:[1,2,3]){ print i } }
void printMessage(String message){ println "Print " + message }
task(distribution).doFirst { printMessage("Distribution") }
task(release) release.dependsOn(distribution) release.doFirst{ println "Print Release" }
> gradle boucleTask :boucleTask 123
> gradle distribution :distribution Print Distribution
> gradle release :distribution Print Distribution :release Print Release
Possibilité d'écrire du code Java/Groovy sous forme d'unités réutilisables
![Page 14: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/14.jpg)
14 Lyon JUG - Présentation Gradle
task mycopy (type:Copy){ description ='Copies the resources dir' from(file('resources')) into(file('target')) include('**/*.txt', '**/*.xml') }
AbstractCopyTask
AbstractArchiveTask
Zip
Jar
War
Tar
SourceTask
Javadoc
ConventionTask
Copy
public class Copy extends AbstractCopyTask { public AbstractCopyTask from(Object... sourcePaths); public AbstractCopyTask into(Object destDir); public AbstractCopyTask include(String... includes); . . . }
![Page 15: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/15.jpg)
15 Lyon JUG - Présentation Gradle
<!– 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" }
![Page 16: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/16.jpg)
16 Lyon JUG - Présentation Gradle
• Les plugins Gradle
• Insertion dans un environnement agile
![Page 17: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/17.jpg)
17 Lyon JUG - Présentation Gradle
java
war
maven
osgi
code-quality
jetty
scala
eclipse idea
projects-reports
Java Configuration Object
War Configuration Object
Jetty Configuration Object
…
Plugins
Project Configuration
…
…
Chaque plugin
- est un ensemble de tâches
- expose un objet Java convention
![Page 18: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/18.jpg)
18 Lyon JUG - Présentation Gradle
> gradle config ...
<!– build.gradle --> task config { ... }
<!– build.gradle --> apply from "http://repomanager/config-1.0.gradle" ...
config-1.0.gradle
Mise à disposition
Utilisation
![Page 19: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/19.jpg)
19 Lyon JUG - Présentation Gradle
![Page 20: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/20.jpg)
20 Lyon JUG - Présentation Gradle
• Flexibilité dans la définition des dépôts
• Possibilité de mettre en place des exclusions globales • Possibilité de définir les dépendances transitives dans le
script Gradle
repositories{ mavenCentral() mavenRepo urls: "http://download.java.net/maven/2/" flatDir name: 'localRepository', dirs: 'lib' }
dependencies { runtime module("org.codehaus.groovy:groovy-all:1.7.5") { dependency("commons-cli:commons-cli:1.0") { transitive = false } } }
![Page 21: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/21.jpg)
21 Lyon JUG - Présentation Gradle
apply plugin:'java'
processResources.enabled=false
test.onlyIf{ !project.hasProperty('skipTests')}
//Add behavior in the lifecycle task(preJar) jar.dependsOn preJar
//Change the output directory buildDirName='target'
//Change the source directory sourceSets{ main{ java.srcDirs file('src/java'), file('src/java2') } }
> gradle build –PskipTests :compileJava :processResources SKIPPED :classes :preJar :jar :war :assemble :compileTestJava :processTestResources :testClasses :test SKIPPED :check :build
BUILD SUCCESSFUL
![Page 22: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/22.jpg)
22 Lyon JUG - Présentation Gradle
apply plugin:'java'
sourceSets{ myGenSourceSet { java { srcDir 'build/generated' } } }
> gradle clean build :clean :generateTask . . . :compileMyGenSourceSetJava :processMyGenSourceSetResources :myGenSourceSetClasses . . .
![Page 23: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/23.jpg)
23 Lyon JUG - Présentation Gradle
sourceSets{ myGenSourceSet { java { srcDir 'build/generated' }
main { compileClasspath = configurations.compile +sourceSets.myGenSourceSet.classes
runtimeClasspath = classes + configurations.runtime + sourceSets.myGenSourceSet.classes } }
jar { from sourceSets.myGenSourceSet.classes }
> gradle clean build :clean :generateTask :compileMyGenSourceSetJava :processMyGenSourceSetResources :myGenSourceSetClasses :compileJava :processResources :classes . . .
![Page 24: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/24.jpg)
24 Lyon JUG - Présentation Gradle
version = 1.0 gradle.taskGraph.whenReady { taskGraph -> if (! taskGraph.hasTask(':release')){ version+='-SNAPSHOT' } }
GRADLE SCRIPT
Engine
CO
NFIG
UR
ATION
PHA
SE
t1 t2
t4
Project Convention 1
HO
OK
t3 t1 t2
t4
Project Convention 2
t3 EXEC
UTIO
N PH
ASE
gradle –-properties gradle –-tasks gradle –-dependencies gradle –-dry-run build
// Other hooks gradle.taskGraph.beforeTask { task -> .. . gradle.beforeProject { project -> .. . ...
![Page 25: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/25.jpg)
25 Lyon JUG - Présentation Gradle
Soyez informé des événements: TestListener, BuildListener, TaskActionListener, …
class MyTestListener implements TestListener{
void beforeTest(TestDescriptor test) { println 'testStarting: '+test.getName() }
void afterTest(TestDescriptor test, TestResult result) { println 'testFinished: '+test.getName() +', result: '+result.getResultType() } }
Test (junit)
GR
AD
LE beforeTest
afterTest
![Page 26: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/26.jpg)
26 Lyon JUG - Présentation Gradle
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())
txtfiles = fileTree('somedir').include('*.txt') ziptxtfiles=zipTree(myzip.archivePath).matching{ include('*.txt') } Assert.assertEquals ( txtfiles.getFiles().size(), ziptxtfiles.getFiles().size()) } }
zipname.zip
createZip
check
> gradle myzip :myzip
BUILD SUCCESSFUL >
![Page 27: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/27.jpg)
27 Lyon JUG - Présentation Gradle
![Page 28: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/28.jpg)
28 Lyon JUG - Présentation Gradle
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") } } }
![Page 29: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/29.jpg)
29 Lyon JUG - Présentation Gradle
build.gradle
build.xml
ant.importBuild('build.xml') antTask.doLast { println('Hello from Gradle') }
<project> <target name="antTask"> <echo message="Hello from Ant"/> </target> </project>
> gradle antTask :antTask Hello from Ant Hello from Gradle
![Page 30: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/30.jpg)
30 Lyon JUG - Présentation Gradle
IVY
Repository Ivy
distant Artifacts + meta Ivy
apply plugin:'java'
repositories { mavenCental() flatDir(dirs:'destrepo', name:'ivyrep’) }
group='test' version='1.0' status='release'
uploadArchives { repositories { add(repositories.ivyrep) } }
> gradle uploadArchives
![Page 31: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/31.jpg)
31 Lyon JUG - Présentation Gradle
Repository Maven distant Artifacts +
meta Maven
Maven Ant
Tasks
Repository Maven Local Artifacts +
meta Maven
apply plugin:'java' apply plugin:'maven'
group='test' version='1.0-SNAPSHOT'
uploadArchives { repositories { mavenDeployer { repository( url: remoteRepo) } } }
> gradle uploadArchives
> gradle install
![Page 32: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/32.jpg)
32 Lyon JUG - Présentation Gradle
• Gestion avancée d'un multi projet
• Utilisation d'un cache
• Exécution parallèle des tests
• Build daemon
![Page 33: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/33.jpg)
33 Lyon JUG - Présentation Gradle
// settings.gradle include 'api', 'shared', 'services:webservices'
// root build.gradle 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
api > gradle jar –-no-rebuild api:jar
![Page 34: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/34.jpg)
34 Lyon JUG - Présentation Gradle
1. Le script Gradle est compilé uniquement en cas de changement
2. Détéction 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
![Page 35: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/35.jpg)
35 Lyon JUG - Présentation Gradle
class GenerateSchemaType extends DefaultTask {
String depsPath
@InputFiles SourceDirectorySet inputXsdDirs
@OutputDirectory File outputFile
@TaskAction void generate() { ant { ...} } }
task generateTask(type:GenerateSchemaType) { inputXsdDirs = sourceSets.main.resources outputFile = generatedSources depsPath = configurations.jaxb.asPath }
> gradle build :generateTask UP-TO-DATE :compileGeneratedJava UP-TO-DATE :processGeneratedResources UP-TO-DATE :generatedClasses UP-TO-DATE :compileJava UP-TO-DATE ...
![Page 36: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/36.jpg)
36 Lyon JUG - Présentation Gradle
apply plugin:'java'
test { forkEvery = 5 maxParallelForks = 4 }
Process 1 TEST SUITE
TEST SUITE
TEST SUITE
TEST SUITE
TEST SUITE
Process 7 TEST SUITE
TEST SUITE
Process 2 TEST SUITE
TEST SUITE
TEST SUITE
TEST SUITE
TEST SUITE
Process 3 TEST SUITE
TEST SUITE
TEST SUITE
TTEST SUITE
TEST SUITE
EXECUTION
Process 4 TEST SUITE
TEST SUITE
TTEST SUITE
TEST SUITE
TEST SUITE
Process 6 TEST SUITE
TEST SUITE
TEST SUITE
TEST SUITE
TEST SUITE PA
RA
LLELISATION
![Page 37: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/37.jpg)
37 Lyon JUG - Présentation Gradle
• Utilisation d'un processus parallèle pour éviter le cout de lancement
• Va favoriser l'intégration de Gradle avec Gradle UI et les IDE (Eclipse, IDEA, ...)
> gradle build ... Total time: 3s
> gradle build –daemon ... Total time: 3s
> gradle build ... Total time: 1s
![Page 38: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/38.jpg)
38 Lyon JUG - Présentation Gradle
![Page 39: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/39.jpg)
39 Lyon JUG - Présentation Gradle
gmock
spock security
4
![Page 40: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/40.jpg)
40 Lyon JUG - Présentation Gradle
• Mailing List très active
• User guide très riche (+280 pages)
• Nombreuses contributions de plugins
• Le nombre d'articles et de conférences sur le sujet augmentent
![Page 41: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/41.jpg)
41 Lyon JUG - Présentation Gradle
![Page 42: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/42.jpg)
42 Lyon JUG - Présentation Gradle
• Nouveau DSL de gestion des dépendances
• Introduction de modèles de JVM basés sur la nature des applications
• Fourniture d'un DSL de composition du build
• Amélioration du DSL du graphe des tâches
• Réutilisation possible des plugins Maven
• Un livre en préparation
![Page 43: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/43.jpg)
43 Lyon JUG - Présentation Gradle
![Page 44: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/44.jpg)
44 Lyon JUG - Présentation Gradle
• Essayez-le !
• Utilisez-le !
• Faites du buzz!
![Page 45: Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika](https://reader033.vdocuments.site/reader033/viewer/2022052508/55980f811a28ab431f8b45a5/html5/thumbnails/45.jpg)
45 Lyon JUG - Présentation Gradle
Merci