Go Modules è il meccanismo standard di gestione delle dipendenze introdotto in Go 1.11+. I file principali sono go.mod (definisce le dipendenze minime e le loro versioni) e go.sum (garantisce l'integrità attraverso gli hash).
Per aggiungere una dipendenza si utilizza:
go get github.com/pkg/errors@v0.9.1
Per aggiornare le dipendenze —
go get -u ./... go mod tidy # rimuovere non utilizzato
Go supporta la versioning semantico (semver) e le dipendenze sono fissate in modo rigido: il progetto è ripetibile, la build è deterministica. Ma è importante considerare:
Cosa succede se si elimina il file go.sum e si esegue il comando go build, e perché è pericoloso?
Molti pensano che Go ricostruirà semplicemente le dipendenze da zero. Ma il file go.sum contiene gli hash di tutti i moduli utilizzati e protegge dalle sostituzioni (supply-chain attack). Se viene rimosso,
alla successiva build Go scaricherà nuovamente le dipendenze, ricreerà il file, ma se il repository della dipendenza è stato modifica da un malintenzionato — la protezione è rotta! È possibile una sostituzione del codice in produzione.
Storia
In un grande progetto, il repository è passato da vendoring a go modules, sono stati dimenticati di fissare le versioni. Dopo un mese gli aggiornamenti dei pacchetti di terze parti hanno rotto la compatibilità, è diventato impossibile compilare il vecchio ramo — il codice ha perso ripetibilità.
Storia
In un altro progetto, uno sviluppatore ha accidentalmente eliminato go.sum. Dopo un nuovo tentativo, il team ha notato che alcune dipendenze erano cambiate, sono emersi bug legati all'incompatibilità delle versioni minor — per questo c'è stato un rollback di diversi giorni fa.
Storia
L'uso di percorsi replace su directory locali (replace ... = ../some/library) non è stato rimosso prima del deployment — nel pipeline CI/CD la build è fallita, poiché il sistema esterno non aveva accesso ai file locali, e la produzione è stata "pinnata" a una versione errata.