Best practice / indicazioni per mantenere i numeri di versione dell'assembly


154

Sto cercando suggerimenti, suggerimenti e persino dettati su come gestire i tre diversi numeri di versione dell'assembly per un assembly .NET. La versione del prodotto è la più semplice, in quanto sembra essere normalmente dettata dal business. Quindi, la versione del file sembra essere per il controllo delle versioni tra le distribuzioni, in cui la versione effettiva dell'assembly viene utilizzata solo durante la spedizione.

In questo momento sto solo cercando un modo semplice per etichettare i test e le versioni di manutenzione di un assembly da cui nessuno dipende, quindi sto cercando numeri di build e revisione auto-incrementanti sulla versione del file, e per il rilascio finale, copiando l'attuale versione del file alla versione dell'assembly. Il prodotto è in uso nella produzione, ma è ancora in fase di sviluppo - sai - una di quelle piccole aziende, nessuna situazione nelle infrastrutture di controllo del cambiamento.


Risposte:


211

Il versioning è qualcosa di cui sono molto appassionato e ho trascorso molto tempo a cercare un sistema di versioning facile da usare. Da quello che hai già detto nella tua domanda è chiaro che hai capito un punto importante, i numeri di versione dell'assembly non sono sinonimi della versione del prodotto. Uno è guidato tecnicamente e l'altro è guidato dal business.

Di seguito si presuppone che si utilizzi una qualche forma di controllo del codice sorgente e un server di generazione. Per il contesto utilizziamo TeamCity e Subversion / Git. TeamCity è gratuito per un numero limitato (10) di progetti ed è un ottimo server di build ma ce ne sono altri, alcuni dei quali completamente gratuiti.

Cosa significa un numero di versione

Che cosa significhi una versione per una persona può significare qualcosa di diverso rispetto a un'altra, la struttura generale è maggiore, minore, macro, micro. Il modo in cui guardo un numero di versione è di suddividerlo in due parti. La prima metà descrive la versione principale (Maggiore) e tutti gli aggiornamenti chiave (Minore). La seconda metà indica quando è stata creata e quale era la versione del codice sorgente. I numeri di versione significano anche cose diverse a seconda del contesto, è un'API, un'app Web, ecc.

Major. Minor. Build.Revision

  • Revision Questo è il numero preso dal controllo del codice sorgente per identificare ciò che è stato effettivamente creato.
  • BuildQuesto è un numero sempre crescente che può essere utilizzato per trovare una particolare build sul server di build. È un numero importante perché il server di build potrebbe aver creato la stessa fonte due volte con un diverso set di parametri. L'uso del numero di build insieme al numero di origine consente di identificare cosa è stato creato e come.
  • MinorQuesto dovrebbe cambiare solo quando si verifica un cambiamento significativo nell'interfaccia pubblica. Ad esempio, se si tratta di un'API, il codice utente sarebbe comunque in grado di compilare? Questo numero dovrebbe essere resettato a zero quando il numero principale cambia.
  • Majorindica la versione del prodotto in cui ti trovi. Ad esempio, il maggiore di tutti gli assembly di VisualStudio 2008 è 9 e VisualStudio 2010 è 10.

L'eccezione alla regola

Ci sono sempre delle eccezioni alla regola e dovrai adattarti quando le incontri. Il mio approccio originale era basato sull'utilizzo di Subversion ma recentemente mi sono trasferito su Git. Il controllo del codice sorgente come sovversione e codice sorgente sicuro che utilizzano un repository centrale dispongono di un numero che può essere utilizzato per identificare un determinato set di fonti da un determinato momento. Questo non è il caso di un controllo del codice sorgente distribuito come Git. Poiché Git utilizza repository distribuiti che si trovano su ogni macchina di sviluppo, non esiste un numero con incremento automatico che è possibile utilizzare, esiste un hack che utilizza il numero di check-in ma è brutto. Per questo motivo ho dovuto evolvere il mio approccio.

Major. Minor. Macro.Build

Il numero di revisione è ora passato, la build è stata spostata nel punto in cui si trovava la revisione e la Macro è stata inserita. Puoi usare la macro come meglio credi, ma la maggior parte delle volte la lascio da sola. Poiché utilizziamo TeamCity, le informazioni perse dal numero di revisione possono essere trovate nella build, ciò significa che esiste un processo in due fasi, ma non abbiamo perso nulla ed è un compromesso accettabile.

