CIプラットフォーム(Hudson)を介してC#アセンブリバージョンを自動インクリメントするにはどうすればよいですか?


112

私と私のグループは、アセンブリのバージョン番号をインクリメントすることに恐ろしく、1.0.0.0バージョンのアセンブリを頻繁に出荷しています。明らかに、これは多くの頭痛の種です。

CIプラットフォームを介してプラクティスを大幅に改善しているassemblyinfo.csので、ファイル内の値を自動インクリメントして、アセンブリのバージョンがそのアセンブリのコード変更で自動更新されるように設定したいと思います。

以前に(Hudsonを見つける前に)msbuildまたはコマンドライン(覚えていない)を介して値をインクリメントする方法をセットアップしましたが、Hudsonを使用すると、SVNリポジトリが更新され、別のビルドがトリガーされます。Hudsonが1時間ごとにSVNをポーリングするため、遅い無限ループが発生します。

ハドソンにバージョン番号を増加させることは悪い考えですか?それを行う別の方法は何でしょうか?

理想的には、ソリューションの私の基準は次のようなものになるでしょう:

  • ビルドassemblyinfo.cs前にビルド番号をインクリメントします
  • 変更されたアセンブリのビルド番号のみをインクリメントします。Hudsonはビルドを行うたびにプロジェクトフォルダーを一掃するため、これは不可能である可能性があります
  • 変更されたassemblyinfo.csをコードリポジトリにコミットします(現在はVisualSVN
  • Hudsonが次に変更をスキャンするときに新しいビルドをトリガーしません

私の頭の中でこれを解決すると、バッチファイル/コマンドを介してこのほとんどの解決策を簡単に思いつくことができましたが、私のすべてのアイデアにより、次にスキャンするときにHudsonが新しいビルドをトリガーするようになります。私は私のためにすべてを行う誰かを探しているのではなく、正しい方向に私を向けるだけで、おそらくHudsonに特定のSVNコミットを無視させるテクニックなどです。

これまでに見つけたものはすべて、バージョン番号を自動的にインクリメントする方法を説明する記事にすぎません。無限ループになる可能性のあるCIプラットフォームは考慮されていません。

回答:


63

簡単な代替策は、C#環境でバージョン属性をmajor.minor.*(AssemblyInfoファイルテンプレートで説明されているように)に設定して、アセンブリバージョンをインクリメントすることです。

ただし、より包括的なソリューションを探している場合もあります。

編集(コメント内の質問への応答):

からAssemblyInfo.cs

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Build and Revision Numbers 
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]

私はこれに遭遇したことがありません。それが何をするかについてもう少し詳しく説明してもらえますか?1つのIDE内でのみ機能しますか、それともCIプラットフォームを使用する開発者のチーム全体で機能しますか?
アレンライス

ああ、私は以前に見たことがありますが、それは許容できる解決策かもしれませんが、ビルドされたものはsubversionなどに保存されていません。そのメカニズムがどのように機能するかについてさらに調査する必要があります、ありがとう!値として何を入力するかを決定する方法がわかりませんか?
アレンライス

1
あなたの質問に対する答えについては、以下の私の答えを参照してください。値はビルド時間に基づいて決定されます。
カイルトラウバーマン09/07/14

うわー、これはうまくいくと思います。どのように私たちがそのような単純なソリューションを見落としていたのかわかりません
アレン・ライス

お役に立てれば幸いです。簡単で速い方法が正しい方法であるのに、なぜ難しい方法をするのですか?:)
グレッグD

65

ここでは、AssemblyFileVersion属性をスタンプするために行ったことを説明します。

AssemblyInfo.csからAssemblyFileVersionを削除しました

AssemblyFileInfo.csという新しい空のファイルをプロジェクトに追加します。

MSBuildコミュニティタスクツールセットをhudsonビルドマシンにインストールするか、プロジェクトのNuGet依存関係としてインストールします。

プロジェクト(csproj)ファイルを編集します。これは単なるmsbuildファイルであり、以下を追加します。

どこかに<PropertyGroup>バージョンを記載するでしょう。たとえば、次のように変更します。

 <Major>1</Major>
 <Minor>0</Minor>
 <!--Hudson sets BUILD_NUMBER and SVN_REVISION -->
 <Build>$(BUILD_NUMBER)</Build>
 <Revision>$(SVN_REVISION)</Revision>

Hudsonは、プロジェクトがhudsonでビルドされたときにそこに表示されるそれらの環境変数を提供します(subversionからフェッチされたと想定)。

