it-swarm.com.de

Bewährte Methoden / Anleitungen zum Verwalten von Assembly-Versionsnummern

Ich suche nach Hinweisen, Vorschlägen und sogar Diktaten zum Verwalten der drei verschiedenen Assembly-Versionsnummern für eine .NET-Assembly. Die Produktversion ist die einfachste, da dies normalerweise vom Unternehmen vorgegeben wird. Dann scheint die Dateiversion für die Versionsverwaltung zwischen Bereitstellungen gedacht zu sein, wobei die tatsächliche Assemblyversion nur beim Versand verwendet wird.

Im Moment bin ich nur auf der Suche nach einer einfachen Möglichkeit, Test- und Wartungsversionen einer Assembly zu kennzeichnen, von denen keine abhängt. Daher suche ich nach automatisch inkrementierenden Build- und Revisionsnummern für die Dateiversion und für die endgültige Version, wobei die aktuelle Version kopiert wird Dateiversion auf die Assembly-Version. Das Produkt ist in der Produktion im Einsatz, befindet sich aber noch in der Entwicklung - Sie wissen schon - eines dieser kleinen Unternehmen, die keine Änderungskontrollinfrastrukturen einsetzen.

151
ProfK

Die Versionierung ist etwas, das mir sehr am Herzen liegt, und ich habe lange versucht, ein benutzerfreundliches Versionierungssystem zu entwickeln. Aus dem, was Sie bereits in Ihrer Frage gesagt haben, geht hervor, dass Sie einen wichtigen Punkt verstanden haben: Die Versionsnummern der Baugruppe sind nicht gleichbedeutend mit der Produktversion. Einer ist technisch motiviert und der andere ist geschäftlich motiviert.

Im Folgenden wird davon ausgegangen, dass Sie eine Form der Quellcodeverwaltung und einen Buildserver verwenden. Für den Kontext verwenden wir TeamCity und Subversion/Git. TeamCity ist kostenlos für eine kleine Anzahl von Projekten und ein sehr guter Build-Server. Es gibt jedoch auch andere, von denen einige völlig kostenlos sind.

Was bedeutet eine Versionsnummer?

Was eine Version für eine Person bedeutet, kann etwas anderes bedeuten, die allgemeine Struktur ist Dur, Moll, Makro, Mikro. Die Art und Weise, wie ich eine Versionsnummer betrachte, besteht darin, sie in zwei Teile zu zerlegen. Die erste Hälfte beschreibt die Hauptversion (Major) und alle wichtigen Updates (Minor). Die zweite Hälfte gibt an, wann es erstellt wurde und wie die Quellcode-Version lautete. Versionsnummern haben je nach Kontext auch unterschiedliche Bedeutungen. Handelt es sich um eine API, eine Web-App usw.

Major.Minor.Build.Revision

  • Revision Dies ist die Nummer, die der Quellcodeverwaltung entnommen wurde, um zu identifizieren, was tatsächlich erstellt wurde.
  • Build Dies ist eine immer größere Zahl, mit der ein bestimmter Build auf dem Build-Server gefunden werden kann. Dies ist eine wichtige Zahl, da der Build-Server möglicherweise zweimal dieselbe Quelle mit einem anderen Parametersatz erstellt hat. Durch die Verwendung der Build-Nummer in Verbindung mit der Quellennummer können Sie identifizieren, was und wie gebaut wurde.
  • Minor Dies sollte sich nur ändern, wenn die öffentliche Schnittstelle erheblich geändert wurde. Wenn es sich beispielsweise um eine API handelt, kann der verbrauchende Code dann immer noch kompiliert werden? Diese Nummer sollte auf Null zurückgesetzt werden, wenn sich die Major-Nummer ändert.
  • Major gibt an, auf welcher Version des Produkts Sie sich befinden. Beispielsweise ist der Major aller VisualStudio 2008-Assemblys 9 und VisualStudio 2010 10.

Die Ausnahme von der Regel

Es gibt immer Ausnahmen von der Regel und Sie müssen sich anpassen, wenn Sie auf sie stoßen. Mein ursprünglicher Ansatz basierte auf der Verwendung von Subversion, aber ich bin kürzlich zu Git gewechselt. Quellcodeverwaltung wie Subversion und Source Safe, die ein zentrales Repository verwenden, verfügen über eine Nummer, mit der bestimmte Quellcodeverwaltungen zu einem bestimmten Zeitpunkt identifiziert werden können. Dies ist bei einer verteilten Quellcodeverwaltung wie Git nicht der Fall. Da Git verteilte Repositorys verwendet, die sich auf jedem Entwicklungscomputer befinden, können Sie keine automatisch inkrementierende Nummer verwenden. Es gibt einen Hack, der die Anzahl der Eincheckvorgänge verwendet, aber hässlich ist. Aus diesem Grund musste ich meinen Ansatz weiterentwickeln.

Major.Minor.Macro.Build

Die Versionsnummer ist jetzt weg, der Build wurde an die Stelle verschoben, an der sich die Version befand, und das Makro wurde eingefügt. Sie können das Makro verwenden, wie Sie es für richtig halten, aber die meiste Zeit lasse ich es in Ruhe. Da wir TeamCity verwenden, befinden sich die Informationen aus der Versionsnummer im Build. Dies bedeutet, dass es einen zweistufigen Prozess gibt, wir jedoch nichts verloren haben und dass dies ein akzeptabler Kompromiss ist.

Was ist einzustellen?

Das Erste, was Sie verstehen müssen, ist, dass Assembly-Version, Dateiversion und Produktversion nicht übereinstimmen müssen. Ich befürworte nicht die Verwendung unterschiedlicher Nummernsätze, aber es erleichtert das Leben erheblich, wenn kleine Änderungen an einer Assembly vorgenommen werden, die keine öffentlichen Schnittstellen betreffen, die Sie nicht zwingen müssen, abhängige Assemblys neu zu kompilieren. Ich gehe damit um, indem ich nur die Major- und Minor-Nummern in der Assembly-Version einstelle, aber alle Werte in der File-Version einstelle. Beispielsweise:

  • 1.2.0.0 (AssemblyVersion)
  • 1.2.3.4 (FileVersion)

Auf diese Weise können Sie Hotfixes bereitstellen, die den vorhandenen Code nicht beschädigen, da die Assembly-Versionen nicht übereinstimmen. Sie können jedoch die Revision/den Build einer Assembly anhand der Dateiversionsnummer anzeigen. Dies ist eine gebräuchliche Vorgehensweise und kann bei einigen Open-Source-Assemblys in den Assembly-Details eingesehen werden.

Sie als Teamleiter müssten dafür verantwortlich sein, die untergeordnete Nummer zu erhöhen, wenn jemals eine Änderung erforderlich ist. Eine Lösung für die Einführung einer erforderlichen Änderung an einer Schnittstelle, ohne den vorherigen Code zu beschädigen, besteht darin, die aktuelle als veraltet zu markieren und eine neue Schnittstelle zu erstellen. Dies bedeutet, dass vorhandener Code gewarnt wird, dass die Methode veraltet ist und jederzeit entfernt werden kann, ohne dass Sie alles sofort auflösen müssen. Sie können dann die veraltete Methode entfernen, wenn alles migriert wurde.

So verdrahten Sie es zusammen

Sie könnten das alles manuell erledigen, aber es wäre sehr zeitaufwendig. Im Folgenden wird beschrieben, wie wir den Prozess automatisieren. Jeder Schritt ist ausführbar.

  • Entfernen Sie die Attribute AssemblyVersion und AssemblyFileVersion aus allen AssemblyInfo.cs-Projektdateien.
  • Erstellen Sie eine allgemeine Assembly-Info-Datei (nennen Sie sie VersionInfo.cs) und fügen Sie sie allen Ihren Projekten als verknüpftes Element hinzu.
  • Fügen Sie der Version mit den Werten "0.0.0.0" die Attribute AssemblyVersion und AssemblyFileVersion hinzu.
  • Erstellen Sie ein MsBuild-Projekt, das Ihre Lösungsdatei erstellt.
  • Fügen Sie vor dem Build eine Aufgabe hinzu, die die VersionInfo.cs aktualisiert. Es gibt eine Reihe von Open Source-MsBuild-Bibliotheken, die eine AssemblyInfo-Task enthalten, mit der die Versionsnummer festgelegt werden kann. Einfach auf eine beliebige Zahl setzen und testen.
  • Fügen Sie eine Eigenschaftsgruppe hinzu, die eine Eigenschaft für jedes Segment der Build-Nummer enthält. Hier stellen Sie Dur und Moll ein. Die Build- und Revisionsnummer sollte als Argument übergeben werden.

Mit Subversion:

<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>

Hoffentlich war mir klar, aber es geht um viel. Bitte stellen Sie Fragen. Ich werde jedes Feedback nutzen, um einen präziseren Blog-Beitrag zusammenzustellen.

208
Bronumski

