Build Pipeline (pipeline di compilazione) è una sequenza di fasi automatizzate che il codice attraversa dal momento del commit fino a un artefatto pronto per il deployment. La pipeline include compilazione, esecuzione dei test, analisi statica e preparazione del pacchetto di rilascio. Secondo Google Cloud DORA, 2025, i team con una pipeline ben configurata raggiungono una consegna delle modifiche 440 volte più veloce rispetto ai team senza automazione.
Punti chiave
Build Pipeline è una sequenza formalizzata di passi che vengono eseguiti automaticamente ad ogni modifica del codice. Ogni passo verifica un determinato aspetto di qualità: compilabilità, correttezza dei test, assenza di vulnerabilità, conformità allo stile del codice. Se un passo fallisce, la pipeline si ferma.
Il concetto di pipeline deriva dalla linea di produzione — come in una fabbrica dove ogni stazione aggiunge valore al prodotto. Nello sviluppo, ogni fase aggiunge fiducia che il codice sia pronto per il rilascio. Le pipeline moderne sono definite come codice (Pipeline as Code) e memorizzate nel repository Git insieme al progetto.
Secondo la Continuous Delivery Foundation, 2025, una build pipeline matura riduce il tempo dal commit al rilascio da settimane a minuti. Ciò è ottenuto attraverso l'automazione completa e l'esecuzione parallela di fasi indipendenti.
Invece di configurare attraverso un'interfaccia web, una pipeline moderna viene descritta in file YAML o Groovy. Jenkinsfile, `.gitlab-ci.yml`, `.github/workflows/build.yml` sono esempi di Pipeline as Code. Vantaggi: versionamento, code review, riproducibilità.
Jenkins ha due sintassi. Dichiarativo — più semplice, con una struttura chiara di stages/steps. Scriptato — più flessibile, basato su Groovy. Per la maggior parte dei progetti, l'approccio dichiarativo è raccomandato in quanto più leggibile e prevedibile.
Una build pipeline tipica per un'applicazione mobile include diverse fasi chiave. Ogni fase svolge la sua funzione e filtra i problemi potenziali in una fase precoce.
La pipeline inizia con la clonazione del repository. Poi vengono installate le dipendenze: pacchetti Gradle/Maven, CocoaPods, SPM (Swift Package Manager), pacchetti npm. L'uso della cache in questa fase accelera le build successive del 50-70%.
Prima della compilazione, vengono avviati strumenti di qualità del codice: Detekt o ktlint per Kotlin, SwiftLint per Swift, ESLint per JavaScript. Verificano la conformità allo stile del codice e trovano potenziali bug a livello di analisi del codice.
Il codice viene compilato in forma binaria, i test unitari vengono eseguiti in parallelo. Per Android è `./gradlew testDebugUnitTest`, per iOS — `xcodebuild test -scheme App -destination 'platform=iOS Simulator'`. Il fallimento dei test ferma immediatamente la pipeline.
name: Mobile Build Pipeline
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./gradlew detekt
unit-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./gradlew testDebugUnitTest
- run: ./gradlew jacocoTestReport
build-release:
needs: [lint, unit-tests]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./gradlew assembleRelease
- uses: actions/upload-artifact@v4
with:
name: release-apk
path: app/build/outputs/apk/release/app-release.apk
Dopo una compilazione riuscita, vengono eseguiti i test che richiedono l'esecuzione dell'applicazione: Espresso per Android, XCTest/XCUITest per iOS, Detox per React Native. In questa fase, l'artefatto viene distribuito su un simulatore o dispositivo reale attraverso servizi farm (Firebase Test Lab, BrowserStack, Sauce Labs).
La corretta configurazione della pipeline determina l'efficienza dell'intero processo CI/CD. La configurazione include la scelta dei trigger, la definizione di fasi parallele e sequenziali, la parametrizzazione e l'integrazione con servizi esterni.
Trigger principali: push nel repository, pull request (specialmente per code review con controlli automatizzati), creazione di tag Git (per build di rilascio), pianificazione (nightly build). Il trigger pull request è il più pratico per il lavoro di squadra poiché identifica i problemi prima dell'unione del codice.
Le fasi indipendenti (linting, test su diverse versioni del sistema operativo) dovrebbero essere eseguite in parallelo per accelerare. Quelle dipendenti — sequenzialmente. I sistemi CI moderni gestiscono automaticamente i compiti paralleli, distribuendoli tra gli agenti disponibili.
Una pipeline lunga rallenta il ciclo di sviluppo e riduce la motivazione del team. L'ottimizzazione del tempo di compilazione è uno dei compiti principali di un ingegnere DevOps quando lavora con le build pipeline.
Gradle Build Cache salva i risultati delle compilazioni precedenti. Se il codice sorgente di un modulo non è cambiato, non viene ricompilato. La compilazione incrementale in Swift e Kotlin funziona in modo simile. La dimensione della cache può raggiungere gigabyte, ma il risparmio di tempo varia dal 30% al 70%.
I test unitari possono essere eseguiti su più agenti contemporaneamente, distribuendo le classi di test. Lo sharding è una tecnica di divisione dei test in gruppi (shard). GitHub Actions supporta `strategy.matrix`, Jenkins — Parallel Test Executor, Gradle — `--parallel --max-workers`.
Ogni fase extra aggiunge tempo. Analizzate regolarmente la pipeline: quali fasi possono essere combinate? Ad esempio, il linting può essere eseguito in parallelo con la compilazione invece che prima. I test di integrazione — solo per le pull request, non per ogni commit.
pipeline {
agent any
options {
timestamps()
timeout(time: 30, unit: 'MINUTES')
}
stages {
stage('Parallel Checks') {
parallel {
stage('Lint') {
steps { sh './gradlew detekt' }
}
stage('Unit Tests') {
steps { sh './gradlew test' }
}
}
}
stage('Build') {
steps { sh './gradlew assembleRelease' }
}
}
}
La build pipeline è un elemento critico della catena di fornitura del software e la sua sicurezza non può essere ignorata. Il compromesso della pipeline può portare all'inserimento di codice dannoso nell'artefatto di rilascio, colpendo tutti gli utenti dell'applicazione.
Attacchi noti: SolarWinds (2020), Codecov (2021), 3CX (2023) — tutti hanno sfruttato vulnerabilità nelle pipeline CI/CD. Vettore comune — un attaccante ottiene l'accesso alle credenziali del server di build e modifica il codice nella fase di compilazione. Risultato — un rilascio malevolo firmato con un certificato legittimo.
Non memorizzate mai chiavi di firma, token API e password nel repository o nelle variabili d'ambiente del sistema CI in chiaro. Utilizzate i segreti del sistema CI (GitHub Secrets, GitLab CI Variables), HashiCorp Vault, AWS Secrets Manager. Minimizzate l'accesso ai segreti — ogni pipeline dovrebbe ricevere solo le chiavi necessarie per i suoi passi specifici.
Ogni artefatto che esce dalla pipeline deve essere firmato crittograficamente e contenere un'attestazione — prova di origine (provenance). Strumenti: framework SLSA, attestazione in-toto, cosign per la firma dei container. La verifica della firma deve essere eseguita prima del deployment in qualsiasi ambiente.
name: Secure Build Pipeline
on: [push]
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Scan dependencies
run: ./gradlew dependencyCheckAnalyze
- name: SAST scan
run: ./gradlew detekt
sign-attest:
needs: security-scan
runs-on: ubuntu-latest
steps:
- run: ./gradlew assembleRelease
- name: Sign APK
run: jarsigner -keystore ${{ secrets.KEYSTORE }} \
app-release.apk ${{ secrets.KEY_ALIAS }}
- name: Generate provenance
uses: actions/attest-build-provenance@v1
La build pipeline è un sistema complesso che richiede monitoraggio costante. Senza metriche, è impossibile determinare se la pipeline è rallentata e quale fase è diventata un collo di bottiglia.
Monitorate: durata totale della pipeline, tempo di ogni fase, tasso di fallimento delle build, tempo di attesa in coda. Per un team grande (>20 sviluppatori), si consiglia di configurare una dashboard in Grafana o Datadog con statistiche aggregate per settimana/mese.
Ogni fallimento della pipeline richiede una risposta. Configurate notifiche nei messaggeri (Slack, Telegram, Discord) con un link al log dell'errore e il nome dell'autore del commit. Per fallimenti critici — PagerDuty o Opsgenie con escalation.
Strumenti come Act (per GitHub Actions) o Jenkins Pipeline Unit Test permettono di eseguire la pipeline localmente senza fare commit. Questo accelera lo sviluppo e il debug delle pipeline, specialmente quando si aggiungono nuove fasi o si modifica la configurazione.
Domande frequenti
Build pipeline è una parte della CI/CD pipeline responsabile della compilazione e della preparazione dell'artefatto. La CI/CD pipeline è più ampia: include il deployment, il monitoraggio post-rilascio e i controlli dell'infrastruttura.
Ad ogni push nel repository. Per le pull request — obbligatorio prima dell'unione. Nightly build — per test lunghi (e2e, performance) che non sono necessari per ogni commit.
Per i nuovi progetti — YAML (GitHub Actions, GitLab CI, Bitrise). È leggibile e semplice. Groovy (Jenkins) è più potente ma più difficile da mantenere. La scelta dipende dal sistema CI utilizzato.
Metodi principali: cache delle dipendenze, esecuzione parallela di fasi indipendenti, sharding dei test, esclusione dei test lunghi dalla pipeline per ogni commit, uso di agenti di build potenti.
Analizzate i log: quale test specifico è fallito e perché. Se il test è instabile (flaky) — aggiungete un meccanismo di riprova. Se è un vero bug — correggete il codice, non disabilitate il test. Disabilitare i test è l'ultima risorsa.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche