Continuous Delivery: principi e pratiche
Come portare il CD nel proprio team di sviluppo
Non serve essere Netflix per adottare pratiche di Continuous Delivery: si tratta di principi applicabili a qualsiasi dimensione aziendale.
D-Day: il giorno del rilascio
Ogni sviluppatore ha vissuto nella sua vita, almeno una volta, quella sensazione di palpabile tensione che si avverte nel Giorno del Rilascio. Tutti conosciamo le insidie dello sviluppo di un software e comprensibilmente temiamo il momento in cui questo comincerà ad essere utilizzato, svelando i suoi difetti e, con essi, quelli del nostro lavoro.
Se siamo all’inizio della nostra carriera di sviluppatori, la paura del nostro primo rilascio potrebbe immobilizzarci, spingendoci a posporlo il più possibile. Se invece siamo sviluppatori esperti, sarà il fatalismo a farla da padrone: marceremo accigliati incontro al nostro destino e, se ci sarà da debuggare, si debuggerà!
In alcuni casi la preoccupazione per un rilascio è tale da toglierci il sonno la notte, o le notti, precedenti al fatidico Delivery Day. Siamo sicuri che debba essere veramente così?
La paura si vince con la conoscenza: si può forse dunque superare il timore del rilascio trasformando ogni giorno in un D-Day, e rendendo le procedure di rilascio una routine prevedibile ed eseguibile su richiesta. È qui che ci viene in aiuto la pratica del Continuous Delivery.
Are you a release candidate?
Il termine “Continuous Delivery” acquisisce notorietà nel 2010 con la pubblicazione dell’omonimo libro scritto da Jez Humble e David Farley. Evolvendo i concetti di Continuous Integration (CI) figli del pensiero dell’eXtreme Programming di fine anni ’90, il Continuous Delivery si propone di portare cambiamenti di qualunque tipo — incluse nuove features, cambi di configurazione, fix di bugs ed esperimenti — in ambiente di produzione e, quindi, nelle mani degli utilizzatori finali, in modo sicuro, veloce e sostenibile.
In un processo di tipo tradizionale, infatti, dopo lo sviluppo del prodotto seguono una serie di attività volte a far sì che il software sviluppato diventi rilasciabile. L’idea alla base del Continuous Delivery invece è che il software sviluppato debba essere sempre rilasciabile. Ma come arrivarci?
Il punto di partenza è quello, tipico della metodologia Agile, di suddividere il lavoro in singoli requisiti rilasciabili autonomamente. Lo step successivo, concettualmente fondamentale, è l’Integrazione Continua di ogni singolo sviluppo: anziché posporre questa fase a un momento successivo essa viene automaticamente eseguita con il commit. Si crea così un sistema di feedback che rileva se un cambiamento rompe il sistema o non rispetta i requisiti nel momento stesso in cui viene introdotto.
Il Continuous Delivery aggiunge un passo in più: dopo le fasi di build e test il software è automaticamente rilasciato in un ambiente di staging, analogo a quello di produzione, con gli stessi processi e strumenti. Il software prodotto secondo questa prassi, se supera tutti i passaggi e arriva all’ambiente di staging, è quindi di fatto già in condizione di poter essere rilasciato. Ogni cambiamento introdotto nel sistema in questo modo diventa dunque un release candidate, rilasciabile in produzione tramite una nuova versione del software.
E’ possibile portare questo processo al suo estremo automatizzando anche quest’ultimo passaggio, senza l’intervento di una persona per l’approvazione della messa in produzione: è la pratica cosiddetta di Continuous Deployment.
I principi del Continuous Delivery
Tenendo a mente questa concezione di release candidate si possono identificare sei principi essenziali per garantire un processo di rilascio efficace e continuo:
- Automatizzare quasi tutto: molti team di sviluppo non automatizzano il processo di sviluppo perché pare rischioso, complesso e time-demanding. La verità è che quasi tutto (processo di build, test di accettazione, upgrade e downgrade di database, configurazione di network e firewall, e molto altro ancora) può col giusto lavoro essere automatizzato. L’automazione è il prerequisito per una pipeline di deployment che sia affidabile, ripetibile e semplice come premere un bottone.
- Mantenere tutto in controllo versione: ogni piccolo commit di codice, tutto ciò che usiamo per lo sviluppo, il test, il rilascio dei nostri applicativi deve essere conservato con un sistema di versionamento (Git, Subversion, Mercurial o qualsiasi altro VCS). Ogni change set dev’essere referenziato con un numero di versione, e dev’essere sempre possibile identificare quale build dei vari applicativi è rilasciata in un dato momento in ogni singolo ambiente, e da quale versione proviene.
- Affrontare il dolore e costruire sulla qualità: Integration, test, release possono essere momenti dolorosi in un progetto. Per questo non vanno rimandati alla fine, ma anticipati il prima possibile ed eseguiti il più spesso possibile. Questo principio consente non solo di migliorare le competenze del team ma soprattutto di individuare subito i difetti del software e poter intervenire prontamente per correggerli. Scrivendo codice coperto da test quindi si è automaticamente vincolati a scrivere buon codice: è così possibile arrivare al “Build Quality In”.
- Finito vuol dire rilasciato: uno dei più classici problemi nella definizione di un requisito, solitamente espresso sotto forma di user story, è la nozione di “finito”, anche chiamata Definition of Done: la lista di attività che devono essere portate a termine affinché il requisito possa dirsi completato. In realtà, una feature raggiunge il suo scopo solo nel momento in cui viene utilizzata dai suoi utenti: è uno dei motivi alla base del Continuous Delivery. Per eliminare ogni equivoco dunque in un processo di CD si considera finito solo ciò che è già stato rilasciato.
- Ognuno è responsabile: il rilascio di un software richiede tipicamente la collaborazione di più persone (developer, tester, operations team, PO…). Poiché finché non è rilasciato non genera valore per il cliente, il successo di un progetto è sempre un successo di team, mai individuale. Rendere le persone corresponsabili e incoraggiare la loro collaborazione è uno step fondamentale per ottenere rilasci più rapidi e più affidabili.
- Miglioramento continuo: proprio come il rilascio di un’applicazione è solo la prima fase della sua vita, che continuerà ad evolvere, così anche il processo di rilascio deve essere continuamente e incrementalmente migliorato.
Un processo anche per le piccole realtà
A dieci anni dall’uscita del libro di Humble, il Continuous Delivery è celebre per essere utilizzato in molte grandi aziende del mondo digitale come ad esempio Google o Yahoo. Il deployment engine di Amazon gestisce oltre 50 milioni di rilasci l’anno mentre Facebook rilascia dai 500 ai 1.000 cambiamenti al giorno.
Il CD non è tuttavia una questione di scala: è basato su un set di principi che possono essere trasformati in pratica in modo diverso ma con uguale successo a seconda del contesto in cui opera ogni team di sviluppo, anche in aziende di piccole dimensioni.
Quel che raccontiamo di seguito non ha la pretesa di essere esaustivo; è il frutto dello studio e dell’esperienza maturate nella nostra realtà, Mia-Platform, un’azienda informatica che conta circa 40 sviluppatori.
Continuous Delivery in Mia-Platform
Mia-Platform fornisce il proprio software a molte aziende differenti, che lo utilizzano per lo sviluppo di applicazioni che servono complessivamente milioni di utenti. Si pone dunque la necessità di conciliare i rilasci del proprio prodotto con gli sviluppi, gli aggiornamenti e la manutenzione degli applicativi dei clienti, ciascuno dei quali ha i propri tempi e le proprie esigenze.
Gestire una tale complessità non è banale: il processo di delivery tradizionale, che prevedeva build e test manuali, ci ha creato negli anni più di un grattacapo. Non era infrequente la situazione in cui, a seguito di un rilascio a fine giornata, ci si trovasse poi a dover riparare il software a orari improbabili, perché l’integrazione del software e il suo funzionamento non erano stati prima debitamente testati e verificati; talvolta addirittura si poteva incorrere in problemi perché non sempre l’immagine che era testata era poi la stessa che veniva rilasciata.
Uno dei nostri team, al lavoro su un progetto specifico, ha deciso in accordo con gli altri di sperimentare e portare all’interno del proprio percorso di rilascio alcuni principi di Continuous Delivery, trasformandoli in pratiche concrete adoperabili nel proprio contesto.
Vediamole insieme:
- Obiettivi pianificati: La pianificazione stabilisce gli obiettivi di rilascio per ogni ciclo di lavoro, che ha una periodicità definita (tipicamente settimanale). Ogni mattina poi il team si aggiorna e condivide ciò che verrà sviluppato e rilasciato quel giorno. La board del team (fisica o digitale che sia) consente di tenere gli obiettivi sott’occhio, mantiene il team allineato e aiuta ad attuare il principio dell’“Everyone is Responsible”.
- Pipeline di deployment automatica: Il codice sviluppato e versionato attiva una pipeline automatica di build, unit test e test di accettazione. Il Product Owner, interno al team, verifica subito i requisiti di accettazione del cliente e abilita il rilascio automatico in ambiente di staging, dove il software è sottoposto a un’ulteriore validazione. In modo continuo, nel corso di ogni sprint, durante le finestre di rilascio prestabilite le feature pronte passano dall’ambiente di staging a quello di produzione, tramite un deployment automatico che viene azionato manualmente.
- Finestre di rilascio: non sempre il business servito — il cliente — rende possibile rilasciare in produzione in ogni momento. Analizzando il traffico e l’utilizzo da parte degli utenti è possibile individuare i momenti migliori per i rilasci a seconda delle esigenze specifiche. Le finestre temporali sono generalmente dipendenti dalle applicazioni e dal dominio applicativo (es. macchine non disponibili in determinate fasce orarie), e comprendono sempre anche il tempo per eventuali rollback, come il re-deployment della versione precedente.
- Small batches: il batch work (accorpare insieme feature differenti, bug fixes, ecc.) è nemico dei developer perché aumenta la possibilità di fallire il rilascio. La complessità di merge infatti non aumenta linearmente rispetto alla quantità di codice rilasciato. Un’eventuale roll-back inoltre invalida tutto il lavoro fatto, incoraggiando il team a scomporre il lavoro in singole feature e procedere per cicli di sviluppo incrementali.
- Versionamento rigoroso: poiché si rilascia molto spesso in tutti gli ambienti, è fondamentale sapere sempre che cosa è rilasciato in ogni ambiente. Per questo ogni applicazione e servizio espone un proprio numero di versione.
I risultati ottenuti sono stati estremamente positivi: dopo un primo periodo di assestamento e di messa a punto del processo, il team ha incrementato in modo esponenziale il numero dei propri rilasci, che oggi sono anche varie decine al giorno.
Allo stesso tempo i rilasci che causano rotture critiche sono pressoché scomparsi, perché i cambiamenti che rompono il sistema vengono automaticamente bloccati prima di arrivare in produzione.
Molti degli insegnamenti appresi da questo team sono diventati patrimonio comune e pratica condivisa per tutti i team di Mia-Platform. Ogni singolo progetto software ha il proprio contesto e le proprie esigenze specifiche, e dunque non sempre è possibile estendere a tappeto i processi in modo uniforme; i principi alla base però rimangono validi per tutti e sono oggi un riferimento imprescindibile nel percorso di sviluppo dell’intera azienda.
In conclusione
I principi di Continuous Delivery, applicati nella pratica secondo il contesto in cui opera ogni team di sviluppo, consentono di sconfiggere la paura del rilascio e far evolvere il software in modo più rapido, semplice e affidabile. Anche grazie a questi principi oggi riusciamo a gestire l’intricata trama dello sviluppo di molteplici prodotti e applicativi, e vivere i rilasci come una normale routine.
Un buon processo di delivery, nella nostra esperienza, è automatico, è uguale per tutti gli ambienti, comprende anche le infrastrutture, prevede due step separati per build e deploy, è attivabile da chiunque all’interno di un team, segue un versionamento rigoroso e consente in modo continuo il rollback del software.
I costi principali risiedono nella scrittura dei test e nell’automazione dei processi, nella suddivisione dei progetti in singole feature da sviluppare, e nel tempo necessario alle persone per adattarsi al nuovo processo di sviluppo. Nessuno di questi costi dovrebbe essere un freno tale da scoraggiare questa strada, dati i numerosi benefici che essa comporta tanto per l’azienda come per i suoi clienti.
Questo articolo è frutto del lavoro fatto dai nostri colleghi Tommaso Ballardini e Riccardo Porrini e del loro talk “It Starts With a Goal”: si deve a loro l’esperienza diretta e la razionalizzazione dei concetti espressi nel testo.
Riferimenti
- https://www.slideshare.net/TommasoBallardini/tommaso-ballardini-ilgiornodelrilasciov120190608
- https://www.slideshare.net/RiccardoPorrini/it-starts-with-a-goal-continuous-delivery-of-an-api-platform
- “Continuous Delivery”, by Jez Humble and David Farley, Addison-Wesley, 2010
- https://continuousdelivery.com/
- https://it.atlassian.com/continuous-delivery/principles/continuous-integration-vs-delivery-vs-deployment
- https://dzone.com/articles/jenkins-pipeline-for-continuous-delivery-and-deplo
- https://www.thoughtworks.com/insights/blog/case-continuous-delivery