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

.net 如何通过我们的CI平台(Hudson)自动增加C#assembly版本?,.net,msbuild,continuous-integration,hudson,versioning,.net,Msbuild,Continuous Integration,Hudson,Versioning,我和我的团队在增加程序集版本号方面表现得非常糟糕,我们经常以1.0.0.0版本发布程序集。显然,这会引起很多头痛 通过我们的平台,我们的实践取得了很大的进步,我真的希望将其设置为自动增加assemblyinfo.cs文件中的值,以便使用该程序集中的代码更改自动更新程序集的版本 在我们找到之前,我已经设置了一种通过msbuild或命令行(不记得了)来增加值的方法,但是在Hudson中,这将更新SVN存储库并触发另一个构建。这将导致一个缓慢的无限循环,因为哈得逊调查SVN每小时一次 让哈德逊增加版本

我和我的团队在增加程序集版本号方面表现得非常糟糕,我们经常以1.0.0.0版本发布程序集。显然,这会引起很多头痛

通过我们的平台,我们的实践取得了很大的进步,我真的希望将其设置为自动增加
assemblyinfo.cs
文件中的值,以便使用该程序集中的代码更改自动更新程序集的版本

在我们找到之前,我已经设置了一种通过
msbuild
或命令行(不记得了)来增加值的方法,但是在Hudson中,这将更新SVN存储库并触发另一个构建。这将导致一个缓慢的无限循环,因为哈得逊调查SVN每小时一次

让哈德逊增加版本号是个坏主意吗?另一种方法是什么

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

  • 在生成之前增加
    assemblyinfo.cs
    中的生成编号
  • 仅增加已更改的程序集中的内部版本号。这可能不可能,因为Hudson每次生成时都会清除项目文件夹
  • 将更改的assemblyinfo.cs提交到代码存储库(当前)
  • 不会导致Hudson在下次扫描更改时触发新构建
在我的头脑中解决这个问题,我可以很容易地通过批处理文件/命令来解决大部分问题,但我所有的想法都会导致Hudson在下次扫描时触发一个新的构建。我不是在找一个人为我做每件事,只是给我指出正确的方向,也许是一种让Hudson忽略某些SVN提交的技术,等等


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

一个简单的替代方法是让C#环境通过将version属性设置为
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.*")]

.NET为您提供此功能。在AssemblyInfo.cs文件中,将程序集版本设置为major.minor.*(例如:1.0.*)

构建项目时,版本将自动生成


构建和修订号是基于日期生成的,我相信是使用unix纪元生成的。生成基于当天,修订基于午夜后的秒数。

可以将Hudson配置为忽略对某些路径和文件的更改,从而不会提示新生成

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

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

/MyProject/trunk/version.properties

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

我从未在VS2005或VS2008中实际见过1.0.*功能。是否需要做些什么来设置VS以增加值

如果AssemblyInfo.cs硬编码为1.0.*,那么实际生成/修订存储在哪里

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

Version version = new Version(Application.ProductVersion);

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

这是一个优雅的解决方案,在添加新项目时需要提前做一些工作,但处理过程非常简单

其思想是每个项目链接到一个只包含程序集版本信息的解决方案文件。因此,构建过程只需更新一个文件,所有程序集版本在编译时都从一个文件中提取

步骤:

  • 在解决方案文件*.cs文件中添加一个类,我将其命名为min SharedAssemblyProperties.cs
  • 从新文件中删除所有cs信息
  • 从AssemblyInfo文件中剪切部件信息: [汇编:汇编版本(“1.0.0.0”)] [程序集:AssemblyFileVersion(“1.0.0.0”)]
  • 将语句“using System.Reflection;”添加到文件中,然后将数据粘贴到新的cs文件中(例如SharedAssemblyProperties.cs)
  • 将现有项添加到项目中(请稍候…在添加文件之前继续阅读)
  • 选择文件,在单击“添加”之前,单击“添加”按钮旁边的下拉列表,然后选择“添加为链接”
  • 对解决方案中的所有现有项目和新项目重复步骤5和6
  • 将文件添加为链接时,它将数据存储在项目文件中,并在编译时从此文件中提取程序集版本信息


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

    以下是我所做的,用于标记AssemblyFileVersion属性

    已从AssemblyInfo.cs中删除AssemblyFileVersion

    将名为AssemblyFileInfo.cs的新空文件添加到项目中

    将该工具集安装在hudson build机器上,或作为项目的一部分

    编辑项目(csproj)文件,它只是一个msbuild文件,并添加以下内容

    总有一天会有一家公司
     <Major>1</Major>
     <Minor>0</Minor>
     <!--Hudson sets BUILD_NUMBER and SVN_REVISION -->
     <Build>$(BUILD_NUMBER)</Build>
     <Revision>$(SVN_REVISION)</Revision>
    
     <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>
    
    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
    
    <#@ 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#>")]
    
    <#@ 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>
    
    <Import Project="C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\TextTemplating\v10.0\Microsoft.TextTemplating.targets" />
    
    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>
    
    Assembly assembly = Assembly.GetExecutingAssembly();
    FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(assembly.Location);
    return fvi.FileVersion;
    
         ./build.bat --build_id %BUILD_ID% -build_number %BUILD_NUMBER%
    
         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
    
         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%
    
      // 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); 
      }
    
    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" }