Cosa impostare

La prima cosa da capire è che la versione dell'assembly, la versione del file e la versione del prodotto non devono corrispondere. Non sto proponendo di avere diversi insiemi di numeri, ma rende la vita molto più semplice quando si apportano piccole modifiche a un assembly che non influisce su alcuna interfaccia pubblica che non si è costretti a ricompilare assembly dipendenti. Il modo in cui mi occupo di questo è di impostare solo i numeri Major e Minor nella versione dell'assembly ma di impostare tutti i valori nella versione del file. Per esempio:

  • 1.2.0.0 (AssemblyVersion)
  • 1.2.3.4 (FileVersion)

Questo ti dà la possibilità di implementare hotfix che non romperanno il codice esistente perché le versioni dell'assembly non corrispondono ma ti permettono di vedere la revisione / build di un assembly guardando il suo numero di versione del file. Questo è un approccio comune e può essere visto su alcuni assembly open source quando si guardano i dettagli dell'assembly.

In qualità di responsabile del team, è necessario essere responsabili dell'incremento del numero minore ogni volta che è richiesto un cambiamento di rottura. Una soluzione per implementare una modifica richiesta a un'interfaccia ma non rompere il codice precedente è contrassegnare quella corrente come obsoleta e creare una nuova interfaccia. Significa che il codice esistente è avvisato che il metodo è obsoleto e potrebbe essere rimosso in qualsiasi momento, ma non richiede di interrompere immediatamente tutto. È quindi possibile rimuovere il metodo obsoleto quando tutto è stato migrato.

Come collegarlo insieme

Potresti fare tutto quanto sopra manualmente ma richiederebbe molto tempo, il seguente è il modo in cui automatizziamo il processo. Ogni passaggio è eseguibile.

  • Rimuovere gli attributi AssemblyVersione AssemblyFileVersionda tutti i file AssemblyInfo.cs del progetto.
  • Creare un file comune di informazioni sull'assembly (chiamarlo VersionInfo.cs) e aggiungerlo come elemento collegato a tutti i progetti.
  • Aggiungi AssemblyVersione AssemblyFileVersionattributi alla versione con valori di "0.0.0.0".
  • Creare un progetto MsBuild che crea il file della soluzione.
  • Aggiungi un'attività prima della build che aggiorna VersionInfo.cs. Esistono numerose librerie MsBuild open source che includono un'attività AssemblyInfo che può impostare il numero di versione. Basta impostarlo su un numero arbitrario e testare.
  • Aggiungi un gruppo di proprietà contenente una proprietà per ciascuno dei segmenti del numero di build. Qui è dove imposti il ​​maggiore e il minore. Il numero di build e revisione deve essere passato come argomento.

Con sovversione:

<PropertyGroup>
    <Version-Major>0</Version-Major>
    <Version-Minor>0</Version-Minor>
    <Version-Build Condition=" '$(build_number)' == '' ">0</Version-Build>
    <Version-Build Condition=" '$(build_number)' != '' ">$(build_number)</Version-Build>
    <Version-Revision Condition=" '$(revision_number)' == '' ">0</Version-Revision>
    <Version-Revision Condition=" '$(revision_number)' != '' ">$(revision_number)</Version-Revision>
</PropertyGroup>

Spero di essere stato chiaro ma c'è molto da fare. Si prega di porre domande. Userò qualsiasi feedback per mettere insieme un post sul blog più conciso.


Hai preso in considerazione l'utilizzo dei tag di versione di GitHub? Sono molto curioso di sapere come si adatterebbe al puzzle.
raRaRa,

1
@raRaRa - Questo è un post piuttosto vecchio. Mentre la maggior parte di tutto ciò è ancora lì, ci sono alcune cose che farei diversamente. Il controllo delle versioni di NuGet ha cambiato il modo in cui faccio le cose e utilizzo i tag Git per build riuscite, ma alla fine della giornata il numero di versione sull'assemblaggio dovrebbe ricollegarsi alla versione di build sul server di build e alla versione di tag nel controllo del codice sorgente.
Bronumski,

57

