Come il mio team rilascia le librerie

Il team con cui lavoro in Google gestisce oltre 300 repository, in tutto
7 lingue, sviluppate all'aperto su GitHub. Rilasciamo nuove versioni della libreria ai gestori di pacchetti, come Maven, npm e PyPi, centinaia di volte al mese:

Il rilascio di una libreria non è semplicemente una questione di pubblicazione del codice in un gestore di pacchetti. La maggior parte delle nostre librerie utilizza SemVer per il controllo delle versioni. SemVer formalizza il concetto che il MAJOR , MINOR e PATCH nelle versioni ([MAJOR].[MINOR].[PATCH] ) dovrebbe essere utilizzato per comunicare le modifiche di natura al tuo utente:

— semver.org.

È importante incrementare il MAJOR corretto , MINOR o PATCH , quando si rilascia una nuova versione della libreria. Tuttavia, un numero di versione da solo non fornisce informazioni sufficienti durante l'aggiornamento. Un registro delle modifiche (un record leggibile dall'uomo delle modifiche al software, solitamente archiviato in ./CHANGELOG.md ) è importante perché comunica all'utente:

  • Quali nuove funzionalità possono aspettarsi.
  • Quali bug abbiamo corretto che potrebbero averli interessati.
  • A quali modifiche sostanziali dovrebbero prestare attenzione durante l'aggiornamento.

— keepachangelog.com.

Gli umani non sono bravi in ​​questo

La scelta manuale di un nuovo numero di versione durante il rilascio è soggetta a errori. Saprai che il tuo collega ha introdotto una piccola modifica sostanziale due giorni prima?

La scrittura manuale delle note di rilascio richiede tempo. Mi sono ritrovato a spendere 20 minuti per ogni versione (per chi fa matematica, questo avrebbe significato che avremmo trascorso 130 ore a scrivere note sulla versione a maggio ). È anche soggetto a errori... abbiamo richiamato l'attenzione sulle funzionalità appropriate, abbiamo documentato tutte le modifiche sostanziali?

Obiettivi in ​​competizione

Ci siamo trovati con due obiettivi potenzialmente in competizione:

  • Ci tenevamo molto a seguire SemVer e a fornire un log delle modifiche fruibile e leggibile dall'uomo.
  • Se non avessimo automatizzato il nostro processo di rilascio, scopriremmo rapidamente che ci stava impiegando il 100% del nostro tempo.

Il resto di questo post introduce una convenzione che abbiamo adottato e uno strumento che abbiamo scritto (e open source 🎉 ), per conciliare l'obiettivo di creare rilasci significativi e automatizzati.

Adozione delle convenzioni di commit

I messaggi di commit forniscono un contesto importante sia per gli altri collaboratori che per gli utenti della tua libreria. Ci credo, ma quando guardo indietro a vari progetti, i commit sono un po' un miscuglio:

Quale aggiornamento è stato apportato al changelog? perché ero una persona terribile? cosa risolve il numero 148?

Ci deve essere un modo migliore!

Convenzioni dei messaggi di commit di AngularJS Git

Nel 2011 Igor Minar e Vojta Jína, mentre lavoravano al progetto Angular, hanno avuto la brillante idea di introdurre una convenzione leggera in aggiunta ai messaggi di commit. Il loro documento di progettazione originale descrive i seguenti obiettivi:

  • Consenti la generazione di CHANGELOG.md con uno script.
  • Consenti di ignorare i commit non importanti, quando usi git bisect.
  • Fornisci informazioni migliori durante la navigazione nella cronologia.

Proseguono proponendo il formato:

<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
  • digitare :rappresenta il tipo di modifica avvenuta, esempi validi sono ci: , feat: , fix: , perf: , build: .
  • ambito :è facoltativo e rappresenta la parte del sistema che è cambiata, esempi di ambiti supportati includono localize , http , router , forms .
  • oggetto :è una descrizione della modifica.
  • corpo :è una descrizione in forma più lunga della modifica. Può anche includere il token BREAKING CHANGE , per indicare una modifica dell'API di interruzione.

Un messaggio di commit finisce per assomigliare a questo:

fix(http): addressed bug with http module

There was a bug with the http module, it has now been addressed.

Queste linee guida per il commit angolare hanno ispirato i commit convenzionali, che è la convenzione di commit adottata dal mio team.

Impegni convenzionali