プロジェクトファイルの最後に、

 <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" Condition="Exists('$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets')" />
  <Target Name="BeforeBuild" Condition="Exists('$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets')">
    <Message Text="Version: $(Major).$(Minor).$(Build).$(Revision)" />
    <AssemblyInfo CodeLanguage="CS" OutputFile="AssemblyFileInfo.cs" AssemblyFileVersion="$(Major).$(Minor).$(Build).$(Revision)" AssemblyConfiguration="$(Configuration)" Condition="$(Revision) != '' " />
  </Target>

これは、MSBuildCommunityTasksを使用してAssemblyFileVersion.csを生成し、プロジェクトがビルドされる前にAssemblyFileVersion属性を含めます。必要に応じて、すべてのバージョン属性に対してこれを行うことができます。

結果は、hudsonビルドを発行するたびに、結果のアセンブリが1.0.HUDSON_BUILD_NR.SVN_REVISIONのAssemblyFileVersion、たとえば1.0.6.2632を取得することです。


1
だからこれを更新するだけです:メソッドはC#で動作します。しばらく使用しています。しかし、C ++アセンブリ(つまりC ++ / CLI)はまだ問題です。私の知る限り、AssemblyInfoタスクは有効なC ++を生成しません。また、この方法には、他の開発者が何が起こっているのかを理解するのがやや不透明であるという欠点があると思います。プロパティとしてバージョン番号をMSBuildに直接プッシュすることはできません...
CJBrew

@CJBrew AssemblyInfoのC ++コードを生成する小さな.batファイルを作成し、そのビルドをmsbuildで開始することができます。プロパティとしてプッシュすることの意味がわかりません。バージョン文字列を好きなプロパティに詰め込むことができます。ここで使用したメジャー/マイナー/ビルド/リビジョンを使用する必要はありません。
番号

このルートを使用することで得られるものは、AssemblyFileVersionをコメント化するだけでなく、[assembly:AssemblyVersion( "1.0。*")]と自動的に一致するように設定できるのですか
チェンバレン2014

@ColeChamberlain Hudsonからではなく、自分のPCのビジュアルスタジオからビルドすると、自動インクリメントされます。バージョン番号、特定のビルド、およびソースコードのリビジョンとは関係ありません。
nos

42

これは、新しいプロジェクトを追加するときに少し前もって作業を必要とするが、プロセスを非常に簡単に処理するエレガントなソリューションです。

各プロジェクトは、アセンブリのバージョン情報のみを含むソリューションファイルにリンクするという考えです。したがって、ビルドプロセスは1つのファイルを更新するだけでよく、すべてのアセンブリバージョンはコンパイル時に1つのファイルからプルされます。

手順:

  1. クラスをソリューションファイル* .csファイルに追加し、min SharedAssemblyProperties.csという名前を付けます
  2. その新しいファイルからすべてのcs情報を削除します
  3. AssemblyInfoファイルからアセンブリ情報を切り取ります:[assembly:AssemblyVersion( "1.0.0.0")] [assembly:AssemblyFileVersion( "1.0.0.0")]
  4. 「System.Reflectionを使用して」というステートメントを追加します。ファイルにデータを貼り付け、新しいcsファイル(例:SharedAssemblyProperties.cs)にデータを貼り付けます。
  5. プロジェクトに既存のアイテムを追加します(お待ちください...ファイルを追加する前に読んでください)
  6. ファイルを選択し、[追加]をクリックする前に、追加ボタンの横にあるドロップダウンをクリックして[リンクとして追加]を選択します。
  7. ソリューション内のすべての既存および新規プロジェクトについて、ステップ5および6を繰り返します。

ファイルをリンクとして追加すると、データがプロジェクトファイルに保存され、コンパイル時にこの1つのファイルからアセンブリバージョン情報がプルされます。

ソース管理で、SharedAssemblyProperties.csファイルを単純に増分するbatファイルまたはスクリプトファイルを追加すると、すべてのプロジェクトがそのファイルからアセンブリ情報を更新します。


ありがとう、マーク。リンク切れのため申し訳ありませんが、コミュニティサーバーは移動が簡単ではないことがわかりました。私はそのトピックについてのヘルプを検索する必要があります...
sondlerd '06 / 06/29

11

Hudsonは、特定のパスおよびファイルへの変更を無視するように構成できるため、新しいビルドを要求しません。

ジョブ構成ページの[ ソースコード管理 ]で、[ 詳細設定 ]ボタンをクリックします。Excluded Regionsボックスに、除外に一致する1つ以上の正規表現を入力します。

たとえば、version.propertiesファイルへの変更を無視するには、次のように使用できます。

/MyProject/trunk/version.properties

これはC#以外の言語でも機能し、バージョン情報をsubversion内に保存できます。


