Durante lo sviluppo di un'applicazione, c'è sempre una piccola apprensione al momento del rilascio in produzione. Questa piccola voce che ti dice "il mio codice non romperà nulla?" o ancora "sono sicuro di aver superato tutti i test prima di fare il push?". Questo timore è tanto più giustificato quando arrivi su un progetto esistente e non hai ancora una conoscenza globale di quest'ultimo.
Peggio ancora quando sei sviluppatore su questo progetto e ne arriva uno nuovo, non si è più rassicurati. Anche se si sono definiti dei test,
nulla ci assicura che gli sviluppatori li lancino prima del rilascio in produzione. È qui che i ruoli de
l'integrazione continua (
CI) e dello sviluppo continuo (
CD) acquisiscono pieno significato.
GitLab CI/CD è una funzionalità di GitLab che permette di implementare pipeline di CI/CD per qualsiasi progetto, che sia nuovo o esistente, a patto che utilizzi Git.
Motivazioni
Per chi?
Puoi usare GitLab CI/CD anche senza ospitare il tuo progetto su GitLab, scegliendo l'opzione "Run CI/CD for external repository". Se usi GitHub, potrai così vedere lo stato della tua pipeline dopo aver fatto il push di un commit:
Perché?
Implementare la CI/CD con GitLab ti permette di automatizzare le fasi:
di integrazione continua: Build > Tests (unitari, di integrazione, di non regressione...)
di deployment continuo: Review > Deployment (staging, production...)
Questa automazione accelera la produzione di codice: un solo commit è sufficiente ad attivare una pipeline lato GitLab che si occuperà di generare un build di produzione, lanciare la suite di test ed effettuare il deployment della nuova versione in staging/production! Questo permette anche di aumentare la fiducia degli sviluppatori e la qualità del codice inviato in produzione, poiché si ha la certezza che ogni modifica sia passata attraverso questo processo.
Implementazione
Gli stages
Analizzeremo il caso pratico dell'implementazione di una pipeline di CI/CD per un'applicazione web scritta in JavaScript e che utilizza Next.js. In un primo momento, bisogna definire i diversi stages della pipeline di CI/CD che si desidera creare. Ti propongo una suddivisione in tre stages: Build, Tests e Deploy.
Questi stages sono lanciati sequenzialmente e sono composti da jobs. Uno stage deve contenere almeno un job, questi ultimi vengono eseguiti in parallelo per impostazione predefinita. Ecco la struttura della pipeline che implementeremo, libero di adattarla:
Ci ritroviamo i nostri tre stages : Build, Tests e Deploy. Su questo schema, gli stages Tests e Deploy possiedono ciascuno due jobs.
Per descrivere l'architettura della nostra pipeline a GitLab, dovremo creare un file .gitlab-ci.yml alla radice del nostro progetto e aggiungervi queste righe:
Vediamo qui più in dettaglio il contenuto del nostro file:
image ti permette di specificare l'immagine Docker da usare per lanciare la tua pipeline, naturalmente da adattare in base alle tue esigenze,
cache ci permette qui di mantenere in cache i nostri node_modules per evitare di doverli scaricare di nuovo ogni volta,
Infine,
stages ci permette di definire i nostri diversi stages all'interno della pipeline.
I jobs
Bene, gli stages sono stati definiti, ma come ho menzionato in precedenza, uno stage deve contenere almeno un job, altrimenti la nostra pipeline non esegue nulla e non ha interesse. Vediamo quindi come definire il nostro primo job, build, aggiungendo queste righe a seguire nel nostro .gitlab-ci.yml:
Qui, il nome del nostro job è
build, e si trova all'interno dello stage
build. La parte
script definisce
la mia procedura di build per il mio progetto che utilizza Next.js e genera al termine del comando
next export una cartella
out che contiene i miei file generati.
L'utilizzo della parola chiave artifacts qui mi permette di definire file e/o cartelle che verranno archiviati all'interno di questa pipeline per essere eventualmente passati ad altri jobs più tardi. Nel nostro caso, specifichiamo la cartella out che contiene i nostri file generati per passarli più tardi al job deploy.
Ora possiamo aggiungere i jobs corrispondenti allo stage di tests. Aggiungi queste righe dopo il tuo .gitlab-ci.yml:
L'aggiunta di più jobs a uno stage avviene senza difficoltà, si definisce semplicemente per ogni job lo stage a cui appartiene, qui tests. I runners di GitLab utilizzano la nostra immagine Docker node:12.1.0 che non contiene Jest di default: aggiungiamo quindi la dipendenza richiesta prima di lanciare i comandi di cui abbiamo bisogno.
Questi due jobs si lanceranno in parallelo l'uno all'altro, non appena l'étape precedente tests sarà terminata. Possiamo passare all'ultima tappa: il deployment.
L'ambiente
In questo articolo, ho scelto di optare per un deployment utilizzando SSH, puoi ovviamente adattare i comandi se utilizzi altri servizi come AWS S3 o GCP. GitLab offre la possibilità di utilizzare variabili d'ambiente per evitare di scrivere gli identificativi di connessione al servizio di deployment direttamente nel file .gitlab-ci.yml.
Per definire variabili d'ambiente, vai sull'interfaccia GitLab e recati in Settings > CI / CD > Variables. Ho aggiunto una variabile USER_PASSWORD corrispondente alla password della mia connessione SSH.
Ora possiamo scrivere i nostri ultimi due jobs, che permettono di deployare il sito in staging e in produzione! Ti propongo di vedere il job di staging per prima cosa:
Diversi punti da vedere qui. Innanzitutto, un resource_group pari a deploy è stato definito per il job. Per farla semplice, non è possibile per i runners di GitLab che eseguono le nostre pipeline lanciare due jobs appartenenti allo stesso resource_group in parallelo, anche se questi jobs si trovano in due pipeline diverse in corso. Qui vogliamo impedire più deployments verso il nostro server per avere una sola connessione alla volta che invia i file.
La parola chiave dependencies specifica il o i jobs di cui vogliamo recuperare gli artifacts. Abbiamo fatto in modo che il nostro job build invii la cartella out come artifacts, quest'ultimo verrà quindi recuperato dal job deploy_staging.
Infine, la parola chiave only permette di specificare da quali branch il job può essere eseguito. Qui, ho scelto di restringere i deployments dalla branch master.
Siamo tuttavia in diritto di porci una domanda: qual è la differenza tra il nostro job deploy_staging e il nostro job deploy_production ? Dopotutto, deploy_production sarebbe identico, ad eccezione del comando di deployment.
I template
GitLab ha implementato un sistema di templates che permette il riutilizzo del codice, rispettando così i
principi di sviluppo DRY. Nel nostro caso, la quasi totalità del codice del job deploy_staging può essere riutilizzata per deploy_production. Ti propongo quindi di modificare il nostro .gitlab-ci.yml per definire questi due jobs come segue:
Definiamo così un template iniziando il suo nome con un punto. Per referenziare il template, basta quindi includerlo con la parola chiave <<: e di referenziare il suo nome con un asterisco *. Una piccola sottigliezza qui: non vogliamo che il contenuto dello script definito nei jobs deploy_staging e deploy_production sovrascriva lo script del template. GitLab permette di definire in particolare tre parole chiave: before_script, script e after_script. Ho quindi scelto di posizionare i comandi del template in before_script affinché vengano eseguiti prima del comando di trasferimento file in SSH.
Ho inoltre aggiunto per il deploy in produzione l'istruzione when: manualQuest'ultima indica a GitLab che il job potrà essere eseguito solo tramite attivazione manuale (e solo se i job precedenti sono andati a buon fine!).
Risultati
Ecco come appare la nostra pipeline finale vista dall'interfaccia di GitLab. Vediamo chiaramente i nostri 3 stage e i loro job associati, così come il job deploy_production che può essere deployato solo manualmente.
Se desideri essere notificato su Slack, Discord o un'altra applicazione dello stato delle tue pipeline durante un push, puoi andare su GitLab e navigare in Settings > Integrations e attivare le notifiche corrispondenti.
Conclusione
Ora conosci le basi per l'implementazione di una pipeline CI/CD con GitLab! Ovviamente, è inutile dire che l'interesse di questo approccio è minore se non scrivi test per le tue applicazioni.
Scrivi test e approfitta dei vantaggi dei servizi di GitLab per migliorare il tuo flusso di sviluppo e aumentare la tua produttività!