- Teoria SCM (Git vs SVN)
- Centralizzato vs Distribuito
- Snapshot vs Delta
- Gestione Conflitti
- Strategie di Branching
- Continuous Integration & Code Analysis
- Motivazioni e Tool
- Analisi Statica e SonarQube
- Maven Deep Dive
- Alternative (Make, Ant, Gradle)
- Lifecycle
- Dipendenze Transitive
- Indipendenza IDE & Spotless
- Virtualizzazione e Docker
- Containers vs VMs
- Terminologia Docker
- Sicurezza della Supply Chain
- AI in DevOps
1. Teoria SCM (Source Control Management)
Il controllo di versione è la spina dorsale dello sviluppo collaborativo. Gestire il codice in team richiede
sistemi robusti per prevenire perdite di dati e risolvere sovrapposizioni.
- Centralizzato (SVN): Un unico server centrale contiene la history del repository. Ogni
sviluppatore scarica solo l'ultima versione dei file. Operazioni come
commit o l'analisi
della history richiedono una connessione costante al server. Se il server cade, nessuno può lavorare.
- Distribuito (Git): Ogni client possiede una copia locale completa
(clone) dell'intero repository, con tutta la history. Le operazioni sono istantanee e offline. La
sincronizzazione (push/pull) avviene solo quando necessario verso un server condiviso (es. GitHub o
GitLab).
- Sistemi Delta-based (SVN): Memorizzano solo le differenze (delta) tra la versione base
di un file e le sue modifiche successive. Per ricostruire la versione attuale, il sistema deve sommare
tutti i delta.
- Sistemi Snapshot (Git): A ogni commit, Git scatta una "fotografia" (snapshot) di come
appare l'intero file system in quel momento. Se un file non è cambiato, Git memorizza un semplice
collegamento alla versione precedente. Questo rende Git incredibilmente veloce nel checkout e nel
branching.
I vecchi sistemi usavano il modello Lock-Modify-Unlock (un file poteva essere modificato da una
sola persona alla volta bloccandolo globalmente). Git usa il Copy-Modify-Merge: tutti
possono modificare copie locali in parallelo senza bloccare nessuno. Quando avviene un push, se due
sviluppatori hanno toccato la stessa riga, Git segnala un conflitto e delega allo
sviluppatore il compito di risolvere manualmente la sovrapposizione prima di completare la merge definitiva.
2. Strategie di Branching (Workflow)
Come organizzare il lavoro in team quando decine di sviluppatori contribuiscono in contemporanea allo stesso
repository.
Un workflow molto strutturato, ideale per prodotti
enterprise con cicli di rilascio lenti e pianificati.
- Usa rami a lunga vita:
main (solo codice in produzione stabile) e
develop (integrazione continua delle nuove feature).
- Le nuove funzionalità nascono isolatamente nei
feature branches e poi confluiscono in
develop.
- Prima di un rilascio, si crea un
release branch per il collaudo e il bugfixing dell'ultimo
minuto.
- Per problemi critici scoperti in produzione, si aprono rami
hotfix direttamente dal
main.
Il workflow moderno preferito dalle metodologie agili
DevOps e dal Cloud Native.
- Tutti gli sviluppatori committano e fondono codice frequentemente (anche più volte al giorno)
direttamente su un unico ramo principale (chiamato
main o trunk), o su
feature branch di brevissima vita (poche ore).
- Elimina i blocchi organizzativi e il "Merge Hell" (la difficoltà immane di unire rami vecchi di
settimane).
- Prerequisito vitale: Lavorare tutti su
main richiede una suite di
test automatizzati rigorosi (CI/CD) per garantire che il codice sia sempre "deployable".
Spesso si usano i Feature Toggles per nascondere agli utenti reali funzionalità ancora non
finite.
3. Continuous Integration & Code Analysis
La Continuous Integration serve a mitigare il rischio di integrazione tardiva e la complessità di integrare codice sviluppato in isolamento per troppo tempo.
Integrare frequentemente il codice (almeno una volta al giorno) permette di rilevare tempestivamente i bug, riducendo l'"Integration Hell".
- Strumenti Storici e Attuali: Hudson e il suo fork Jenkins sono stati i pionieri open-source, basati su server standalone. Bamboo è la soluzione enterprise di Atlassian. Oggi il mercato si sta spostando su soluzioni cloud-native integrate direttamente nella piattaforma di repository, come GitLab CI/CD e GitHub Actions.
Le pipeline di CI moderne non si limitano a compilare il codice, ma includono fasi automatizzate di Analisi Statica (Static Application Security Testing).
- SonarQube: È lo standard di mercato per la code quality. Analizza il codice sorgente per individuare vulnerabilità (Bugs), pattern di programmazione errati (Code Smells) e misurare la copertura dei test (Test Coverage).
- Quality Gates: Regole booleane configurate in SonarQube (es. "Copertura Test > 80%"). Se il codice non supera il Quality Gate, la pipeline di CI/CD si blocca (fail) e il branch non può essere unito (merge) al ramo principale.
4. Maven Deep Dive
Maven non è solo un semplice scaricatore di librerie, ma un orchestratore potente dell'intero ciclo di vita
(build lifecycle) del software Java.
- Make: Il primissimo build tool, basato su Makefile (script shell-like). Estremamente flessibile ma considerato difficile da mantenere e da debuggare per progetti complessi.
- Apache Ant: Nato in ambito Java, sostituiva i Makefile con file XML (
build.xml). È estensibile tramite task ma, storicamente, mancava di un supporto nativo per la gestione automatica delle dipendenze (aggiunta solo dopo con Apache Ivy), costringendo a check-in manuali dei file .jar.
- Gradle: L'alternativa moderna a Maven. Più veloce perché non forza un lifecycle rigido e definisce le dipendenze basandosi su grafi diretti aciclici (DAG) di task. È scritto in Groovy o Kotlin ed è diventato il tool di build predefinito per Android.
Maven definisce una sequenza ordinata e logica di fasi.
Chiamando l'esecuzione di una singola fase, Maven eseguirà automaticamente in sequenza tutte le fasi
precedenti ad essa nell'albero.
validate: Controlla che il progetto sia corretto (sintassi pom.xml) e tutte le
info siano disponibili.
compile: Prende il codice sorgente (.java) e lo compila in bytecode
(.class).
test: Esegue i test unitari usando framework standard (come JUnit) bloccando la build se un
test fallisce.
package: Impacchetta il codice appena compilato e collaudato (es. in un archivio
distributivo .jar o .war).
verify: Lancia test di integrazione pesanti sul pacchetto per verificarne ulteriormente la
validità nel contesto reale.
install: Copia il pacchetto nel repository locale della macchina (nella cartella
.m2) per renderlo utilizzabile come dipendenza da altri progetti Maven locali dello stesso
sviluppatore.
deploy: Carica in modo sicuro l'artefatto compilato in un repository remoto o aziendale
(es. Nexus, Artifactory) per la condivisione finale con l'intero team.
Il meccanismo "transitivo" è il cuore del gestore di dipendenze. Se il tuo pom.xml richiede la
libreria A, e chi ha sviluppato la libreria A ha indicato nel suo
pom che ha bisogno della libreria B, Maven scaricherà automaticamente anche
B nel tuo progetto.
Gestione Conflitti di versione:
Spesso il modulo X scarica la libreria C in versione 1.0, mentre il modulo Y scarica la stessa libreria C in
versione 2.0. Quale viene tenuta nel pacchetto finale? Maven applica algoritmi di mediazione, generalmente
vince la "nearest definition": sceglie la dipendenza che appare più "vicina" alla radice nell'albero
gerarchico delle dipendenze.
- Indipendenza dall'IDE: Una regola ingegneristica fondamentale è che Maven deve essere l'astrazione finale della build. Un progetto deve potersi compilare, testare ed impacchettare correttamente da riga di comando (es.
mvn clean install) senza alcuna dipendenza dalle configurazioni o dai plugin locali dell'IDE (IntelliJ, Eclipse, VS Code) di chi sta programmando. Questo garantisce che la build funzioni in modo deterministico anche sui server di Continuous Integration.
- Formattazione automatica (Spotless): È vitale usare plugin Maven come Spotless per applicare e forzare uno standard di formattazione del codice unico per tutto il team. Questo evita che su Git si creino "rumori" e finti conflitti dovuti a semplici differenze di tabulazioni, spazi o fine riga introdotti dai vari IDE degli sviluppatori.
5. Virtualizzazione e Docker
I Container rappresentano la rivoluzione del deployment moderno, impacchettando il codice assieme a tutte le sue dipendenze di sistema in un formato standardizzato e portabile.
- Macchine Virtuali (VM): Virtualizzano l'hardware. Includono sempre un intero sistema operativo "Guest" completo, che gira sopra un Hypervisor. Sono pesanti (Gigabyte), lente ad avviarsi e sprecano risorse per far girare processi OS ridondanti.
- Containers: Virtualizzano il sistema operativo. Più container condividono lo stesso kernel del sistema operativo host, isolando solo lo spazio utente (filesystem, processi, rete). Sono leggerissimi (Megabyte), si avviano in millisecondi e massimizzano l'efficienza delle risorse.
- Image: È il pacchetto statico, immutabile, che contiene il codice, le librerie e gli strumenti necessari. Rappresenta i dati "a riposo" (template).
- Container: È un'istanza viva e in esecuzione di un'Image. Può essere creata, avviata, fermata o distrutta.
- Engine: Il software runtime di base (il demone Docker) installato sul server che ha il compito pratico di creare, eseguire e gestire i Container.
- Registry: Un magazzino centralizzato (es. Docker Hub) dove vengono archiviate, versionate e distribuite le Image per essere scaricate e usate nei deployment.
6. Sicurezza della Supply Chain
Oggi nessuna azienda costruisce un software interamente da zero. I progetti moderni sono assemblaggi di decine
di librerie scritte da terzi open-source. Questo apre a rischi catastrofici se uno di questi anelli della catena
di fornitura (Supply Chain) viene compromesso.
A fine 2021, è stata scoperta una falla critica estrema (grado massimo, CVSS 10.0) in Log4j, la
minuscola libreria di logging per Java usata dal 99% dei server mondiali. Un attaccante remoto poteva
prendere il controllo totale del server inviandogli semplicemente una stringa di testo specifica. Siccome
Log4j era inclusa come dipendenza transitiva ovunque, l'attacco ha colpito
infrastrutture di Amazon, Apple, server di Minecraft, sistemi sanitari e banche centrali, dimostrando come
la compromissione di un singolo nodo quasi invisibile dell'albero open-source possa mettere in ginocchio la
rete globale.
Come ci si difende da rischi come Log4Shell? La soluzione metodologica promossa dallo standard di settore è
l'adozione dell'SBOM. Come nei prodotti alimentari, è letteralmente la "lista degli
ingredienti" del tuo software compilato. Consiste in un file o un database generato in automatico che elenca
ricorsivamente tutti i componenti di terze parti inclusi, le loro versioni esatte e le rispettive licenze
d'uso. Nel momento in cui nel mondo esplode una nuova falla "zero-day", un team di sicurezza può scansionare
in 3 secondi la propria SBOM per capire inequivocabilmente se e in quale file del proprio vasto ecosistema
risiede la libreria vulnerabile, senza dover scaricare, spacchettare o ricompilare il codice sorgente.
7. AI in DevOps
L'Intelligenza Artificiale Generativa non è più riservata solo ad assistere lo sviluppatore nell'IDE per
generare righe di codice, ma sta impattando prepotentemente tutto il ciclo di vita DevOps e IT Operations.
Con il termine TuringBots si identificano gli assistenti autonomi (o semi-autonomi) basati su LLM
che lavorano al fianco degli ingegneri dell'infrastruttura, riducendo esponenzialmente il Toil
manuale per i seguenti scopi:
- Generazione Infrastruttura As Code: Creare da zero complessi file
Dockerfile o moduli di Terraform descrivendo la topologia di rete desiderata in puro
linguaggio naturale conversazionale.
- Fix delle Pipeline CI/CD: Di fronte al fallimento di una pipeline di build causato da
centinaia di log criptici, i TuringBots diagnosticano all'istante l'errore analizzando l'output della
build, individuando quale step o dipendenza ha bloccato il rilascio, proponendo o applicando il fix per il
GitHub Actions yaml.
- Semantic Commits: Rilevare in automatico le righe di codice effettivamente variate in
uno snapshot locale (il "diff") e autogenerare istantaneamente il testo del
git commit -m
aderendo allo standard Conventional Commits aziendale.