L'approccio CI/CD, o Continuous Integration / Continuous Delivery, è ormai un tassello molto importante nell'applicazione delle metodologie di sviluppo agile
Chi si occupa di creare applicazioni ha quasi certamente già adottato approcci per lo
sviluppo cosiddetto Agile e in ottica DevOps. Al di là delle sigle sempre un po' esoteriche, l'obiettivo comune di tali approcci è velocizzare e
sistematizzare il percorso che va dallo sviluppo di una applicazione al suo rilascio in produzione. Da questo punto di vista, ultimamente si è aggiunto un elemento di complessità in più rispetto a quando si è iniziato a parlare di sviluppo Agile: lo sviluppo non è più una attività (relativamente) centralizzata ma è
distribuito su molte piattaforme e tool diversi.
Per fare un paragone che rende l'idea, anche se magari non è proprio perfetto, è come se chi sviluppa applicazioni fosse passato dal controllare una catena di montaggio interna a una fabbrica
all'assemblare componenti che vengono da tanti fornitori diversi. Il nuovo processo richiede maggiore controllo e magari anche procedure automatiche che evitino gli errori causati da questa maggiore complessità.
In estrema sintesi,
la Continuous Integration (CI) è proprio questo: un approccio e un insieme di best practice attraverso cui gli sviluppatori apportano modifiche frequenti ma proprio per questo contenute al loro codice, validandole e integrandole in modo coerente ogni volta. Il nodo della
coerenza è importante, perché non esiste "la" Continuous Integration e ciascun team di sviluppo può definirne una propria, però questa deve essere comunque un
processo consistente e automatizzato di scrittura di codice, generazione di moduli e test delle modifiche.
In questo flusso manca la parte di implementazione - è solo il
Dev di DevOps - e infatti la CI non va quasi mai avanti da sola. È la prima metà del binomio
Continuous Integration / Continuous Delivery (CI/CD), in cui la delivery è l'implementazione del nuovo codice (o dei nuovi servizi) dove è più opportuno, con anche l'aggiornamento di eventuali componenti infrastrutturali interessati dal nuovo codice.
In tutto questo vanno messi in evidenza due punti. Il primo, minore, è che le operazioni automatizzate della CI/CD ovviamente
riguardano gli ambienti di produzione, ma non solo quelli: ci sono ad esempio anche gli ambienti di test e sviluppo. Il secondo, più importante, è che si parla sempre di CI/CD ma è molto meglio considerare la "coppia" come
un trio che comprende anche il Continuous Testing. Non serve a nulla - ed è anzi dannoso - automatizzare e velocizzare il rilascio e l'implementazione di
codice di cattiva qualità. Di Continuous Delivery e Continuous Testing parleremo più approfonditamente in un altro articolo.
Continuous Integration: i vantaggi
Il fattore chiave che spinge l'adozione di strumenti di Continuous Integration è che questa in definitiva
porta a un tasso minore di errori nel codice. Il motivo è presto detto: la CI è
continua proprio perché spinge ad uno sviluppo continuo, ossia ad integrare nel codice esistente modifiche o aggiunte frequenti (anche quotidiane) e di piccole dimensioni. In questo modo
è più facile evidenziare eventuali errori o inconsistenze introdotte dalle modifiche.
È importante notare che si parla di Continuous Integration e non di continuous development. Non basta avere uno sviluppo frequente,
deve esserlo anche l'integrazione del nuovo codice in quello esistente. Per essere un po' più tecnici alla
GitHub, il punto è eseguire piccoli commit frequenti, "fissando" le modifiche spesso in modo che non ci siano commit di tante modifiche fatte in un lasso di tempo più lungo, eventualità che tra l'altro aumenta il rischio che sviluppatori diversi
modifichino le stesse parti di codice.
La Continuous Integration richiede attenzione
I benefici e l'automazione della Continuous Integration non evitano ai team di sviluppo di
doversi organizzare bene. Anzi, specie nelle prime fasi di adozione delle tecniche e
degli strumenti di CI/CD bisogna arrivare a una idea chiara e comune di
cosa significhi modificare spesso il codice e, soprattutto, del raggio d'azione che possono avere i commit frequenti.
Il punto critico principale è che una attività di sviluppo basata sulla Continuous Integration
seguirà inevitabilmente diversi flussi paralleli, anche se si "installa" su un team di sviluppo che cercava di non averne. Questo accade banalmente perché alcune funzioni che si vogliono aggiungere al proprio codice richiederanno certamente un tempo di sviluppo molto superiore alla frequenza dei commit che si giudica ideale per evidenziare e limitare gli errori.
Serve quindi definire, in sostanza,
una strategia coerente per il branching del codice. Idealmente si mantiene un "filone" principale di sviluppo che viene aggiornato spesso, mentre le modifiche che richiedono tempo costituiscono un ramo di sviluppo parallelo, che verrà riportato a quello principale solo una volta completato. Non è un approccio concettualmente complicato ma
può diventare difficile da gestire quando i rami di sviluppo paralleli diventano troppi, segno probabilmente che il piano di sviluppo complessivo dell'applicazione o del servizio va riconsiderato.