158

.NETアセンブリの3つの異なるアセンブリバージョン番号を管理する方法についての指針、提案、さらには口述を探しています。製品バージョンは最も単純です。これは通常、ビジネスによって決定されるようです。次に、ファイルバージョンは展開間のバージョン管理用であるように見えます。実際のアセンブリバージョンは出荷時にのみ使用されます。

今は、依存しないアセンブリのテストリリースとメンテナンスリリースにラベルを付ける簡単な方法を探しているので、ファイルバージョンのビルド番号とリビジョン番号を自動インクリメントし、最終リリースでは現在のリリースをコピーします。ファイルバージョンからアセンブリバージョンへ。この製品は実稼働環境で使用されていますが、まだ開発中です-ご存知のとおり-これらの小さな会社の1つであり、変更管理インフラストラクチャの状況はありません。

4

6 に答える 6

216

バージョン管理は私が非常に情熱を持っていることであり、使いやすいバージョン管理システムを考え出すために長い時間を費やしてきました。質問ですでに述べたことから、1つの重要な点を理解していることは明らかです。アセンブリのバージョン番号は、製品のバージョンと同義ではありません。1つは技術的に推進され、もう1つはビジネスによって推進されます。

以下は、何らかの形式のソース管理とビルドサーバーを使用することを前提としています。コンテキストには、TeamCityとSubversion/Gitを使用します。TeamCityは、少数のプロジェクトに対して無料であり、非常に優れたビルドサーバーですが、他にもあり、その一部は完全に無料です。

バージョン番号の意味

ある人にとってバージョンが意味することは、別の人とは異なることを意味する場合があります。一般的な構造は、メジャー、マイナー、マクロ、ミクロです。私がバージョン番号を見る方法は、それを2つの部分に分解することです。前半では、メインバージョン(メジャー)と主要な更新(マイナー)について説明します。後半は、いつビルドされたか、ソースコードのバージョンは何かを示しています。バージョン番号も、API、Webアプリなど、コンテキストに応じて異なる意味を持ちます。

MajorMinorBuildRevision

  • Revisionこれは、実際に構築されたものを識別するためにソース管理から取得された数値です。
  • Buildこれは、ビルドサーバーで特定のビルドを見つけるために使用できる数が増え続けています。ビルドサーバーが異なるパラメーターのセットを使用して同じソースを2回ビルドした可能性があるため、これは重要な数値です。ビルド番号をソース番号と組み合わせて使用​​すると、何がどのようにビルドされたかを識別できます。
  • Minorこれは、パブリックインターフェイスに大幅な変更があった場合にのみ変更する必要があります。たとえば、それがAPIの場合、消費するコードは引き続きコンパイルできますか?メジャー番号が変更されたら、この番号をゼロにリセットする必要があります。
  • Major使用している製品のバージョンを示します。たとえば、すべてのVisualStudio 2008アセンブリのメジャーは9で、VisualStudio2010は10です。

ルールの例外

ルールには常に例外があり、それらに遭遇したときに適応する必要があります。私の元々のアプローチはSubversionの使用に基づいていましたが、最近Gitに移行しました。中央リポジトリを使用するSubversionやSourceSafeなどのソース管理には、特定の時間から特定のソースのセットを識別するために使用できる番号があります。これは、Gitなどの分散ソース管理には当てはまりません。Gitは各開発マシンにある分散リポジトリを使用するため、使用できる自動インクリメントの数がないため、チェックインの数を使用するハックがありますが、それは醜いです。このため、私は自分のアプローチを進化させなければなりませんでした。

MajorMinorMacroBuild

リビジョン番号がなくなり、ビルドが以前のリビジョンにシフトし、マクロが挿入されました。マクロは自分に合った方法で使用できますが、ほとんどの場合、そのままにしておきます。TeamCityを使用しているため、リビジョン番号から失われた情報はビルドで見つけることができます。これは、2段階のプロセスがあることを意味しますが、何も失われておらず、許容できる妥協案です。

何を設定するか

最初に理解することは、アセンブリバージョン、ファイルバージョン、および製品バージョンが一致している必要はないということです。私は異なる番号のセットを持つことを推奨していませんが、依存するアセンブリを再コンパイルする必要がないパブリックインターフェイスに影響を与えないアセンブリに小さな変更を加えると、作業がはるかに楽になります。私がこれに対処する方法は、アセンブリバージョンでメジャー番号とマイナー番号を設定するだけで、ファイルバージョンですべての値を設定することです。例えば:

  • 1.2.0.0(AssemblyVersion)
  • 1.2.3.4(FileVersion)