1
Hudsonは、コミットメッセージに応じて、特定のユーザーからのコミットを無視するか、ビルドをトリガーしないこともできます。この方法で、Hudsonからのすべてのコミットを無視できます。
Peter Schuetze、2010

9

.NETがこれを行います。AssemblyInfo.csファイルで、アセンブリのバージョンをmajor.minor。*に設定します(例:1.0。*)。

プロジェクトをビルドすると、バージョンが自動生成されます。

ビルド番号とリビジョン番号は、UNIXエポックを使用して日付に基づいて生成されると思います。ビルドは現在の日付に基づいており、リビジョンは午前0時以降の秒数に基づいています。


21
<ring、ring>「こんにちは、製品サポートはどのようにお手伝いできますか?」<お客様>「エラーが発生しました」<サポート>「OK、実行しているバージョンは?」<顧客>「バージョン1ポイント2リビジョン8 5 2 5 3 3 7 4ビルド7 4 6 3 3 5 2 9 ...」<サポート>「そのまま入力してください...うーん...バージョンを繰り返してください数値、そのビルドとリビジョンがリストされていないようです...」-GRRR!
神保

はははいいコメント。私もそのインクリメントシステムのファンではありません:p
ジョシュアヘイズ

3
ビジュアルスタジオでの自動インクリメントは、ひどいです。
Kugel

8
@神保:あなたのコメントがおかしいと私たちは皆同意しますが、実際には問題ではありません。VSインストールについて話すとき、あなたはVisual Studio 2008 SP1またはVS2008 9.0.30729.1 SPを持っていますか?自動インクリメントビルド番号の使用は非常に一般的なスキームであり、リリースビルドがリリースされたときにメジャー/マイナーバージョン番号をインクリメントすることで非常に簡単に「修正」できます。
Marek、

マイナーリビジョンを増やすために0にリセットする前のビルド番号は678です(もちろんcruisecontrolでは、cruisecontrolのようにhudsonよりもリセットするのが簡単であるように見えました。プロジェクトで0に戻しただけです。 、しかしハドソンの他のすべてがより良いです)
ディーン・ヒラー

8

1.0。*機能がVS2005またはVS2008で機能することは、実際には見たことがありません。VSを値をインクリメントするように設定するために実行する必要があるものはありますか?

AssemblyInfo.csが1.0。*でハードコーディングされている場合、実際のビルド/リビジョンはどこに保存されますか?

AssemblyInfoに1.0。*を入れた後、ProductVersionに無効な値が含まれているため、次のステートメントを使用できません。VSによって割り当てられた値ではなく、1.0。*を使用しています。

Version version = new Version(Application.ProductVersion);

ため息-これは誰もが尋ねるような問題のようですが、どういうわけか確実な答えはありません。何年も前に、ビルド後のプロセスの一部として、リビジョン番号を生成してAssemblyInfoに保存するためのソリューションを見ました。VS2008にはこのようなダンスが必要ないことを望みました。多分VS2010?


10
AssemblyFileVersionを削除する必要があります。それ以外に、それは私たちにとって素晴らしいことです、それは受け入れられた答えです。
アレンライス

1
はい、AssemblyFileVersionを削除するとバージョンが更新され、Versionに関するエラーは発生しなくなります。いいね。注:2つのビルド操作は、リビジョンを1度だけインクリメントしますが、ReBuildを実行すると、リビジョンが更新されます。ktraubermanが言ったように、それはbuild.revision = date.timeのように見えます。これは、データがアセンブリ以外のどこにも保存されない理由を説明しています。ここで、プライマリ出力プロジェクトが更新されたときに新しいProductCodeを生成する標準のMSIセットアップを取得する必要があります。セットアップはリビジョンを許可せず、ビルドのみを許可します。更新を行うために既存のインストールに上書きインストールしたい。研究する必要があります。
TonyG、2009年

5

私は、AssemblyVersion.ttが以下で行うような環境から、問題のアセンブリ属性をオンザフライで作成するテキストテンプレートを使用してこれを行うこともできると想定しています。

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".cs" #>
<#
var build = Environment.GetEnvironmentVariable("BUILD_NUMBER");
build = build == null ? "0" : int.Parse(build).ToString();
var revision = Environment.GetEnvironmentVariable("SVN_REVISION");
revision = revision == null ? "0" : int.Parse(revision).ToString();    
#>
using System.Reflection;
[assembly: AssemblyVersion("1.0.<#=build#>.<#=revision#>")]
[assembly: AssemblyFileVersion("1.0.<#=build#>.<#=revision#>")]

3

