Introduzione a Jenkins 2 e al potere delle condutture

1. Panoramica

In questo articolo, mostreremo l'utilizzo delle pipeline attraverso un esempio di distribuzione continua utilizzando Jenkins.

Costruiremo una pipeline semplice, ma abbastanza utile, per il nostro progetto di esempio:

  • Compilazione
  • Analisi statica semplice (parallela alla compilazione)
  • Test unitari
  • Test di integrazione (parallelamente agli unit test)
  • Distribuzione

2. Installazione di Jenkins

Prima di tutto, dobbiamo scaricare l'ultima versione stabile di Jenkins (2.73.3 al momento della stesura di questo articolo).

Andiamo alla cartella in cui si trova il nostro file ed eseguiamolo utilizzando il comando java -jar jenkins.war . Tieni presente che non possiamo utilizzare Jenkins senza una configurazione iniziale degli utenti.

Dopo aver sbloccato Jenkins utilizzando la password iniziale generata dall'amministratore, dobbiamo inserire le informazioni del profilo del primo utente amministratore e assicurarci di installare tutti i plug-in consigliati.

Ora abbiamo una nuova installazione di Jenkins pronta per essere utilizzata.

Tutte le versioni disponibili di Jenkins possono essere trovate qui.

3. Condotte

Jenkins 2 viene fornito con una grande funzionalità chiamata Pipelines , che è molto estensibile quando abbiamo bisogno di definire un ambiente di integrazione continua per un progetto.

Una pipeline è un altro modo per definire alcuni passaggi di Jenkins utilizzando il codice e automatizzare il processo di distribuzione del software.

Utilizza un linguaggio DSL (Domain Specific Language) con due diverse sintassi:

  • Pipeline dichiarativa
  • Pipeline con script

Nei nostri esempi, utilizzeremo la pipeline con script che segue un modello di programmazione più imperativo costruito con Groovy .

Esaminiamo alcune caratteristiche del plugin Pipeline :

  • le pipeline vengono scritte in un file di testo e trattate come codice; questo significa che possono essere aggiunti al controllo della versione e modificati in seguito
  • rimarranno dopo i riavvii del server Jenkins
  • facoltativamente possiamo mettere in pausa le pipeline
  • supportano requisiti complessi come l'esecuzione di lavori in parallelo
  • il plugin Pipeline può anche essere esteso o integrato con altri plugin

In altre parole, impostare un progetto Pipeline significa scrivere uno script che applicherà sequenzialmente alcuni passaggi del processo che vogliamo realizzare.

Per iniziare a utilizzare le pipeline dobbiamo installare il plugin Pipeline che permette di comporre automazioni semplici e complesse.

Facoltativamente, possiamo anche avere la Pipeline Stage View in modo che quando eseguiamo una build, vedremo tutte le fasi che abbiamo configurato.

4. Un rapido esempio

Per il nostro esempio, useremo una piccola applicazione Spring Boot. Creeremo quindi una pipeline che clona il progetto, lo compila ed esegue diversi test, quindi esegue l'applicazione.

Installiamo i plugin Checkstyle , Static Analysis Collector e JUnit , che sono rispettivamente utili per raccogliere i risultati di Checkstyle , costruire un grafico di analisi combinato dei rapporti di prova e illustrare i test eseguiti con successo e quelli falliti.

Innanzitutto, capiamo qui il motivo di Checkstyle: è uno strumento di sviluppo che aiuta i programmatori a scrivere codice Java migliore seguendo standard accettati e ben noti.

Static Analysis Collector è un componente aggiuntivo che raccoglie diversi output di analisi e stampa i risultati in un grafico di tendenza combinato. Inoltre, il plug-in fornisce rapporti sullo stato di salute e crea stabilità sulla base di questi risultati raggruppati.

Infine, il plug-in JUnit fornisce un editore che utilizza report di test XML generati durante le build e fornisce informazioni dettagliate e significative relative ai test di un progetto.

