README.md 18.1 KB
Newer Older
Bastien Herreros's avatar
jacobo    
Bastien Herreros committed
1
2
3
4
[![pipeline status](http://gitlab.isima.fr/baherreros/tp3-forge/badges/master/pipeline.svg)](http://gitlab.isima.fr/baherreros/tp3-forge/commits/master)

[![coverage report](http://gitlab.isima.fr/baherreros/tp3-forge/badges/master/coverage.svg)](http://gitlab.isima.fr/baherreros/tp3-forge/commits/master)

baherreros's avatar
baherreros committed
5
# Infos étudiant :
baherreros's avatar
baherreros committed
6

baherreros's avatar
baherreros committed
7
Par binôme Nom Prénom:
baherreros's avatar
baherreros committed
8
9
 * Amorim Dylan
 * Herreros Bastien
baherreros's avatar
baherreros committed
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

# TP 3

Le but de ce TP est de mettre en place un processus d'intégration continue en se basant sur le projet précédent.

## 1 Création d'un espace projet dédié sous gitlab
1. Pour mettre en place une chaine d'intégration continue initialisez un nouveau projet sous [GitLab](https://gitlab.isima.fr).
1. Ajouter dans la liste des développeurs votre binôme. (Settings/Members)
1. Ajouter en reporter `tjouve` et `iia_samorel`.
1. Ajoutez ce compte rendu comme readme de votre projet.
    * Vous pouvez le faire directement depuis l'interface avec *new File*
    * Copier le code markdown, il est possible d'editer le document via l'interface web directement sur gitlab
    * **Renseignez vos noms en haut du compte rendu**
1. Ajoutez une licence pour indiquer sous quels termes votre production est disponible
    * Cliquez sur **Add License**, il est possible de rédiger soi-même le contenu, ou de selectionner une licence existante (Apache, MIT, GNU ...). Le site [choose a license](https://choosealicense.com/licenses/) propose un comparatif entre les différentes liences les plus courantes.


## 2 Initialisation du projet
Pour prendre en charge la gestion des dépendances et l'automatisation de la construction de l'application nous utiliserons `Maven`.
Pour démarrer rapidement le projet nous allons faire du *scaffolding*. Pour ce faire nous utiliserons [Spring Boot](https://projects.spring.io/spring-boot/). Et plus particuliérement [Spring initializr](https://start.spring.io/).

### 2.1 Spring Initializer
1. Créer un squelette d'application avec [Spring initializr](https://start.spring.io/) :
    1. choisissez comme groupe id **isima.F2**
    2. comme nom d'artefact vous saisirez **TP3.`nom binome`**
    3. téléchargez ce template de projet.
1. clonez votre nouveau projet localement
    1. dézippez l'archive dans votre repo local, ce dernier ne devrait contenir que l'arborescence des sources, le pom et votre readme
    1. commitez et pushez sur le serveur


### 2.2 Utilisation de maven
Avant de reporter le code du TP2 nous allons nous familiariser avec *Maven*

#### 2.2.1 Convention over configuration
Pour permettre de développer plus rapidement des applications une bonne pratique est de respecter certaines normes.

Dans notre cas en utilisant **Spring Initializer** nous avons rapidement généré un squelette d'application utilisant maven et fournissant un certain nombre de fonctionnalitées transverses.
Notamment un framework de test **JUnit** et un framework de logging **Logback**


* A quoi correspondent les fichiers présents dans le zip ?
    * pom.xml
    * .gitignore
    * décrire l'arborescence de répertoire

AmorimDylan's avatar
AmorimDylan committed
56
57
58
59
60
61
62
63
64
65
66
### Pom.xml

Le POM.xml est l'unité de travail fondamentale de Maven. Il s'agit d'un fichier XML qui contient des informations sur le projet et les détails de configuration utilisés par Maven pour générer le projet. Lors de l'exécution d'une tâche ou d'un objectif, Maven recherche le POM dans le répertoire actuel. Il lit le POM, obtient les informations de configuration nécessaires, puis exécute l'objectif.

### .gitignore

La .gitignore permet d'exclure certains fichiers de git, les fichiers contenus dans le .gitignore ne sont donc pas pris en compte lors des différentes commandes git.

### Arborescence

Au sein du dossier on va retrouver un dossier src contenant deux autres dossiers : main et test. Dans le dossier main on trouvera les classes java dans le dossier java contenant lui même un package, ici isima.F2.TP3.Amorim.Herreros. Et dans le dossier test on retrouvera la même architecture dans laquelle on implémentera les tests correspondants aux classes dans le dossier main.
baherreros's avatar
baherreros committed
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

#### 2.2.2 Gestion des dépendances

Dans le nouveau projet on retrouve une classe *Application.java* sous *src/main/java* dans le package *isima.F2.TP3.`nom binome`*
* Dans cette classe créez un logger et loggez un `Hello Word` en *warning*

```java
private static final Logger logger = LoggerFactory.getLogger(DemoApplication.class);

public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
    logger.warn("Hello Word");

}
```

* Exécutez votre programme

Bastien Herreros's avatar
log    
Bastien Herreros committed
85
86
87
88
89
90
91
92
93
94
    2020-02-10 15:15:38.691  INFO 5919 --- [main] i.F2.TP3.Amorim.Herreros.Application : Starting Application on LAPTOP-9QQC47BV with PID 5919 (/home/juflasse/Documents/cours/forge/tp3/tp3-forge/TP3.Amorim.Herreros/target/classes started by juflasse in /home/juflasse/Documents/cours/forge/tp3/tp3-forge/TP3.Amorim.Herreros)

    2020-02-10 15:15:38.696  INFO 5919 --- [main] i.F2.TP3.Amorim.Herreros.Application     : No active profile set, falling back to default profiles: default

    2020-02-10 15:15:40.441  INFO 5919 --- [main] i.F2.TP3.Amorim.Herreros.Application : Started Application in 2.958 seconds (JVM running for 4.503)
    
    2020-02-10 15:15:40.444  WARN 5919 --- [main] i.F2.TP3.Amorim.Herreros.Application : Hello Word

    Process finished with exit code 0

baherreros's avatar
baherreros committed
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

Vous remarquerez qu'il n'est pas nécessaire d'ajouter la dépendance vers un logger (ici *logback*). C'est une dépendance classique d'un projet java. Elle est déjà présente dans le pom de *spring boot*.

Pour illustrer la gestion des dépendances automatiques vous ajouterez une dépendance vers la librairie **commons-lang3** de **apache**
* Ajout de la dépendance *Apache commons lang3*
    * Pour ce faire recherche `commons-lang3` sur [MVNrepository](https://mvnrepository.com).
    * selectionnez la derniére version
    * copiez la déclaration et collez là dans votre *pom.xml*
    * Décrivrez rapidement le fonctionnement de la résolution de dépendance

`Vos reponces ICI; n'oubliez pas de commiter au fil de l'eau`

* Utilisez la classe utilitaire `StringUtils` et sa méthode `reverse` pour afficher dans la log au niveau *debug* vos noms à la suite du Hello Word.
    * La ligne de log n'apparait pas dans la console car le niveau de trace par defaut est `WARN`.
    * [Spring boot logging](https://docs.spring.io/spring-boot/docs/current/reference/html/howto-logging.html) indique comment changer le niveau de trace. (Il n'est pas nécessaire d'ajouter la dépendance elle est déjà présente).
    * Un fois le niveau de trace par defaut changé vous devriez voir le résultat de votre commande.
    * Quel fichier de configuration est modifié ?

`Vos reponces ICI; n'oubliez pas de commiter au fil de l'eau`   
Bastien Herreros's avatar
Bastien Herreros committed
114
    Pour que le logger afficher les messages de debug, il faut ajouter "logging.level.root=DEBUG" dans application.properties.
baherreros's avatar
baherreros committed
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130

#### 2.2.3 Gestion du cycle de vie

Dans cette partie nous allons utiliser les commandes de build de manven. Ces commandes permettentent d'automatiser certaines taches.
[Maven Lyfe Cycle](https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html) décrit l'ensemble des instructions et l'enchainement des différentes phases de **Maven**.

L'archive générée via spring initializer contient un répertoire `.mvn` et 2 scripts `mvnw` et `mvnw.bat`. Le projet contient par defaut un *wrapper* qui permet d'avoir une installation locale de maven pour ne pas être dépendant du systéme sur lequel on développe.

Il est possible de lancer directement des taches maven en appellant le script (`mvnw` pour *linux* et `mvnw.bat` pour *windows* ).

Par example `./mvnw.bat clean` permet de supprimer les classes compilées dans le repertoire target.

En utilisant la ligne de commande nous allons compiler, tester et packager l'application sous la forme d'un jar.

##### 2.2.3.1 Compilation
* Quelle est la commande à lancer pour compiler l'application ?
Bastien Herreros's avatar
Bastien Herreros committed
131
132
133
    
        mvn compile

baherreros's avatar
baherreros committed
134
* Quelle est la commande à lancer pour compiler & éxécuter les tests ?
Bastien Herreros's avatar
Bastien Herreros committed
135
136
137
    
        mvn test

baherreros's avatar
baherreros committed
138
139
* Quel sont les fichiers / répertoires générés par cette commande ?

Bastien Herreros's avatar
Bastien Herreros committed
140
141
        /target/surefire-reports/isima.F2.TP3.Amorim.Herreros.ApplicationTests.txt 

baherreros's avatar
baherreros committed
142
143
144

##### 2.2.3.2 Packaging
* Quelle est la commande à lancer ?
Bastien Herreros's avatar
Bastien Herreros committed
145
146
147

        mvn package

baherreros's avatar
baherreros committed
148
149
* Quel sont les fichiers / répertoires générés par cette commande ?

Bastien Herreros's avatar
Bastien Herreros committed
150
151
        target/TP3.Amorim.Herreros-0.0.1-SNAPSHOT.jar

baherreros's avatar
baherreros committed
152
153
154
155
156
157
158
159


### 2.3 Reportez le code du TP2           
* Reportez vos classes d'implémentation et de test dans le nouveau projet
    * Votre implémentation dans le repertoire src/main/java/*pakcage_name*/*Application*
    * Votre classe de test dans le repertoire src/test/java/*pakcage_name*/*ApplicationTests*
* Effectuez le packaging de votre application pour lancer la compilation et les tests.

Bastien Herreros's avatar
yml    
Bastien Herreros committed
160
        mvn package
baherreros's avatar
baherreros committed
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

## 3 Intégration continue

Gitlab permet de faire de l'intégration continue sur votre code.
Nous allons mettre en place un job permettant de réaliser la compilation,les test et le packaging à chaque commit en utilisant [Gitlab CI](https://about.gitlab.com/features/gitlab-ci-cd/)

### 3.1 Mettre en place une intégration continue en utilisant gitlab-ci

Liens utiles:
* [Gitlab CI](https://docs.gitlab.com/ce/ci/yaml/README.html#gitlab-ci-yml)

Sur la page d'acceuil de votre projet, à coté du bouton pour ajouter une licence, il y a un acces rapide pour créer à partir d'un template un fichier `.gitlab-ci.yml`.
On utilisera un template maven pour initialiser le descriptif des actions à réaliser.

* Désormais dans la partie CI/CD de votre projet vous pouvez voir vos pipelines en cours d'éxécution ou passé et leurs status.
* Le yml par defaut devrait faire echouer votre pipeline.
* Quelles est l'erreur ?

Bastien Herreros's avatar
yml    
Bastien Herreros committed
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
        [ERROR] The goal you specified requires a project to execute but there is no POM in this directory (/builds/baherreros/tp3-forge). Please verify you invoked Maven from the correct directory. -> [Help 1]
        org.apache.maven.lifecycle.MissingProjectException: The goal you specified requires a project to execute but there is no POM in this directory (/builds/baherreros/tp3-forge). Please verify you invoked Maven from the correct directory.
            at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:84)
            at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:307)
            at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:193)
            at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:106)
            at org.apache.maven.cli.MavenCli.execute(MavenCli.java:863)
            at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:288)
            at org.apache.maven.cli.MavenCli.main(MavenCli.java:199)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:606)
            at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
            at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
            at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
            at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
        1234 [ERROR] 
        1234 [ERROR] Re-run Maven using the -X switch to enable full debug logging.
        1235 [ERROR] 
        1235 [ERROR] For more information about the errors and possible solutions, please read the following articles:
        1235 [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MissingProjectException
        ERROR: Job failed: exit code 1
baherreros's avatar
baherreros committed
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225

* Le script template proposé par defaut est relativement complexe.
* Pour la suite nous utiliserons le template suivant :

```yaml
variables:
  # This will supress any download for dependencies and plugins or upload messages which would clutter the console log.
  # `showDateTime` will show the passed time in milliseconds. You need to specify `--batch-mode` to make this work.
  MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true"
  # As of Maven 3.3.0 instead of this you may define these options in `.mvn/maven.config` so the same config is used
  # when running from the command line.
  # `installAtEnd` and `deployAtEnd` are only effective with recent version of the corresponding plugins.
  MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end --show-version -DinstallAtEnd=true -DdeployAtEnd=true"

# Cache downloaded dependencies and plugins between builds.
# To keep cache across branches add 'key: "$CI_JOB_REF_NAME"'
cache:
  paths:
    - .m2/repository

#Definition des différentes étapes présent dans le pipeline
stages:
  - build
  - test
baherreros's avatar
baherreros committed
226
  - package
baherreros's avatar
baherreros committed
227
228
229
230
231
232

#Définition du job de compilation
compilation:
  image: maven:3.3.9-jdk-8
  stage: build
  script:
Bastien Herreros's avatar
readme    
Bastien Herreros committed
233
    - mvm compile
baherreros's avatar
baherreros committed
234
235
236
237
238
239


validation:
  image: maven:3.3.9-jdk-8
  stage: test
  script:
Bastien Herreros's avatar
readme    
Bastien Herreros committed
240
241
242
243
244
    - mvn test


packaging:
  image: maven:3.3.9-jdk-8
baherreros's avatar
baherreros committed
245
  stage: package
Bastien Herreros's avatar
readme    
Bastien Herreros committed
246
247
  script:
    - mvn package
baherreros's avatar
baherreros committed
248
249
250
251
252
253
```

* Remplacez le `.gitlab-ci.yml` par celui-ci et completez le avec les commandes maven précédement utilisées pour réaliser la phase de build et de test

* Completez le `.gitlab-ci.yml` pour inclure un nouveau stage de packaging qui vas construire le jar de votre application

Bastien Herreros's avatar
readme    
Bastien Herreros committed
254
255
        packaging:
            image: maven:3.3.9-jdk-8
baherreros's avatar
baherreros committed
256
            stage: package
Bastien Herreros's avatar
readme    
Bastien Herreros committed
257
258
            script:
                - mvn package   
baherreros's avatar
baherreros committed
259
260
261
262
263

#### 3.1.1 Badge

**Gilab** permet d'afficher dans votre readme le status de votre pipeline dynamiquement pour celà :
* Rendez vous dans la partie [Settings > CI/CD > General pipelines settings](https://docs.gitlab.com/ee/user/project/pipelines/settings.html) de votre projet. A l'aide de la documentation sur les [badges](https://docs.gitlab.com/ee/user/project/pipelines/settings.html#badges)
Bastien Herreros's avatar
readme    
Bastien Herreros committed
264
265
rajoutez un badage indiquant le status de votre pipeline de build dans votre readme.

baherreros's avatar
baherreros committed
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
### 3.2 Couverture de code

Nous allons ajouter un outil permettant de réaliser des statistiques sur la qualité des tests. Il sagit ici de [jacoco](http://www.eclemma.org/jacoco/) une librairie permettant de réaliser des statistiques sur le taux de couverture de code par les tests unitaires.

* Ce plugin lors de la compilation vas modifier votre code pour injecter du code permettant de savoir quelles lignes sont exécutées ou non.
    * Pour ce faire il faut rajouter dans votre **pom.xml**, dans la partie *build/pulgins*, la déclaration suivante :

```xml
<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.8.0</version>
    <executions>
        <execution>
            <id>default-prepare-agent</id>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
    </executions>
</plugin>
```

* Nous allons rajouter au readme du projet un badge indiquant le % de code couvert.
    * Sur gitlab, dans les settings de la partie CI/CD dans General pipeline settings, vous trouverez une zone de saisie pour **Test coverage parsing**.
En effet il est nécessaire d'indiquer à **Gitlab CI** où trouver l'information sur le pourcentage de code couvert : `A regular expression that will be used to find the test coverage output in the job trace.`
    * Cette information se trouve dans le rapport généré par jacoco. Par defaut le rapport n'est pas généré. Il faut donc modifier le paramètrage du plugin pour lui demander de générer le rapport.
Dans le code suivant on indique au plugin qu'il doit exécuter sa tache **report** lorsque de la phase **test** de maven.   

```xml
<execution>
    <id>default-report</id>
    <phase>test</phase>
    <goals>
        <goal>report</goal>
    </goals>
</execution>
```

* Le rapport est généré dans le repertoire target/site/jacoco sous la forme d'un fichier html.
    * Il faut dans la partie settings de votre CI indiquer l'expression réguliére permettant de retrouver le % de code couvert. Utilisez `Total.*?([0-9]{1,3})%`.
    * Ajoutez à votre `.gitlab-ci.yml` la commande permettant de faire apparaitre le contenu de ce fichier dans la log de votre job.

`Comment affichez vous l'information dans la log du job ?`

Bastien Herreros's avatar
package    
Bastien Herreros committed
311
312
313
314
315
316
        validation:
        image: maven:3.3.9-jdk-8
        stage: test
        script:
            - mvn test;cat target/site/jacoco/index.html

baherreros's avatar
baherreros committed
317
318
* Rajoutez en début de votre readme le badge indiquant le pourcentage de couverture de code.

Bastien Herreros's avatar
jacobo    
Bastien Herreros committed
319

Bastien Herreros's avatar
Bastien Herreros committed
320

baherreros's avatar
baherreros committed
321
322
323
### 3.3 Analyse de code avec Sonar
Nous allons mettre en place à chaque éxécution de notre pipeline une analyse sonar.

Bastien Herreros's avatar
Bastien Herreros committed
324
Le serveur sonar à utiliser se trouve à l'adresse suivante : [ISIMA Sonar](http://40.89.147.107/)
baherreros's avatar
baherreros committed
325

Bastien Herreros's avatar
Bastien Herreros committed
326
Le compte permettant d'acceder à l'application est `isima`, le mot de passe `isima2019`.
baherreros's avatar
baherreros committed
327
328
329
330
331

* à la suite de la phase de test ajoutez dans votre job une analyse Sonar.
* Pour exécuter une analyse sonar il suffit de lancer la commande :

```
Bastien Herreros's avatar
Bastien Herreros committed
332
mvn sonar:sonar -Dsonar.host.url=http://40.89.147.107 -Dsonar.login=TOKEN
baherreros's avatar
baherreros committed
333
334
```

Bastien Herreros's avatar
Bastien Herreros committed
335
* Le token pour le user `isima` est `99ae2bca252a19b71d0886ed8338c768d5c2da95`.
baherreros's avatar
baherreros committed
336
337
338
339
340
341
* Une fois la première analyse lancée, rendez vous sur l'application pour constater quels sont les anomalies détectées et les indicateurs de qualimétrie de votre code.
* Corrigez votre code en conséquence pour obtenir la meilleur note possible.
* Il est possible de spécifier directement dans le pom.xml l'adresse du serveur cible
    * pour ce faire on ajoutera dans la balise properties une entrée tel que :

    ```xml
Bastien Herreros's avatar
Bastien Herreros committed
342
    <sonar.host.url>http://40.89.147.107</sonar.host.url>
baherreros's avatar
baherreros committed
343
344
345
346
347
348
    ```
    * on peux alors appeler directement `mvn sonar:sonar -Dsonar.login=TOKEN` l'URL du serveur est prise dans les properties de votre projet maven

* Pour le login il est possible de faire de même, mais en terme de sécurité ce n'est pas une bonne idée d'indiquer le token d'acces dans vos sources
    * Gitlab-ci permet d'injecter de manière caché certaines propriétés [secret variables](https://gitlab.isima.fr/help/ci/variables/README#secret-variables)
    * Définissez une variable secrete contenant le login et utilisez la dans votre .gitlab-ci.yml