Die [AssemblyVersion] ist eine sehr große Sache in .NET. Eine Philosophie, die von Microsoft unterstützt wird, ist, dass Sie es automatisch inkrementieren lassen, um alle Projekte zu erzwingen, deren Neukompilierung von der Assembly abhängt. Funktioniert einwandfrei, wenn Sie einen Build-Server verwenden. Es ist niemals das Falsche , sich vor Schwertträgern in Acht zu nehmen.

Das andere, das enger mit seiner tatsächlichen Bedeutung zusammenhängt, ist, dass die Nummer für die Versionierung der öffentlichen Schnittstelle der Versammlung repräsentativ ist. Mit anderen Worten, Sie ändern es nur, wenn Sie eine öffentliche Schnittstelle oder Klasse ändern. Da nur eine solche Änderung erfordert, dass Kunden der Versammlung neu kompiliert werden. Dies muss jedoch manuell erfolgen, da das Build-System nicht intelligent genug ist, um eine solche Änderung automatisch zu erkennen.

Sie können diesen Ansatz erweitern, indem Sie die Version nur erhöhen, wenn die Assembly auf Computern außerhalb Ihrer Reichweite bereitgestellt wurde. Dies ist der Ansatz, den Microsoft verwendet. Die Versionsnummern der .NET-Assemblys ändern sich sehr selten. Vor allem wegen der erheblichen Schmerzen, die es bei ihren Kunden verursacht.

Was Microsoft predigt, ist also nicht das, was es praktiziert. Die Steuerung des Erstellungsprozesses und der Versionsverwaltung ist jedoch beispiellos. Sie verfügen sogar über einen speziellen Softwareentwickler, der den Prozess überwacht. Hat nicht ganz so gut geklappt, insbesondere die WaitHandle.WaitOne (int) -Überlastung verursachte einiges an Schmerz . In .NET 4.0 mit einem ganz anderen Ansatz behoben, aber das geht ein bisschen über den Rahmen hinaus.

Es liegt vielmehr an Ihnen und Ihrem Vertrauen, wie gut Sie den Build-Prozess und die Release-Zyklen steuern können, um Ihre eigene Wahl zu treffen. Davon abgesehen ist es sehr angebracht, die [AssemblyFileVersion] automatisch zu erhöhen. Mit der Unannehmlichkeit, dass dies nicht unterstützt wird.

57
Hans Passant

Sie können den Build-Teil der Versionsnummer für das automatische Inkrementieren verwenden.

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

In Ihrer Umgebung ist eine Testversion eine Version mit einer Build-Version! = 0. Bei der Freigabe erhöhen Sie das untergeordnete Teil und setzen das Build-Teil auf 0. Auf diese Weise würden Sie freigegebene Assemblys identifizieren.

Wenn Sie Ihre Assemblys im GAC installieren, wird Ihr GAC mit der Zeit von vielen verschiedenen Versionen überflutet. Denken Sie also daran. Aber wenn Sie die DLLs nur lokal verwenden, halte ich dies für eine gute Praxis.

11
testalino

Ergänzend zu Bronumskis Antwort möchte ich darauf hinweisen, dass nach dem Semantic Versioning 2.0-Standard unter semver.org , Major.Minor.Build.Revision wäre illegal, da nach dem Erhöhen einer Zahl alle regulären Werte auf der rechten Seite auf Null zurückgesetzt werden müssten.

Eine bessere Möglichkeit, dem Standard zu folgen, wäre die Verwendung von Major.Minor+Build.Revision. Dies ist offensichtlich nicht für die Verwendung in AssemblyVersionAttribute vorgesehen, sondern es kann stattdessen ein benutzerdefiniertes Attribut oder eine statische Klasse verwendet werden.

Semver in TeamCity sollte mit dem Meta-Runner Power Pack verfügbar sein. Für Git mit Git-Flow (besonders in der .NET-Welt) fand ich GitVersion hilfreich.

9
sunside

Es gibt keine feste Regel für die Versionierung von Baugruppen. Probieren Sie einfach aus, welche für Sie geeignet ist. Ich empfehle Ihnen jedoch, den 4-Teile-Ansatz zu verwenden, da Sie die Flexibilität haben, die Sie für einige Änderungen benötigen in der Zukunft.

... zum Beispiel: 1.0.0. *

Reserviert - Dies erhöht die Flexibilität, falls Sie in Zukunft Änderungen vornehmen möchten. Behalten Sie jedoch standardmäßig den Wert 0 bei.

Ziehen Sie auch in Betracht, die Assembly mit einem starken Schlüssel zu signieren. Dies löst das Assembly-Konfliktproblem, wenn Sie mehrere Assembly-Versionen im GAC registriert haben. MSDN Link

1