【问题标题】:Use SVN Revision to label build in CCNET使用 SVN Revision 标记 CCNET 中的构建
【发布时间】:2010-09-05 07:05:24
【问题描述】:

我在一个以 SVN 作为源代码控制的示例项目中使用 CCNET。 CCNET 配置为在每次签入时创建一个构建。CCNET 使用 MSBuild 构建源代码。

我想在编译时使用最新的修订号生成AssemblyInfo.cs。 如何从 subversion 中检索最新版本并使用 CCNET 中的值?

编辑:我没有使用 NAnt - 只有 MSBuild。

【问题讨论】:

    标签: svn msbuild cruisecontrol.net


    【解决方案1】:

    我目前正在使用我的cmdnetsvnrev 工具通过 prebuild-exec 任务“手动”执行此操作,但如果有人知道更好的 ccnet 集成方式,我会很高兴听到 :-)

    【讨论】:

      【解决方案2】:

      我在谷歌代码上找到了this 项目。这是CCNET 插件,用于在CCNET 中生成标签。

      DLL 已使用 CCNET 1.3 进行测试,但它适用于我的 CCNET 1.4。我成功地使用这个插件来标记我的构建。

      现在将其传递给MSBuild...

      【讨论】:

        【解决方案3】:

        您基本上有两种选择。您可以编写一个简单的脚本来启动和解析来自

        的输出

        svn.exe info --revision HEAD

        获取修订号(然后生成 AssemblyInfo.cs 非常简单)或仅使用 CCNET 插件。这里是:

        SVN Revision Labeller 是一个插件 CruiseControl.NET 允许您 为您生成 CruiseControl 标签 构建,基于修订号 您的 Subversion 工作副本。这 可以使用前缀和/或自定义 主要/次要版本号。

        http://code.google.com/p/svnrevisionlabeller/

        我更喜欢第一个选项,因为它只有大约 20 行代码:

        using System;
        using System.Diagnostics;
        
        namespace SvnRevisionNumberParserSample
        {
            class Program
            {
                static void Main()
                {
                    Process p = Process.Start(new ProcessStartInfo()
                        {
                            FileName = @"C:\Program Files\SlikSvn\bin\svn.exe", // path to your svn.exe
                            UseShellExecute = false,
                            RedirectStandardOutput = true,
                            Arguments = "info --revision HEAD",
                            WorkingDirectory = @"C:\MyProject" // path to your svn working copy
                        });
        
                    // command "svn.exe info --revision HEAD" will produce a few lines of output
                    p.WaitForExit();
        
                    // our line starts with "Revision: "
                    while (!p.StandardOutput.EndOfStream)
                    {
                        string line = p.StandardOutput.ReadLine();
                        if (line.StartsWith("Revision: "))
                        {
                            string revision = line.Substring("Revision: ".Length);
                            Console.WriteLine(revision); // show revision number on screen                       
                            break;
                        }
                    }
        
                    Console.Read();
                }
            }
        }
        

        【讨论】:

          【解决方案4】:

          如果您更喜欢在 MSBuild 端而不是 CCNet 配置,看起来像 MSBuild 社区任务扩展的 SvnVersion 任务可能会成功。

          【讨论】:

            【解决方案5】:

            自定义 csproj 文件以自动生成 AssemblyInfo.cs
            http://www.codeproject.com/KB/dotnet/Customizing_csproj_files.aspx

            每次我们创建一个新的 C# 项目时, Visual Studio 将 为我们准备的 AssemblyInfo.cs 文件。文件 定义程序集元数据,如 它的版本、配置或 制片人。

            发现上述技术可以使用 MSBuild 自动生成 AssemblyInfo.cs。很快就会发布示例。

            【讨论】:

              【解决方案6】:

              我编写了一个 NAnt 构建文件来处理解析 SVN 信息和创建属性。然后,我将这些属性值用于各种构建任务,包括在构建上设置标签。我将此目标与 lubos hasko 提到的 SVN Revision Labeller 结合使用,效果很好。

              <target name="svninfo" description="get the svn checkout information">
                  <property name="svn.infotempfile" value="${build.directory}\svninfo.txt" />
                  <exec program="${svn.executable}" output="${svn.infotempfile}">
                      <arg value="info" />
                  </exec>
                  <loadfile file="${svn.infotempfile}" property="svn.info" />
                  <delete file="${svn.infotempfile}" />
              
                  <property name="match" value="" />
              
                  <regex pattern="URL: (?'match'.*)" input="${svn.info}" />
                  <property name="svn.info.url" value="${match}"/>
              
                  <regex pattern="Repository Root: (?'match'.*)" input="${svn.info}" />
                  <property name="svn.info.repositoryroot" value="${match}"/>
              
                  <regex pattern="Revision: (?'match'\d+)" input="${svn.info}" />
                  <property name="svn.info.revision" value="${match}"/>
              
                  <regex pattern="Last Changed Author: (?'match'\w+)" input="${svn.info}" />
                  <property name="svn.info.lastchangedauthor" value="${match}"/>
              
                  <echo message="URL: ${svn.info.url}" />
                  <echo message="Repository Root: ${svn.info.repositoryroot}" />
                  <echo message="Revision: ${svn.info.revision}" />
                  <echo message="Last Changed Author: ${svn.info.lastchangedauthor}" />
              </target>
              

              【讨论】:

                【解决方案7】:

                我的方法是使用前面提到的 ccnet 插件和一个 nant echo 任务来生成一个 VersionInfo.cs 文件,其中只包含版本属性。我只需要将VersionInfo.cs 文件包含到构建中

                回显任务只是将我给它的字符串输出到一个文件中。

                如果有类似的 MSBuild 任务,您可以使用相同的方法。这是我使用的小任务:

                <target name="version" description="outputs version number to VersionInfo.cs">
                  <echo file="${projectdir}/Properties/VersionInfo.cs">
                    [assembly: System.Reflection.AssemblyVersion("$(CCNetLabel)")]
                    [assembly: System.Reflection.AssemblyFileVersion("$(CCNetLabel)")]
                  </echo>
                </target>
                

                试试这个:

                <ItemGroup>
                    <VersionInfoFile Include="VersionInfo.cs"/>
                    <VersionAttributes>
                        [assembly: System.Reflection.AssemblyVersion("${CCNetLabel}")]
                        [assembly: System.Reflection.AssemblyFileVersion("${CCNetLabel}")]
                    </VersionAttributes>
                </ItemGroup>
                <Target Name="WriteToFile">
                    <WriteLinesToFile
                        File="@(VersionInfoFile)"
                        Lines="@(VersionAttributes)"
                        Overwrite="true"/>
                </Target>
                

                请注意,我对 MSBuild 不是很熟悉,所以我的脚本可能无法直接使用,需要更正...

                【讨论】:

                  【解决方案8】:

                  小心。用于内部版本号的结构很短,因此您对修订的上限有一个上限。

                  在我们的例子中,我们已经超过了限制。

                  如果您尝试输入内部版本号 99.99.99.599999,文件版本属性实际上会显示为 99.99.99.10175。

                  【讨论】:

                  • 不是 System.Version 指定 .Revision 是 int32 的情况,因此您可以将其读出,而不是 Minor 和 Major,它们是掩码的 Int32 转换为短格式。
                  【解决方案9】:

                  CruiseControl.Net 1.4.4 现在有一个Assembly Version Labeller,它会生成与 .Net 程序集属性兼容的版本号。

                  在我的项目中,我将其配置为:

                  <labeller type="assemblyVersionLabeller" incrementOnFailure="true" major="1" minor="2"/>
                  

                  (警告:assemblyVersionLabeller 不会开始生成基于 svn 修订的标签,直到发生实际的提交触发构建。)

                  然后使用 MSBuildCommunityTasks.AssemblyInfo 从我的 MSBuild 项目中使用它:

                  <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
                  <Target Name="BeforeBuild">
                    <AssemblyInfo Condition="'$(CCNetLabel)' != ''" CodeLanguage="CS" OutputFile="Properties\AssemblyInfo.cs" 
                    AssemblyTitle="MyTitle" AssemblyCompany="MyCompany" AssemblyProduct="MyProduct"
                    AssemblyCopyright="Copyright ©  2009" ComVisible="false" Guid="some-random-guid"
                    AssemblyVersion="$(CCNetLabel)" AssemblyFileVersion="$(CCNetLabel)"/>
                  </Target>
                  

                  为了完整起见,使用 NAnt 而不是 MSBuild 的项目同样容易:

                  <target name="setversion" description="Sets the version number to CruiseControl.Net label.">
                      <script language="C#">
                          <references>
                              <include name="System.dll" />
                          </references>
                          <imports>
                              <import namespace="System.Text.RegularExpressions" />
                          </imports>
                          <code><![CDATA[
                               [TaskName("setversion-task")]
                               public class SetVersionTask : Task
                               {
                                protected override void ExecuteTask()
                                {
                                 StreamReader reader = new StreamReader(Project.Properties["filename"]);
                                 string contents = reader.ReadToEnd();
                                 reader.Close();
                                 string replacement = "[assembly: AssemblyVersion(\"" + Project.Properties["CCNetLabel"] + "\")]";
                                 string newText = Regex.Replace(contents, @"\[assembly: AssemblyVersion\("".*""\)\]", replacement);
                                 StreamWriter writer = new StreamWriter(Project.Properties["filename"], false);
                                 writer.Write(newText);
                                 writer.Close();
                                }
                               }
                               ]]>
                          </code>
                      </script>
                      <foreach item="File" property="filename">
                          <in>
                              <items basedir="..">
                                  <include name="**\AssemblyInfo.cs"></include>
                              </items>
                          </in>
                          <do>
                              <setversion-task />
                          </do>
                      </foreach>
                  </target>
                  

                  【讨论】:

                  • +1 太棒了,这对我帮助很大。我更新了您的 NAnt 版本,还更新了 AssemblyFileVersion 和一些小东西。它作为另一个答案包含在此线程中。谢谢!
                  • 其他人不应忽视这一警告;这是非常重要的。结果,网上有很多答案说这不起作用。仍然看起来有问题,但是在一次签入的基础上触发,之后一切都按预期工作。 -- 非常感谢
                  • 装配版本标签器的链接已损坏。
                  【解决方案10】:

                  基于 skolimas 解决方案,我更新了 NAnt 脚本以更新 AssemblyFileVersion。感谢 skolima 的代码!

                  <target name="setversion" description="Sets the version number to current label.">
                          <script language="C#">
                              <references>
                                      <include name="System.dll" />
                              </references>
                              <imports>
                                      <import namespace="System.Text.RegularExpressions" />
                              </imports>
                              <code><![CDATA[
                                       [TaskName("setversion-task")]
                                       public class SetVersionTask : Task
                                       {
                                        protected override void ExecuteTask()
                                        {
                                         StreamReader reader = new StreamReader(Project.Properties["filename"]);
                                         string contents = reader.ReadToEnd();
                                         reader.Close();                     
                                         // replace assembly version
                                         string replacement = "[assembly: AssemblyVersion(\"" + Project.Properties["label"] + "\")]";
                                         contents = Regex.Replace(contents, @"\[assembly: AssemblyVersion\("".*""\)\]", replacement);                                        
                                         // replace assembly file version
                                         replacement = "[assembly: AssemblyFileVersion(\"" + Project.Properties["label"] + "\")]";
                                         contents = Regex.Replace(contents, @"\[assembly: AssemblyFileVersion\("".*""\)\]", replacement);                                        
                                         StreamWriter writer = new StreamWriter(Project.Properties["filename"], false);
                                         writer.Write(contents);
                                         writer.Close();
                                        }
                                       }
                                       ]]>
                              </code>
                          </script>
                          <foreach item="File" property="filename">
                              <in>
                                      <items basedir="${srcDir}">
                                              <include name="**\AssemblyInfo.cs"></include>
                                      </items>
                              </in>
                              <do>
                                      <setversion-task />
                              </do>
                          </foreach>
                      </target>
                  

                  【讨论】:

                    【解决方案11】:

                    我不确定这是否适用于 CCNET,但我在 CodePlex 上为 Build Version Increment 项目创建了一个 SVN version plug-in。该工具非常灵活,可以设置为使用 svn 修订版自动为您创建版本号。它不需要编写任何代码或编辑 xml,所以耶!

                    希望对你有帮助!

                    【讨论】:

                      【解决方案12】:

                      不知道我在哪里找到的。但我在互联网上的“某处”找到了这个。

                      这会在构建发生之前更新所有 AssemblyInfo.cs 文件。

                      像魅力一样工作。我所有的 exe 和 dll 都显示为 1.2.3.333(如果“333”是当时的 SVN 修订版。)(并且 AssemblyInfo.cs 文件中的原始版本被列为“1.2.3.0”)


                      $(ProjectDir)(我的 .sln 文件所在的位置)

                      $(SVNToolPath)(指向 svn.exe)

                      是我的自定义变量,它们的声明/定义未在下面定义。


                      http://msbuildtasks.tigris.org/ 和/或 https://github.com/loresoft/msbuildtasks 有( FileUpdate 和 SvnVersion )任务。


                        <Target Name="SubVersionBeforeBuildVersionTagItUp">
                      
                          <ItemGroup>
                            <AssemblyInfoFiles Include="$(ProjectDir)\**\*AssemblyInfo.cs" />
                          </ItemGroup>
                      
                          <SvnVersion LocalPath="$(MSBuildProjectDirectory)" ToolPath="$(SVNToolPath)">
                            <Output TaskParameter="Revision" PropertyName="MySubVersionRevision" />
                          </SvnVersion>
                      
                          <FileUpdate Files="@(AssemblyInfoFiles)"
                                  Regex="(\d+)\.(\d+)\.(\d+)\.(\d+)"
                                  ReplacementText="$1.$2.$3.$(MySubVersionRevision)" />
                        </Target>
                      

                      编辑 ---------------------------------- ----

                      在您的 SVN 修订号达到 65534 或更高版本后,上述操作可能会开始失败。

                      见:

                      Turn off warning CS1607

                      这是解决方法。

                      <FileUpdate Files="@(AssemblyInfoFiles)"
                      Regex="AssemblyFileVersion\(&quot;(\d+)\.(\d+)\.(\d+)\.(\d+)"
                      ReplacementText="AssemblyFileVersion(&quot;$1.$2.$3.$(SubVersionRevision)" />
                      

                      这样的结果应该是:

                      在 Windows/Explorer//文件/属性中…….

                      程序集版本将为 1.0.0.0。

                      如果 333 是 SVN 修订版,则文件版本将为 1.0.0.333。

                      【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2023-03-22
                      • 1970-01-01
                      • 2011-03-19
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多