Informazioni sulla gestione dei rami

Completato

Quando si compilano i modelli Bicep e si lavora all'interno di un repository Git, tutte le modifiche apportate dal team vengono infine unite nel ramo principale del repository. È importante proteggere il ramo principale in modo da non distribuire modifiche indesiderate nell'ambiente di produzione. Al contempo, è anche desiderabile che i colleghi siano in grado di lavorare in modo flessibile, collaborare con il team e sperimentare facilmente nuove idee.

In questa unità si apprenderanno informazioni sulle strategie di creazione di rami e su come proteggere il ramo principale e come configurare un processo di revisione per i rami.

Perché è importante proteggere il ramo principale?

Il ramo principale è l'origine di riferimento per ciò che viene distribuito negli ambienti di Azure. Per molte soluzioni sono disponibili più ambienti, ad esempio sviluppo, controllo di qualità (QA) e produzione. In altri scenari, potrebbe essere disponibile soltanto un ambiente di produzione. Indipendentemente dal numero di ambienti usati, il ramo principale è quello a cui contribuiscono i membri del team. Le loro modifiche convergono nel ramo principale.

Un processo tipico potrebbe essere simile al seguente:

  1. Un membro del team clona il repository condiviso.
  2. Apporta delle modifiche locali a un ramo, nella propria copia locale del repository.
  3. Al termine dell'operazione, queste modifiche vengono unite nel ramo principale del repository locale.
  4. Esegue il push di queste modifiche nel ramo principale del repository remoto.
  5. In alcuni scenari, l'esecuzione del push nel repository remoto attiva una pipeline automatizzata per verificare, testare e implementare il codice. Informazioni aggiuntive sulle pipeline sono disponibili in altri moduli di Microsoft Learn.

Nella seguente figura viene illustrato questo processo:

Diagramma che mostra il processo per apportare modifiche locali, eseguire il push delle modifiche nel ramo principale remoto e attivare una pipeline.

Supponiamo che le modifiche apportate da un membro del team introducano un bug subdolo. Al termine dell'esecuzione del processo, il bug si trova nel ramo principale del progetto e viene distribuito in ambiente di produzione. È possibile che il bug venga individuato soltanto in seguito alla ricezione di un messaggio di errore, nel momento in cui si prova a distribuirlo. In alternativa, per altri tipi di bug, la distribuzione potrebbe avere esito positivo ma causare problemi in un secondo momento.

Per un altro scenario, supponiamo che un membro del team stia lavorando a una funzionalità ed esegua il push di una parte del lavoro concluso nel ramo principale del repository condiviso. A questo punto nel ramo principale sono presenti modifiche non concluse o testate, che non devono essere distribuite nell'ambiente di produzione. Potrebbe essere necessario bloccare le distribuzioni in produzione fino a quando la funzionalità non sarà completata. Se le funzionalità appena completate si trovano nel ramo principale, potrebbe non essere possibile distribuirle ai clienti.

Suggerimento

Questi problemi sono particolarmente difficili per i team di grandi dimensioni, in cui più persone contribuiscono allo stesso codice, ma le indicazioni contenute in questo modulo sono utili non appena si collabora con più persone. sia quando si lavora autonomamente su un progetto con più funzionalità.

Un modo più efficace di procedere consiste nel mantenere le modifiche in un luogo separato mentre si lavora su di esse, quindi fare in modo che un altro membro del team riveda le modifiche prima di unirle nel ramo principale del repository condiviso. Grazie a questo processo, il team può prendere una decisione consapevole prima di approvare l'unione di una modifica.

Rami di funzionalità

Un ramo di funzionalità indica un nuovo lavoro che si sta iniziando. Questo lavoro potrebbe essere una modifica alla configurazione di una risorsa definita nel file Bicep o un nuovo set di risorse da distribuire. Ogni volta che si inizia una nuova attività, si crea un nuovo ramo di funzionalità.

Il ramo di funzionalità viene creato a partire dal ramo principale, in modo da essere sicuri, quando si crea un ramo, di iniziare dallo stato attuale dell'ambiente di Azure. In seguito, si apportano tutte le modifiche necessarie.