これにより、アセンブリのバージョンが一致しないために既存のコードを壊さないホットフィックスをロールアウトできますが、ファイルのバージョン番号を確認することでアセンブリのリビジョン/ビルドを確認できます。これは一般的なアプローチであり、アセンブリの詳細を見ると、一部のオープンソースアセンブリで確認できます。

チームリーダーであるあなたは、重大な変更が必要になったときに、マイナー番号を増やす責任を負う必要があります。必要な変更をインターフェースにロールアウトするが、以前のコードを壊さないための1つの解決策は、現在のコードを廃止としてマークし、新しいインターフェースを作成することです。これは、既存のコードがメソッドが廃止され、いつでも削除できることを警告されていることを意味しますが、すべてをすぐに中断する必要はありません。その後、すべてが移行されたら、廃止されたメソッドを削除できます。

一緒に配線する方法

上記のすべてを手動で行うこともできますが、非常に時間がかかります。以下は、プロセスを自動化する方法です。各ステップは実行可能です。

  • すべてのプロジェクトAssemblyInfo.csファイルからAssemblyVersionおよび属性を削除します。AssemblyFileVersion
  • 共通のアセンブリ情報ファイル(VersionInfo.csと呼びます)を作成し、リンクされたアイテムとしてすべてのプロジェクトに追加します。
  • 値が「0.0.0.0」のバージョンに属性を追加AssemblyVersionします。AssemblyFileVersion
  • ソリューションファイルをビルドするMsBuildプロジェクトを作成します。
  • VersionInfo.csを更新するビルドの前にタスクを追加します。バージョン番号を設定できるAssemblyInfoタスクを含むオープンソースのMsBuildライブラリがいくつかあります。任意の数に設定してテストするだけです。
  • ビルド番号の各セグメントのプロパティを含むプロパティグループを追加します。ここでメジャーとマイナーを設定します。ビルド番号とリビジョン番号は引数として渡す必要があります。

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>

うまくいけば、私は明確になりましたが、多くのことが関係しています。ご不明な点がございましたらお問い合わせください。フィードバックを使用して、より簡潔なブログ投稿をまとめます。

于 2010-10-11T10:42:02.873 に答える
58

[AssemblyVersion]は、.NETでは非常に重要です。Microsoftが奨励している哲学の1つは、自動インクリメントを許可し、アセンブリに依存するすべてのプロジェクトを強制的に再コンパイルすることです。ビルドサーバーを使用する場合は問題なく動作します。決して間違ったことではありませんが、剣を持っている人には注意してください。

もう1つは、実際の意味とより密接に関連しているのは、番号がアセンブリのパブリックインターフェイスのバージョン管理を表すことです。つまり、パブリックインターフェイスまたはクラスを変更する場合にのみ変更します。そのような変更のみがアセンブリのクライアントを再コンパイルする必要があるためです。ただし、これは手動で行う必要がありますが、ビルドシステムは、このような変更を自動検出するほどスマートではありません。

アセンブリが手の届かないマシンにデプロイされたときにバージョンをインクリメントするだけで、このアプローチをさらに拡張できます。これはMicrosoftが使用するアプローチであり、.NETアセンブリのバージョン番号が変更されることはめったにありません。主にそれが彼らの顧客に引き起こす非常にかなりの苦痛のためです。

したがって、マイクロソフトが説くのは、マイクロソフトが実践していることではありません。ただし、そのビルドプロセスとバージョン管理は比類のないものであり、プロセスを監視する専任のソフトウェアエンジニアもいます。特にWaitHandle.WaitOne(int)の過負荷は、かなりの痛みを引き起こしました。.NET 4.0で非常に異なるアプローチで修正されましたが、それは範囲を少し超えています。

ビルドプロセスとリリースサイクルをどれだけうまく制御して自分で選択できるかは、あなたとあなたの自信次第です。それ以外は、[AssemblyFileVersion]を自動的に自動インクリメントするのが非常に適切です。ただし、これはサポートされていないという不便があります。

于 2010-09-22T13:05:57.487 に答える
11