La specifica dei commit convenzionali propone un superset delle linee guida di Angular:

  • Il type può essere tutto ciò che piace a un collaboratore, ma feat: e fix: hanno significato semantico:fix: corregge un bug nella tua base di codice, feat: indica che è stata aggiunta una nuova funzionalità.
  • Allo stesso modo, non ci sono restrizioni sul scope .
  • Conventional Commits introduce il ! scorciatoia, per indicare modifiche sostanziali.
refactor(http)!: removed deprecated method start()

Gli obiettivi della specifica degli impegni convenzionali erano:

  • Evidenzia che queste convenzioni di commit, sperimentate da Angular, erano ampiamente applicabili (non devono essere usate solo da gente di JavaScript ).
  • Estrarre le regole in modo che siano applicabili a progetti arbitrari (sottolineando quanto sia facile adottarle ).
  • Fornire una specifica formale per la quale gli autori di strumenti potrebbero creare parser.

Conventional Commits mi è sembrata la scelta perfetta per il mio obiettivo di convincere le persone di 6 team linguistici ad adottare una convenzione:Ho apprezzato le regole leggermente ridotte.

Automatizzare il processo di rilascio

Una volta che i repository hanno iniziato ad adottare i commit convenzionali, siamo stati in grado di iniziare ad automatizzare parti del nostro processo di rilascio che erano state manuali, ad esempio, generando un CHANGELOG.md, scegliendo la versione successiva della libreria, pubblicando in un registro dei pacchetti.

Il processo è stato graduale. Invece di costringere i team a utilizzare le convenzioni di commit, ho pensato che sarebbe stato meglio dimostrare il loro valore. Abbiamo iniziato automatizzando il nostro processo di rilascio di JavaScript. Come speravo, le altre squadre si sono affrettate a seguirlo poiché hanno visto che il tempo stava risparmiando. Ora, un anno dopo, supportiamo JavaScript, Python, Java, Ruby, PHP, Terraform e stiamo iniziando a lavorare su Go.

Parallelamente all'adozione delle convenzioni, abbiamo sviluppato uno strumento chiamato release-please. Abbiamo reso il rilascio-per favore estensibile, in modo che ogni team linguistico sia in grado di personalizzare il proprio processo di rilascio:

  • Alcuni team volevano segnalare diversi tipi di modifiche nel proprio CHANGELOG.md.
  • Alcuni team utilizzano repository mono, mentre altri team hanno un repository per libreria.
  • Alcuni team rilasciano il pre-1.x.x versioni delle loro librerie mentre erano in versione beta.

Presentazione del rilascio, per favore

release-please è lo strumento nato dall'automazione del processo di rilascio da parte del mio team per 6 lingue.

Lo fa analizzando la cronologia di git, cercando messaggi di commit convenzionale e creando PR di rilascio.

Cosa sono le PR di rilascio? I nostri processi di rilascio esistenti non sono stati associati bene al rilascio continuo delle modifiche quando arrivano a un ramo:

  • A volte ci sarà una data di rilascio prestabilita per una funzionalità della libreria, anche se è pronta per essere utilizzata su GitHub.
  • Cerchiamo di eseguire il bumping delle versioni principali di rado, quindi a volte aspetteremo l'arrivo di alcune modifiche sostanziali prima di promuovere una versione.
  • A volte (raramente ) ci sarà una certa quantità di QA manuale prima di promuovere una pubblicazione in libreria.

release-please crea automaticamente le PR di rilascio. Rappresentano l'insieme delle modifiche che sarebbero presenti se dovessi rilasciare la libreria:

Se una versione PR viene unita, release-please creerà una versione della tua libreria, corrispondente alla descrizione nella versione PR.

Conclusione

Pur abbracciando le differenze nei flussi di lavoro di rilascio tra le comunità linguistiche, abbiamo avuto un'ottima esperienza nell'adozione di convenzioni e strumenti di commit coerenti in tutto il nostro team.

Lo abbiamo fatto senza sacrificare un CHANGELOG.md utilizzabile e aderendo con successo a SemVer.

L'implementazione di questo processo è stata un'esperienza fantastica e spero che altri team siano ispirati dal nostro successo.

Collegamenti

  • Documento di progettazione originale di Angular Commit Convention:scritto nel 2011.
  • conventionalcommits.org:una specifica di commit, ispirata a quella di Angular.
  • release-please:lo strumento release-please.
  • release-please-action:esegui release please come azione GitHub.
  • rilascio semantico:automatizza i rilasci, in base alle convenzioni angolari, quando le modifiche vengono inviate a un ramo.