Integrazione continua
# Integrazione continua

Nell'ingegneria del software, lintegrazione continua (continuous integration in inglese, spesso abbreviato in CI) è una pratica che si applica in contesti in cui lo sviluppo del software avviene attraverso un sistema di controllo versione. Consiste nell'allineamento frequente (ovvero "molte volte al giorno") dagli ambienti di lavoro degli sviluppatori verso l'ambiente condiviso (mainline). Il concetto è stato originariamente proposto nel contesto dell'extreme programming (XP), come contromisura preventiva per il problema dell'"integration hell" (le difficoltà dell'integrazione di porzioni di software sviluppati in modo indipendente su lunghi periodi di tempo e che di conseguenza potrebbero essere significativamente divergenti). Il CI può essere considerato come una estremizzazione di idee già presenti in altri metodi precedenti all'XP, per esempio il metodo Booch.

Il CI è stato originariamente concepito per essere complementare rispetto ad altre pratiche, in particolare legate al Test Driven Development (sviluppo guidato dai test, TDD). In particolare, si suppone generalmente che siano stati predisposti test automatici che gli sviluppatori possono eseguire immediatamente prima di rilasciare i loro contributi verso l'ambiente condiviso, in modo da garantire che le modifiche non introducano errori nel software esistente. Per questo motivo, il CI viene spesso applicato in ambienti in cui siano presenti sistemi di build automatico e/o esecuzione automatica di test, come Jenkins. Tuttavia, l'identificazione del CI con l'uso di strumenti di questo tipo, frequente in letteratura, è scorretta: di per sé, la pratica del CI può essere applicata anche a prescindere da sistemi di testing automatico.

## Teoria

Prima di effettuare una modifica sul codice sorgente, uno sviluppatore prende una copia del codice corrente sulla quale lavorare. Man mano che gli altri sviluppatori fanno delle modifiche sul repository, la copia smette di rappresentare il codice del repository. Le modifiche non si riflettono unicamente sul codice, ma anche sulle librerie ed altre risorse che possono creare dipendenze e potenziali conflitti.

Più è lungo il tempo durante il quale un branch di codice rimane scaricato, maggiore è il rischio di conflitti di integrazione quando il branch viene reintegrato nel repository. Quando gli sviluppatori vogliono sottomettere il codice, devono prima aggiornare le proprie copie locali del codice con i cambiamenti che sono stati fatti al repository dal momento in cui loro hanno aggiornato la copia locale. Più modifiche sono state fatte e più lavoro è necessario fare prima di sottomettere le proprie modifiche.

È possibile che il repository sia diventato così diverso dalla copia locale dello sviluppatore che il tempo necessario per integrare le proprie modifiche con quelle fatte dagli altri superi il tempo necessario a fare le modifiche. Questo fenomeno viene descritto come inferno dell'integrazione (integration hell in inglese) o inferno dei merge (merge hell). In uno scenario estremamente negativo, gli sviluppatori potrebbero dover annullare le proprie modifiche e rifarle da capo.

L'integrazione continua è un processo che consiste nell'integrare presto e spesso, limitando le possibilità dell'inferno dell'integrazione. La pratica cerca di minimizzare il lavoro inutile e risparmiare tempo.

## Principi

Di seguito vengono riportati i principi introdotti da Martin Fowler che permettono di svolgere l'integrazione continua.

### Mantieni un repository del codice sorgente

Questo elemento è propedeutico a tutti gli altri principi, perché senza avere un repository del codice è impossibile automatizzare il build ed i test.

### Automatizza il build

Per build si intende il processo che trasforma il codice sorgente in un artefatto eseguibile. Deve essere possibile eseguire la compilazione e la creazione dei pacchetti da mettere sui server in modo completamente automatizzato, senza alcun intervento umano.

### Rendi il build auto-testante

Ogni volta che il codice sorgente viene compilato ed impacchettato, è importante che vengano eseguiti dei test sul sorgente affinché la qualità del codice venga tenuta sotto controllo ed eventuali bug vengano scoperti il prima possibile.

### Tutti eseguono commit alla baseline tutti i giorni

È inutile compilare e testare il sorgente se gli sviluppatori sviluppano codice sui propri computer senza sincronizzarsi spesso col codice scritto da altri. È importante però che il codice sia compilabile ed abbia superato tutti i test.

### Ogni commit fa partire una build

Ogni modifica al codice sorgente condiviso potrebbe generare dei bug e quindi compilare e testare subito dà la possibilità di intervenire immediatamente su eventuali bug.

Questo principio è importante a seguito di un altro principio, detto in inglese fail fast, ovvero se un commit di uno sviluppatore è tale da far fallire un test, bisogna intervenire immediatamente prima che si crei una sequenza di errori successivi a valanga.

### Fai in modo che il build sia veloce

Un build troppo lento può rendere poco agevole il far partire i build automatici dopo i commit, e potrebbe costringere gli sviluppatori ad aspettare la fine del build prima di effettuare un commit o di verificarne l'esito.

### Eseguire i test in un clone dell'ambiente di produzione

Se l'ambiente su cui vengono eseguiti i test non è assolutamente identico all'ambiente di produzione, c'è il rischio che qualcosa che è stato testato generi dei bug inspiegabili una volta rilasciato in produzione, con conseguenti danni economici.

### Fai in modo che sia facile prendere le ultime versioni dei pacchetti

Questo principio serve quando si hanno tanti ambienti che devono essere tenuti allineati.

### Ognuno può vedere i risultati dell'ultimo build

La trasparenza permette di stabilire il livello di qualità raggiunto da ogni modulo e capire quali sono i moduli che hanno bisogno di maggiore attenzione.

### Automatizza i rilasci

Anche il rilascio del software sugli ambienti di test o sull'ambiente di produzione deve essere automatizzato.

