CI/CD best practice

La Continuous Integration (CI) e la Continuous Delivery (CD), in breve CI/CD, sono ormai parte integrante di un modo di sviluppare inteso a ridurre gli errori durante l'integrazione e la successiva distribuzione di nuove features. Queste due pratiche semplificano fortemente il ciclo di sviluppo e rilascio, rendendolo al contempo più solido e resiliente, e aumentando considerevolmente la qualità delle applicazioni.

POTREBBE INTERESSARTI ANCHE: Come introdurre DevOps in azienda

In questo articolo analizziamo alcune delle best practice che è consigliabile seguire per essere supportati al meglio da pipeline costruite per la CI/CD.

 

Conosci già le potenzialità della Site Reliability Engineering?  Scarica la guida e dai una marcia in più alle tue applicazioni!

 

Misura in termini qualitativi e quantitativi l'efficacia del tuo processo agile

Un qualsiasi processo ripetibile deve poter essere misurato: fare integrazione e delivery continue significa ripetere decine, se non centinaia di volte al giorno, i processi di build, test e rilascio. Come monitorare l'andamento di queste pipeline?

In un contesto Enterprise che sposa una metodologia di sviluppo Agile come Scrum o Kanban, strumenti come Gitlab e Jira1 possono essere usati per l'intero ciclo di vita dell'applicazione per pianificare, tracciare e monitorare lo sviluppo di nuove features e il rilascio di bugfix. Al contempo permettono di beneficiare di dashboard, kanban board, punteggi e traguardi raggiunti per avere metriche utili per valutare in ogni momento lo stato del progetto.

In ultimo, risulta utilissima l'integrazione diretta che alcuni di questi tool supportano (User Story -> Pull Request) con la branching strategy (come Gitflow2) adottata dal proprio team di sviluppo.

Promuovi il testing come attitudine di sviluppo, oltre che nell’automazione

Il modo migliore per fare testing efficace è dividere il processo in più fasi: gli scripts di unit testing vanno predisposti fin da subito e fatti girare durante lo sviluppo e come git hooks usando strumenti come Pre-commit3 o typicode/husky. Esistono librerie ad hoc per ogni linguaggio, quali Jest4, il modulo testing di Golang5, PHPUnit o PyTest/PyMock6.

Nella fase di run di una pipeline CI/CD è utile far girare l'intera suite di testing, che includa test unitari, test funzionali ed anche end-to-end, usando strumenti come Selenium o Cypress7. In quest'ottica, è utile predisporre il mock dei dati o quantomeno avere script di fixture/seed e infrastrutture quanto più possibile immutabili (IaaC), pronte ad essere create on-demand, usate per il testing, e poi distrutte di modo da abbattere i costi di mantenimento delle stesse.

È importante anche introdurre tool di non regressione visuale, che permettono di testare che le interfacce multipiattaforma non siano affette da regressioni visuali, usando tool come BackstopJS o Percy8.

In contesti nei quali la solidità del rilascio è mission critical e non è ammessa l'introduzione di regressione, può essere molto efficace affiancare agli script di automazione del testing l'adozione di una tecnica di sviluppo come la TDD (o Test Driven Development)9.

Un processo che si ripete, come una pipeline CI/CD, deve essere veloce

Per velocizzare una pipeline di CI/CD, si può fare affidamento su soluzioni on-demand in grado di esaurire un maggior numero di richieste all'aumentare del carico di lavoro: Gitlab, Github Actions, Travis CI, CircleCI10 sono tutte valide alternative. Ci sono anche soluzioni serverless o ibride in cui parte del vecchio hardware on-premise può essere riciclato come forza lavoro per gestire processi di build e testing, anche orchestrati da soluzioni cloud-based come quelle citate. Esistono tecniche di caching gestite dai vari package manager (Composer, Yarn, npm11) e best practice per la costruzione di docker container che massimizzano la riusabilità degli step precedenti, senza ripercorrere i passi di build inutilmente.

LEGGI ANCHE: Cos'è GitOps e quando adottarne le pratiche?

Promuovi rilasci piccoli e testati per ridurre il rischio di errore

Molti dei tool supportati dai vendor più presenti sul mercato e mantenuti dalle community più attive, quali Docker, Terraform, Hugo, Node e altri, vengono rilasciati seguendo il principio del Semantic Versioning12, talvolta quasi quotidianamente. Il modo migliore per adottare lo stesso approccio è dotarsi di tecniche di deploy all'avanguardia, come il canary deployment, che permette di rilasciare un pacchetto a un mirato parco di utenti in fase esplorativa, e solo successivamente promuovere un rolling update su chiunque.

Allo stesso tempo, è bene promuovere una tecnica di sviluppo che sposi i concetti di immutability, DRY e KiSS principle, anche in fase di rilascio: vale a dire, build frequenti, riproducibili facilmente, senza ripetizioni (sia a livello di codice sia a livello di produzione degli artefatti), e con un numero quanto più possibile ridotto di features per volta.

In contesti dove il rilascio è mission-critical e/o non è possibile isolare un parco di utenti su cui effettuare dei test preliminari, è bene avvalersi di tecniche di rilascio più solide (e costose), come la Blue Green.

Conclusioni

Una delle sfide più grandi, come gran parte delle sfide da vincere nel mondo dello sviluppo Cloud Native e del DevOps, è il cambio di attitudine nella produzione di codice.

Seguire questi principi base può aiutare a implementare in modo efficace pipeline di CI/CD e rafforzare la fase di testing e sviluppo di un prodotto o un servizio, sposando al contempo principi validi e opinionated.

guida SRE


Referenze

1: Jira è uno strumento di sviluppo software usato dai team agile worldwide. Gitlab è un'altra valida piattaforma per mantenere il team organizzato e connesso.

2: Gitflow Workflow è un modello di branching strategy che ruota attorno alle release di un dato progetto: maggiori informazioni qui.

3: Pre-commit è un framework per la gestione e la manutenzione di hook pre-commit multilingue.

4: Jest è un framework per il testing in Javascript che funziona con Babel, TypeScript, Node, React, Angular, Vue e tanti altri.

5: Il modulo testing di Golang fornisce supporto per i test automatici dei pacchetti in Golang.

6: Il framework PyMock è per gli sviluppatori che vogliono implementare unit-testing in Python. Il framework PyTest semplifica la scrittura di piccoli test, ma si adatta a supportare test funzionali complessi per applicazioni e librerie in Python.

7: Selenium è uno dei più diffusi tool per l’automazione del browser, utilizzato principalmente per web testing automatico. Cypress è un tool che rende i test più veloci, semplici e affidabili.

8: BackstopJS è un tool di visual regression testing per le web apps. Percy è una piattaforma di visual review che permette di automatizzare i visual testing.

9: Il Test-driven development si deve a Kent Beck, uno dei padri dell'extreme programming (XP) e delle metodologie agili.

10: Esistono molti provider con diversi piani d'uso gratuiti e integrati con diversi piattaforme di versioning: tra questi ricordiamo Gitlab, Github Actions, Travis CI e CircleCI. A fine 2019 Github rilascia al pubblico le Github Actions che si integrano direttamente con Github e permettono di usare nodi di build esterni in aggiunta a quelli in cloud.

11: Alcuni package manager come Yarn e NPM forniscono sistemi integrati di caching: Codefresh ne parla, e si mette in campo come valida alternativa, qui.

12: Il semantic versioning consiste in un semplice ed efficace insieme di regole e requisiti che determinano come vengono assegnati e incrementati i numeri delle release.