[AssemblyVersion] è un grosso problema in .NET. Una filosofia, incoraggiata da Microsoft, è quella di lasciarlo auto-incrementare, costringendo a ricompilare tutti i progetti che dipendono dall'assemblaggio. Funziona bene se si utilizza un server di build. Non è mai la cosa sbagliata da fare, ma attenzione alle persone che portano le spade.

L'altro, più strettamente associato al suo significato reale è che il numero è rappresentativo per il controllo delle versioni dell'interfaccia pubblica dell'assembly. In altre parole, lo cambi solo quando modifichi un'interfaccia pubblica o una classe. Poiché solo una tale modifica richiede la ricompilazione dei client dell'assembly. Questo deve essere fatto manualmente, tuttavia, il sistema di compilazione non è abbastanza intelligente da rilevare automaticamente tale modifica.

È possibile estendere ulteriormente questo approccio solo incrementando la versione quando l'assembly è stato distribuito su macchine fuori dalla propria portata. Questo è l'approccio utilizzato da Microsoft, i numeri di versione degli assiemi .NET cambiano molto raramente. Principalmente a causa del notevole dolore che provoca ai loro clienti.

Quindi ciò che predica Microsoft non è ciò che pratica. Il suo processo di compilazione e il controllo delle versioni sono tuttavia senza pari, hanno persino un ingegnere software dedicato che monitora il processo. Non ha funzionato così bene, in particolare il sovraccarico WaitHandle.WaitOne (int) ha causato un discreto dolore . Risolto in .NET 4.0 con un approccio molto diverso, ma che andava un po 'oltre l'ambito.

Dipende da te e dalla tua fiducia nel modo in cui puoi controllare il processo di compilazione e i cicli di rilascio per fare la tua scelta. Oltre a ciò, l'incremento automatico di [AssemblyFileVersion] è molto appropriato. Con tuttavia l'inconveniente che questo non è supportato.


11

È possibile utilizzare la parte Build del numero di versione per l'incremento automatico.

[assembly: AssemblyVersion("1.0.*")]

Nel tuo ambiente una versione di prova è una versione che ha una versione build! = 0. Al rilascio, incrementa la parte minore e imposti la parte build su 0, in questo modo identifichi gli assembly rilasciati.

Se installi i tuoi assiemi nel GAC, il tuo GAC viene invaso da molte versioni diverse nel tempo, quindi tienilo a mente. Ma se usi le dll solo localmente, penso che questa sia una buona pratica.


Mi piace il numero di build 0 per le versioni di rilascio.
ProfK,

1
Ovviamente questo significa che il nome sicuro dell'assembly cambierà con ogni build, che tu lo voglia o no.
Richard,

9

Aggiungendo alla risposta Bronumskis , voglio sottolineare che dopo lo standard Semantic Versioning 2.0 su semver.org ,Major.Minor.Build.Revision sarebbe illegale a causa della regola che dopo aver aumentato un numero, tutti i valori regolari a destra dovrebbero essere ripristinati a zero.

Un modo migliore di seguire lo standard sarebbe usare Major.Minor+Build.Revision. Ovviamente questo non è per l'uso inAssemblyVersionAttribute , ma è possibile utilizzare invece un attributo personalizzato o una classe statica.

Semver in TeamCity dovrebbe essere disponibile utilizzando il Power Pack Meta-runner. Per git con git-flow (specialmente nel mondo .NET), ho trovato utile GitVersion .


2
Interessante, lo controllerò. Il formato del numero di versione menzionato potrebbe essere utilizzato nell'attributo AssemblyInformationalVersion.
Bronumski,

1

Non esiste una regola rigida e veloce quando si tratta di assiemi di versioning, quindi sentiti libero di provare quale mai funzionerebbe per te, ma ti suggerirei di utilizzare l'approccio in 4 parti in quanto avrai la flessibilità in caso desideri apportare alcune modifiche nel futuro.

... per esempio: 1.0.0. *

Riservato: aggiunge ulteriore flessibilità, in caso si desideri apportare modifiche in futuro. Ma come impostazione predefinita, tenerlo come 0.

Inoltre, considera di firmare l'assembly con una chiave avanzata. Ciò risolverà il problema del conflitto di assembly nel caso in cui abbiate più versioni di assembly registrate nel GAC. Collegamento MSDN

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.