Configureremo anche Checkstyle nel pom.xml della nostra applicazione :

 org.apache.maven.plugins maven-checkstyle-plugin 2.17 

5. Creazione di uno script pipeline

Innanzitutto, dobbiamo creare un nuovo lavoro Jenkins. Assicuriamoci di selezionare Pipeline come tipo prima di premere il pulsante OK come descritto in questo screenshot:

La schermata successiva ci consente di inserire maggiori dettagli sui diversi passaggi del nostro lavoro Jenkins, come la descrizione , i trigger , alcune opzioni avanzate del progetto:

Entriamo nella parte principale e più importante di questo tipo di lavoro facendo clic sulla scheda Pipeline .

Quindi, per la definizione seleziona Script Pipeline e seleziona Usa Groovy Sandbox.

Ecco lo script di lavoro per un ambiente Unix:

node { stage 'Clone the project' git '//github.com/eugenp/tutorials.git' dir('spring-jenkins-pipeline') { stage("Compilation and Analysis") { parallel 'Compilation': { sh "./mvnw clean install -DskipTests" }, 'Static Analysis': { stage("Checkstyle") { sh "./mvnw checkstyle:checkstyle" step([$class: 'CheckStylePublisher', canRunOnFailed: true, defaultEncoding: '', healthy: '100', pattern: '**/target/checkstyle-result.xml', unHealthy: '90', useStableBuildAsReference: true ]) } } } stage("Tests and Deployment") { parallel 'Unit tests': { stage("Runing unit tests") { try { sh "./mvnw test -Punit" } catch(err) { step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/TEST-*UnitTest.xml']) throw err } step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/TEST-*UnitTest.xml']) } }, 'Integration tests': { stage("Runing integration tests") { try { sh "./mvnw test -Pintegration" } catch(err) { step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/TEST-' + '*IntegrationTest.xml']) throw err } step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/TEST-' + '*IntegrationTest.xml']) } } stage("Staging") { sh "pid=\$(lsof -i:8989 -t); kill -TERM \$pid " + "|| kill -KILL \$pid" withEnv(['JENKINS_NODE_COOKIE=dontkill']) { sh 'nohup ./mvnw spring-boot:run -Dserver.port=8989 &' } } } } }

First, we're cloning the repository from GitHub, then changing the directory to our project, which is called spring-jenkins-pipeline.

Next, we compiled the project and apply Checkstyle analysis in a parallel way.

The following step represents a parallel execution of unit tests and integration tests, then deployment of the app.

Parallelism is used to optimize the pipeline, and have the job runs faster. It's a best practice in Jenkins to simultaneously run some independent actions that can take a lot of time.

For example, in a real-world project, we usually have a lot of unit and integration tests that can take longer.

Note that if any test failed the BUILD will be marked as FAILED too and the deployment will not occur.

Also, we're using JENKINS_NODE_COOKIE to prevent immediate shut down of our application when the pipeline reaches the end.

To see a more general script working on other different systems, check out the GitHub repository.

6. Analysis Report

After creating the job, we'll save our script and hit Build Now on the project home of our Jenkins dashboard.

Here's an overview of the builds:

A little further down we'll find the stage view of the pipeline, with the result of each stage:

Each output is accessible when hovering over a stage cell and clicking the Logs button to see the log messages printed in that step.

We can also find more details of the code analysis. Let's click on the desired build from the Build History on the right menu and hit Checkstyle Warnings.

Here we see 60 high priority warnings browsable by clicking:

The Details tab displays pieces of information that highlight warnings and enable the developer to understand the causes behind them.

In the same way, the full test report is accessible by clicking on Test Result link. Let's see the results of the com.baeldung package:

Here we can see each test file with its duration and status.

7. Conclusion

In questo articolo, abbiamo impostato un semplice ambiente di distribuzione continua per eseguire e mostrare analisi del codice statico e report di test in Jenkins tramite un processo di pipeline .

Come sempre, il codice sorgente di questo articolo può essere trovato su GitHub.