MikeSの回答の続きとして、これを機能させるにはVS + Visual Studio Visualization and Modeling SDKをインストールする必要があり、プロジェクトファイルも変更する必要があることを追加したいと思います。また、バージョンモジュールを備えたWindows 2008 R2サーバーボックスで実行されているビルドサーバーとしてJenkinsを使用しています。ここで、BUILD_NUMBERを取得します。

テキストテンプレートファイルversion.ttは次のようになります

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".cs" #>
<#
var build = Environment.GetEnvironmentVariable("BUILD_NUMBER");
build = build == null ? "0" : int.Parse(build).ToString();
var revision = Environment.GetEnvironmentVariable("_BuildVersion");
revision = revision == null ? "5.0.0.0" : revision;    
#>
using System.Reflection;
[assembly: AssemblyVersion("<#=revision#>")]
[assembly: AssemblyFileVersion("<#=revision#>")]

私は以下のプロパティグループを持っています

<PropertyGroup>
    <TransformOnBuild>true</TransformOnBuild>
    <OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles>
    <TransformOutOfDateOnly>false</TransformOutOfDateOnly>
</PropertyGroup>

Microsoft.CSharp.targetsをインポートした後、私はこれを持っています(VSをインストールする場所によって異なります)

<Import Project="C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\TextTemplating\v10.0\Microsoft.TextTemplating.targets" />

ビルドサーバーでは、次のスクリプトを使用して、実際のビルドの前にテキスト変換を実行し、TFSの最後のチェンジセット番号を取得します。

set _Path="C:\Build_Source\foo"

pushd %_Path% 
"%ProgramFiles(x86)%\Microsoft Visual Studio 10.0\Common7\IDE\tf.exe" history . /r /noprompt /stopafter:1 /Version:W > bar
FOR /f "tokens=1" %%foo in ('findstr /R "^[0-9][0-9]*" bar') do set _BuildVersion=5.0.%BUILD_NUMBER%.%%foo
del bar
popd

echo %BUILD_NUMBER%
echo %_BuildVersion%
cd C:\Program Files (x86)\Jenkins\jobs\MyJob\workspace\MyProject
MSBuild MyProject.csproj /t:TransformAll 
...
<rest of bld script>

このようにしてビルドとチェンジセットを追跡できるので、前回のビルド以降に何もチェックしていなければ、最後の桁は変更されませんが、ビルドプロセスに変更を加えた可能性があるため、最後から2番目の番号が必要です。もちろん、ビルドの前に複数のチェックインを行った場合、最後の変更のみがバージョンに反映されます。あなたはそれが必要であると連結することができると思います。

きっともっと洗練された方法でttテンプレート内からTFSを直接呼び出すことができると思いますが、これでうまくいきます。

次に、このように実行時にバージョンを取得できます

Assembly assembly = Assembly.GetExecutingAssembly();
FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(assembly.Location);
return fvi.FileVersion;

1

私のソリューションでは、外部ツールやスクリプト言語を追加する必要はありません。ビルドマシンでの動作はほぼ保証されています。この問題をいくつかの部分で解決します。まず、JenkinsのBUILD_NUMBERパラメータを環境変数に変換するBUILD.BATファイルを作成しました。Jenkinsの「Windowsバッチコマンドの実行」機能を使用して、Jenkinsビルドに関する次の情報を入力することにより、ビルドバッチファイルを実行します。

     ./build.bat --build_id %BUILD_ID% -build_number %BUILD_NUMBER%

ビルド環境には、次のように始まるbuild.batファイルがあります。

     rem build.bat
     set BUILD_ID=Unknown
     set BUILD_NUMBER=0
     :parse_command_line
     IF NOT "%1"=="" (
         IF "%1"=="-build_id" (
             SET BUILD_ID=%2
             SHIFT
             )
         IF "%1"=="-build_number" (
             SET BUILD_NUMBER=%2
             SHIFT
         )
         SHIFT
         GOTO :parse_command_line
     )
     REM your build continues with the environmental variables set
     MSBUILD.EXE YourProject.sln

それを行ったら、Visual Studioのソリューションエクスプローラーペインでビルドするプロジェクトを右クリックして[プロパティ]を選択し、[ビルドイベント]を選択して、ビルド前イベントコマンドラインとして次の情報を入力します。これにより、.csファイルが自動的に作成されます。現在の環境変数設定に基づくビルド番号情報が含まれています。

     set VERSION_FILE=$(ProjectDir)\Properties\VersionInfo.cs
     if !%BUILD_NUMBER%==! goto no_buildnumber_set
     goto buildnumber_set
     :no_buildnumber_set
     set BUILD_NUMBER=0
     :buildnumber_set
     if not exist %VERSION_FILE% goto no_version_file
     del /q %VERSION_FILE%
     :no_version_file
     echo using System.Reflection; >> %VERSION_FILE%
     echo using System.Runtime.CompilerServices; >> %VERSION_FILE%
     echo using System.Runtime.InteropServices; >> %VERSION_FILE%
     echo [assembly: AssemblyVersion("0.0.%BUILD_NUMBER%.1")] >> %VERSION_FILE%
     echo [assembly: AssemblyFileVersion("0.0.%BUILD_NUMBER%.1")] >> %VERSION_FILE%

