使用SVN修订版在CCNET中标记构建
我在将SVN作为源控件的示例项目上使用CCNET。 CCNET被配置为在每次签入时都创建一个构建。CCNET使用MSBuild来构建源代码。
我想在编译时使用最新的修订版号生成AssemblyInfo.cs
。
如何从Subversion检索最新修订并在CCNET中使用该值?
编辑:我不只使用NAnt MSBuild。
解决方案
回答
我目前正在使用cmdnetsvnrev工具通过prebuild-exec Task进行"手动"操作,但是如果有人知道更好的ccnet集成方法,我会很高兴听到:-)
回答
我在Google代码上找到了这个项目。这是CCNET插件,用于在CCNET中生成标签。
DLL是通过CCNET 1.3测试的,但对我来说是CCNET 1.4的作品。我已成功使用此插件标记了我的构建。
现在将其传递给MSBuild ...
回答
我们基本上有两个选择。我们可以编写一个简单的脚本来启动并解析来自
svn.exe信息-修订版HEAD
获取修订号(然后直接生成AssemblyInfo.cs)或者仅将插件用于CCNET。这里是:
SVN Revision Labeller is a plugin for CruiseControl.NET that allows you to generate CruiseControl labels for your builds, based upon the revision number of your Subversion working copy. This can be customised with a prefix and/or major/minor version numbers. 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(); } } }
回答
如果我们更喜欢在CCBuild配置之外的MSBuild一侧执行此操作,则看起来MSBuild社区任务扩展的SvnVersion任务可以解决问题。
回答
Customizing csproj files to autogenerate AssemblyInfo.cs http://www.codeproject.com/KB/dotnet/Customizing_csproj_files.aspx Every time we create a new C# project, Visual Studio puts there the AssemblyInfo.cs file for us. The file defines the assembly meta-data like its version, configuration, or producer.
找到了使用MSBuild自动生成AssemblyInfo.cs的上述技术。将在不久后发布样品。
回答
我编写了一个NAnt构建文件,用于处理SVN信息解析和创建属性。然后,我将这些属性值用于各种构建任务,包括在构建中设置标签。我将此目标与lubos hasko提到的SVN修订标签机结合使用,效果很好。
<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>
回答
我的方法是使用上述用于ccnet的插件和一个nant echo任务来生成VersionInfo.cs
文件,其中只包含版本属性。我只需要将VersionInfo.cs
文件包含到构建中
echo任务只是将我给它的字符串输出到文件中。
如果存在类似的MSBuild任务,则可以使用相同的方法。这是我使用的小nant任务:
<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不太了解,因此我的脚本可能无法即用即用,需要更正...
回答
当心。用于内部版本号的结构很短,因此我们可以对修订版本进行最高限制。
在我们的情况下,我们已经超出了限制。
如果我们尝试输入内部版本号99.99.99.599999,则文件版本属性实际上会显示为99.99.99.10175.
回答
CruiseControl.Net 1.4.4现在具有程序集版本标签程序,该程序生成与.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>
回答
基于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>
回答
我不确定这是否可以与CCNET一起使用,但是我已经为CodePlex上的Build Version Increment项目创建了SVN版本插件。该工具非常灵活,可以设置为使用svn修订版自动为我们创建版本号。它不需要编写任何代码或者编辑xml,所以是的!
希望对我们有所帮助!