Poiché viene eseguito il commit di tutte le modifiche al codice nel ramo di funzionalità, queste non interferiscono con il ramo principale del repository. Se un altro membro del team deve apportare una modifica urgente al ramo principale, può farlo in un altro ramo di funzionalità indipendentemente da quello dell'utente.

È anche possibile collaborare nei rami di funzionalità. Pubblicando ed eseguendo il push del ramo di funzionalità nel repository condiviso, l'utente e i membri del team possono collaborare a una modifica. Si può anche decidere di passare una funzionalità a un altro utente per completare il lavoro quando si va in vacanza.

Aggiornare i rami di funzionalità

Quando il ramo di funzionalità è in funzione, è possibile unire altre funzionalità nel ramo principale del repository. Il risultato è che il ramo di funzionalità e il ramo principale del progetto si separeranno. Più si separano, più diventa difficile unire nuovamente i due rami in un secondo momento e più alta è la probabilità di riscontrare conflitti di unione.

È consigliabile aggiornare regolarmente il ramo di funzionalità in modo da incorporare tutte le modifiche apportate al ramo principale del repository. È inoltre consigliabile aggiornare il ramo di funzionalità prima di iniziare a unirlo di nuovo nel ramo principale. In questo modo, è possibile assicurarsi che le nuove modifiche possano essere facilmente unite nel ramo principale.

Suggerimento

Unire regolarmente il ramo principale con il ramo di funzionalità.

Usare rami piccoli e di breve durata

Avere come obiettivo rami di funzionalità di breve durata. Questo approccio consente di evitare conflitti di merge riducendo la quantità di tempo che i rami potrebbero non essere sincronizzati. Questo approccio semplifica inoltre la comprensione delle modifiche apportate dai colleghi, che è utile quando è necessario esaminare le modifiche.

Suddividere i lavori di grandi dimensioni in elementi più piccoli e creare un ramo di funzionalità per ognuno di essi. Più grande è la funzionalità, più a lungo sarà necessario lavorare su di essa, con conseguente allungamento della durata del relativo ramo. È possibile distribuire le modifiche più piccole nell'ambiente di produzione man mano che si unisce ogni ramo di funzionalità, creando gradualmente un lavoro più grande.

Si supponga di dover apportare alcune modifiche a un set di codice Bicep. Si stanno spostando alcune definizioni di risorse in moduli. È anche necessario aggiungere nuove risorse ai file Bicep. Potrebbe essere consigliabile effettuare prima il refactoring di tutti i moduli nel proprio ramo. Al termine dell'unione dei moduli, è possibile iniziare a lavorare sulle aggiunte ai file Bicep. La separazione delle modifiche consentire di mantenere ognuna di esse, e il relativo ramo, di piccole dimensioni e di facile comprensione.

In questo modo, è possibile usare la parola chiave if per disabilitare la distribuzione delle risorse finché non sono pronte. Il codice di esempio seguente illustra come usare la parola chiave if per creare un file Bicep che definisce un account di archiviazione ma disabilita la distribuzione dell'account di archiviazione fino a quando non vengono completate tutte le modifiche.

@description('Specifies whether the storage account is ready to be deployed.')
param storageAccountReady bool = false

resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = if (storageAccountReady) {
  name: storageAccountName
  location: location
  kind: 'StorageV2'
  sku: {
    name: 'Premium_LRS'
  }
}

È possibile usare i parametri per specificare valori diversi per la variabile storageAccountReady in ambienti diversi. Ad esempio, è possibile impostare il valore del parametro su true per l'ambiente di test e su false per l'ambiente di produzione. In questo modo, è possibile provare il nuovo account di archiviazione nell'ambiente di test.

Nota

Quando è il momento di abilitare la funzionalità in produzione, è necessario eseguire i passaggi seguenti per rendere effettiva la modifica:

  1. Modificare il valore del parametro.
  2. Ridistribuire il file Bicep.

Unione dei rami di funzionalità

Dopo aver completato il lavoro su un ramo di funzionalità, è necessario unirlo al ramo principale del repository. È consigliabile esaminare le modifiche apportate nel ramo di funzionalità prima di procedere all'unione. È possibile esaminare il codice tramite le richieste pull, che verranno trattate in seguito all'interno di questo modulo.