自動インクリメントには、バージョン番号のビルド部分を使用できます。

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

ご使用の環境では、テストバージョンはビルドバージョン!= 0のバージョンです。リリース時にマイナーパーツをインクリメントし、ビルドパーツを0に設定します。これにより、リリースされたアセンブリを識別できます。

アセンブリをGACにインストールすると、GACは時間の経過とともに多くの異なるバージョンで溢れるので、それを覚えておいてください。ただし、ローカルでのみdllを使用する場合は、これは良い習慣だと思います。

于 2010-09-22T11:08:02.503 に答える
10

Bronumskisの回答に加えて、semver.orgのSemantic Versioning 2.0標準のMajor.Minor.Build.Revision後、数値を増やした後、右側のすべての通常の値をゼロにリセットする必要があるという規則により、違法になることを指摘したいと思います。

標準に従うより良い方法は、を使用することMajor.Minor+Build.Revisionです。これは明らかにで使用するためのものではありませんAssemblyVersionAttributeが、代わりにカスタム属性または静的クラスを使用できます。

TeamCityのSemverは、Meta-runnerPowerPackを使用して利用できる必要があります。git-flowを使用したgit(特に.NETの世界)では、GitVersionが役立つことがわかりました。

于 2014-03-12T16:34:18.863 に答える
1

アセンブリのバージョン管理に関しては、厳格なルールはありません。自由に試してみてください。ただし、変更を加えたい場合に備えて柔軟性があるため、4つの部分からなるアプローチを使用することをお勧めします。将来。

...例:1.0.0。*

予約済み-将来変更を加えたい場合に備えて、柔軟性が追加されます。ただし、デフォルトでは、0のままにします。

また、強力なキーを使用してアセンブリに署名することを検討してください。これにより、GACに複数のバージョンのアセンブリが登録されている場合のアセンブリの競合の問題が解決されます。 MSDNリンク

于 2010-10-08T20:32:13.973 に答える
0

アセンブリ情報を自動生成するためのT4テンプレートの例を次に示しますアセンブリバージョンは、変換が実行されるたびにインクリメントされます。プロジェクトデータのみを入力する必要があります。

// Names.
string projectName = "MyProjectName"; // Project (short name for COM).
string productName = "My Project Name"; // Full title.
string developerName = "Developer Name"; // Developer.
string assemblyType = "Application"; // Application, Library, etc.

// Version.
int majorVersion = 1;
int minorVersion = 0;

// Year of the start of work on the project.
string since = "2021";

テンプレートを変換すると、次のような出力が得られます。

#if COMVISIBLE
using System.EnterpriseServices;
#endif
using System.Reflection;
using System.Runtime.InteropServices;

// General information about this assembly is provided by the following set
// attributes. Change the values of these attributes to change the information,
// related to the assembly.
[assembly: AssemblyTitle ("My Project Name Application 1.0")] // Assembly name.
[assembly: AssemblyDescription ("My Project Name Application 1.0")] // Assembly description.
[assembly: AssemblyCompany ("Developer Name")] // Developer.
[assembly: AssemblyProduct ("Developer Name My Project Name Application")] // Product name.
[assembly: AssemblyCopyright ("© Developer Name 2021")] // Copyright.
//[assembly: AssemblyTrademark ("Developer Name ® My Project Name Application®")] // Trademark.
[assembly: AssemblyCulture ("")]
[assembly: AssemblyVersion ("1.0.2110.0047")]
[assembly: AssemblyFileVersion ("1.0.2110.0047")]
#if DEBUG
[assembly: AssemblyConfiguration ("Debug")]
#else
[assembly: AssemblyConfiguration ("Release")]
#endif

// Setting ComVisible to False makes the types in this assembly invisible
// for COM components. If you need to refer to the type in this assembly via COM,
// set the ComVisible attribute to TRUE for this type.
#if COMVISIBLE
[assembly: ComVisible (true)]
[assembly: ApplicationName ("MyProjectName")] // The name of the COM application.
[assembly: ApplicationID ("fc24620a-239d-4e40-b756-7ed38e82ef69")]
#else
[assembly: ComVisible (false)]
#endif
// The following GUID is used to identify the type library if this project will be visible to COM
[assembly: Guid ("e60d1ecf-6c7b-4c9b-925f-4bf07615da87")]
于 2022-01-23T20:03:17.733 に答える