ビルドの好みに合わせて調整する必要があるかもしれません。プロジェクトを手動で1回ビルドして、メインプロジェクトのPropertiesディレクトリに最初のVersion.csファイルを生成します。最後に、Version.csファイルを、そのプロジェクトの[プロパティ]タブの下の[ソリューションエクスプローラー]ペインにドラッグして、Visual Studioソリューションに手動で含めます。将来のビルドでは、Visual StudioはJenkinsのビルド時にその.csファイルを読み取り、そこから正しいビルド番号情報を取得します。


1

したがって、異なるバージョン番号のアセンブリを持ついくつかのプロジェクトを含む1つのソリューションを持つプロジェクトがあります。

上記の方法のいくつかを調査した後、AssemblyInfo.csファイルで検索と置換を行うPowershellスクリプトを実行するビルドステップを実装しました。私はまだソース管理で1.0。*バージョン番号を使用しており、Jenkinsはmsbuildが実行される前に手動でバージョン番号を更新します。

dir **/Properties/AssemblyInfo.cs | %{ (cat $_) | %{$_ -replace '^(\s*)\[assembly: AssemblyVersion\("(.*)\.\*"\)', "`$1[assembly: AssemblyVersion(`"`$2.$build`")"} | Out-File $_ -Encoding "UTF8" }
dir **/Properties/AssemblyInfo.cs | %{ (cat $_) | %{$_ -replace '^(\s*)\[assembly: AssemblyFileVersion\("(.*)\.\*"\)', "`$1[assembly: AssemblyFileVersion(`"`$2.$build`")"} | Out-File $_ -Encoding "UTF8" }

-Encoding "UTF8"オプションを追加したのは、gitが.csファイルをバイナリファイルとして扱っていなかったため、そうしなかったためです。確かに、私は実際に結果をコミットしたことがないので、これは問題ではありませんでした。それは私がテストしているときに現れました。

私たちのCI環境には、Jenkinsビルドを特定のgitコミットに関連付ける機能がすでにあるので(Stashプラグインに感謝します!)、バージョン番号が付けられたgitコミットがなくても心配ありません。


0

これはより単純なメカニズムです。MSBuildステップの前にWindowsバッチコマンドタスクビルドステップを追加し、単純な検索と置換プログラム(FART)を使用するだけです。

バッチステップ

fart --svn -r AssemblyInfo.cs "[assembly: AssemblyVersion(\"1.0.0.0\")]" "[assembly: AssemblyVersion(\"1.0.%BUILD_NUMBER%.%SVN_REVISION%\")]"
if %ERRORLEVEL%==0 exit /b 1
fart --svn -r AssemblyInfo.cs "[assembly: AssemblyFileVersion(\"1.0.0.0\")]" "[assembly: AssemblyFileVersion(\"1.0.%BUILD_NUMBER%.%SVN_REVISION%\")]"
if %ERRORLEVEL%==0 exit /b 1
exit /b 0

svn以外のソース管理を使用している場合は、ご使​​用のscm環境に適したオプションの--svnオプションを変更してください。

おならをダウンロード


0

ビルド前のPowershellスクリプト(https://gist.github.com/bradjolicoeur/e77c508089aea6614af3)を使用して、ビルドが成功するたびにインクリメントする方法をいくつか使用することにしました。Global.asaxでは、次のようにします。

  // We are using debug configuration, so increment our builds.
  if (System.Diagnostics.Debugger.IsAttached)
  {
      string version = System.Reflection.Assembly.GetExecutingAssembly()
                                                       .GetName()
                                                       .Version
                                                       .ToString();

      var psi = new ProcessStartInfo(@"svn", "commit -m \"Version: " + version + "\n \"");
      psi.WorkingDirectory = @"C:\CI\Projects\myproject";
      Process.Start(psi); 
  }

プロセス全体が複雑すぎるとまだ思います。同じ結果を達成するためのより効率的な方法を検討します。これは主に、バージョンをSVNに渡し、次に追加のツールをあまり使わずにJenkinに渡すために必要でした。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.