Protezioni dei rami

In GitHub è possibile configurare le protezioni dei rami per il ramo principale del repository condiviso. Le protezioni dei rami applicano alcune regole, come le seguenti:

  • Non è possibile unire alcuna modifica al ramo principale, se non attraverso una richiesta pull.
  • Le modifiche devono essere esaminate almeno da altri due utenti.

Se un utente tenta di eseguire il push di un commit direttamente in un ramo protetto, l'operazione non riesce. Nell'unità successiva si apprenderà come applicare le protezioni dei rami.

Criteri ramo

In Azure DevOps è possibile configurare i criteri del ramo per il ramo principale del repository condiviso. I criteri del ramo applicano alcune regole, come le seguenti:

  • Non è possibile unire alcuna modifica al ramo principale, se non attraverso una richiesta pull.
  • Le modifiche devono essere esaminate almeno da altri due utenti.

Se un utente tenta di eseguire il push di un commit direttamente in un ramo protetto, l'operazione non riesce. Nell'unità successiva si apprenderà come applicare i criteri dei rami.

Altre strategie di creazione di rami

Quando si collabora al codice Bicep, è possibile usare varie strategie di creazione di rami. Ogni strategia presenta vantaggi e svantaggi.

Il processo appreso finora è una versione della strategia di sviluppo basato su trunk. Secondo questa strategia di gestione dei rami, il lavoro viene eseguito su rami di funzionalità di breve durata e quindi viene unito in un unico ramo principale. È possibile distribuire automaticamente il contenuto del ramo principale del repository condiviso nell'ambiente di produzione ogni volta che si unisce una modifica, oppure è possibile eseguirne il batch e rilasciarli in base a una pianificazione, ad esempio ogni settimana. Lo sviluppo basato su trunk è facile da comprendere e consente di collaborare in modo abbastanza semplice.

Alcuni team separano il lavoro completato dal lavoro distribuito nell'ambiente di produzione. Usano un ramo di sviluppo di lunga durata come destinazione per l'unione dei rami di funzionalità. Uniscono il ramo di sviluppo nel ramo principale quando rilasciano le modifiche all'ambiente di produzione.

Altre strategie di creazione di rami richiedono la creazione di rami di versione. Quando si dispone di un set di modifiche pronte per la distribuzione in produzione, si crea un ramo di versione con le modifiche da distribuire. Queste strategie possono essere utili quando si distribuisce l'infrastruttura di Azure con una cadenza regolare o quando si integrano le modifiche con molti altri team.

Altre strategie di creazione di rami includono Gitflow, GitHub Flow e GitLab Flow. Alcuni team usano GitHub Flow o GitLab Flow perché consente di separare il lavoro di team diversi, oltre a separare le correzioni di bug urgenti da altre modifiche. Questi processi consentono inoltre di separare i commit in versioni diverse della soluzione. Questa operazione è denominata cherry picking. Per garantire che le modifiche siano compatibili tra loro è tuttavia necessaria una maggiore gestione. Nel riepilogo di questo modulo sono disponibili collegamenti ad altre informazioni relative alle strategie di creazione di rami.

La strategia di creazione di rami appropriata per ogni team dipende dal modo in cui la squadra lavora, collabora e rilascia le modifiche. È consigliabile iniziare da un processo semplice, ad esempio lo sviluppo basato su trunk. Se si ritiene che il team non possa lavorare in modo efficace usando questo processo, introdurre gradualmente altri livelli di creazione di rami o adottare una strategia di gestione dei rami, ma tenere presente che quando si aggiungono altri rami, la gestione del repository diventa più complessa.

Suggerimento

Indipendentemente dalla strategia di creazione di rami usata, è consigliabile proteggere il ramo principale tramite i criteri e usare le richieste pull per esaminare le modifiche. Anche altre strategie di creazione di rami introducono rami importanti da proteggere.

Questo modulo usa lo sviluppo basato su trunk con rami di funzionalità, data la sua facilità di utilizzo.