.net - 如何通过我们的CI平台(Hudson)自动增加C#程序集版本?




msbuild continuous-integration (8)

我自己和我的团队在增加程序集版本号方面非常可怕,我们经常以1.0.0.0版本发布程序集。 很明显,这会引起很多头痛。

通过我们的CI平台,我们的实践得到了很大改善,我真的希望将它设置为自动递增assemblyinfo.cs文件中的值,以便我们的程序集版本可以自动更新该组件。

我以前设置过(在我们找到Hudson之前)通过msbuild或命令行(不记得)增加值的方法,但是使用Hudson,它将更新SVN存储库并触发另一个构建。 随着Hudson每小时轮询SVN,这将导致缓慢的无限循环。

哈德森是否将版本号增加为一个坏主意? 什么是替代方法呢?

理想情况下,我的解决方案标准是:

  • 在构建之前增加buildinfo.cs中的内部版本号
  • 只增加已更改的程序集中的内部版本号。 这可能是不可能的,因为Hudson每次构建时都会擦除项目文件夹
  • 将更改的assemblyinfo.cs提交到代码库(当前为VisualSVN
  • 下次扫描变化时,不会导致Hudson触发新的构建

在我的脑海里解决这个问题,我可以很容易地通过批处理文件/命令想出一个解决方案,但是我所有的想法都会让Hudson在下次扫描时触发一个新的构建。 我不是在找人为我做所有事情,只是指向正确的方向,也许是让哈德森忽略某些SVN提交等技巧。

到目前为止,我发现的所有内容都只是一篇文章,解释如何自动增加版本号,没有考虑可以旋转成无限循环的CI平台。


.NET为你做这个。 在您的AssemblyInfo.cs文件中,将您的程序集版本设置为major.minor。*(例如:1.0。*)。

当你建立你的项目时,版本是自动生成的。

我相信,构建版本号和修订版号是根据日期生成的,使用unix时代。 构建基于当天,修订基于自午夜以来的秒数。


Hudson可以配置为忽略对某些路径和文件的更改,以便它不会提示新建立。

在作业配置页面的源代码管理下 ,单击高级按钮。 在排除的区域框中输入一个或多个正则表达式以匹配排除。

例如,要忽略可以使用的对version.properties文件的更改:

/MyProject/trunk/version.properties

这将适用于C#以外的其他语言,并允许您将版本信息存储在subversion中。


作为MikeS答案的延续,我想补充一点,需要安装VS + Visual Studio Visualization and Modeling SDK才能运行,并且还需要修改项目文件。 还应该提到,我使用Jenkins作为构建服务器,在具有版本模块的Windows 2008 R2服务器上运行,其中我获得了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>

这样我可以跟踪构建和变更集,所以如果自上次构建以来我没有检查过任何内容,最后一位数字不应该改变,但是我可能对构建过程进行了更改,因此需要第二个数字。 当然,如果您在构建之前进行多项签入,您只能获得版本中反映的最后一项更改。 我想你可以连接这是必需的。

我相信你可以做一些更有趣的事情,并直接从tt Template中调用TFS,但这对我很有用。

然后我可以像这样在运行时获得我的版本

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

我从来没有真正看到1.0。*功能在VS2005或VS2008中工作。 有什么需要做的设置VS增加值?

如果AssemblyInfo.cs使用1.0。*进行了硬编码,那么真正的构建/修订版存储在哪里?

在AssemblyInfo中放入1.0。*后,我们不能使用以下语句,因为ProductVersion现在具有无效值 - 它使用1.0。*而不是由VS分配的值:

Version version = new Version(Application.ProductVersion);

叹息 - 这似乎是每个人都会问的事情之一,但不知何故,这个问题从来没有一个可靠的答案。 几年前,我看到了一些解决方案,用于生成修订版编号并将其保存到AssemblyInfo中,作为后期构建过程的一部分。 我希望VS2008不需要这种舞蹈。 也许VS2010?


我决定使用一些使用预生成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的没有太多附加工具。


我的解决方案不需要添加外部工具或脚本语言 - 它几乎可以保证在您的构建机器上工作。 我在几个部分解决了这个问题。 首先,我创建了一个BUILD.BAT文件,将Jenkins BUILD_NUMBER参数转换为环境变量。 我使用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%

你可能需要适应你的品味。 我手动构建项目以在主项目的Properties目录中生成一个初始的Version.cs文件。 最后,通过将Version.cs文件拖放到解决方案资源管理器窗格中,将该版本文件手动包含到Visual Studio解决方案中,该窗格位于该项目的属性选项卡下。 在将来的构建中,Visual Studio会在Jenkins构建时读取该.cs文件,并从中获取正确的构建编号信息。


这是一个优雅的解决方案,需要在添加新项目时提前做一些工作,但很容易处理该过程。

这个想法是,每个项目链接到一个只包含程序集版本信息的解决方案文件。 所以你的编译过程只需要更新一个文件,编译时从一个文件中取出所有的程序集版本。

脚步:

  1. 为你的解决方案文件* .cs文件添加一个类,我将其命名为min SharedAssemblyProperties.cs
  2. 从新文件中删除所有cs信息
  3. 从AssemblyInfo文件中剪切程序集信息:[assembly:AssemblyVersion(“1.0.0.0”)] [assembly:AssemblyFileVersion(“1.0.0.0”)]
  4. 添加语句“using System.Reflection;” 添加到文件中,然后将数据粘贴到新的cs文件中(例如SharedAssemblyProperties.cs)
  5. 将项目添加到项目中(等待...在添加文件之前阅读)
  6. 选择文件,然后单击添加,然后单击添加按钮旁边的下拉列表并选择“添加为链接”。
  7. 对解决方案中的所有现有项目和新项目重复步骤5和6

将文件作为链接添加时,会将数据存储在项目文件中,并在编译时从该文件中提取程序集版本信息。

在源代码管理中,您添加一个bat文件或脚本文件,该文件只是递增SharedAssemblyProperties.cs文件,所有项目都将从该文件更新其装配信息。


这是一个更简单的机制。 它只需在MSBuild步骤之前添加Windows Batch命令任务构建步骤,并使用简单的查找和替换程序(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选项。

下载放屁





versioning