我在以 SVN 作为源代码控制的示例项目中使用 CCNET。CCNET 配置为在每次签入时创建构建。CCNET 使用 MSBuild 构建源代码。
我想AssemblyInfo.cs
在编译时使用最新的修订号来生成。如何从 subversion 中检索最新版本并使用 CCNET 中的值?
编辑:我没有使用 NAnt - 只有 MSBuild。
我在以 SVN 作为源代码控制的示例项目中使用 CCNET。CCNET 配置为在每次签入时创建构建。CCNET 使用 MSBuild 构建源代码。
我想AssemblyInfo.cs
在编译时使用最新的修订号来生成。如何从 subversion 中检索最新版本并使用 CCNET 中的值?
编辑:我没有使用 NAnt - 只有 MSBuild。
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>
你基本上有两个选择。您可以编写一个简单的脚本来启动并解析来自
svn.exe 信息 --revision HEAD
获取修订号(然后生成 AssemblyInfo.cs 非常简单)或仅使用 CCNET 插件。这里是:
SVN Revision Labeller是 CruiseControl.NET 的插件,它允许您根据 Subversion 工作副本的修订号为您的构建生成 CruiseControl 标签。这可以使用前缀和/或主要/次要版本号进行自定义。
我更喜欢第一个选项,因为它只有大约 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();
}
}
}
我在谷歌代码上找到了这个项目。这是CCNET
生成标签的插件CCNET
。
DLL
已经过测试,但CCNET 1.3
它适用CCNET 1.4
于我。我成功地使用这个插件来标记我的构建。
现在将其传递给MSBuild
...
如果您更喜欢在配置上执行它MSBuild
,CCNet
看起来MSBuild
社区任务扩展的SvnVersion
任务可能会成功。
我编写了一个 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>
我目前正在使用我的cmdnetsvnrev工具通过 prebuild-exec 任务“手动”执行此操作,但如果有人知道更好的 ccnet 集成方式,我会很高兴听到 :-)
自定义 csproj 文件以自动生成 AssemblyInfo.cs
http://www.codeproject.com/KB/dotnet/Customizing_csproj_files.aspx每次我们创建一个新的 C# 项目时,Visual Studio 都会为我们放置 AssemblyInfo.cs 文件。该文件定义程序集元数据,如其版本、配置或生产者。
找到了使用 MSBuild 自动生成 AssemblyInfo.cs 的上述技术。将很快发布样品。
我不确定这是否适用于 CCNET,但我已经为 CodePlex 上的Build Version Increment项目创建了一个SVN 版本插件。该工具非常灵活,可以设置为使用 svn 修订版自动为您创建版本号。它不需要编写任何代码或编辑 xml,所以耶!
我希望这会有所帮助!
我的方法是使用前面提到的 ccnet 插件和一个 nant echo 任务来生成一个VersionInfo.cs
只包含版本属性的文件。我只需要将VersionInfo.cs
文件包含到构建中
echo 任务只是将我给它的字符串输出到一个文件中。
如果有类似的 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 不是很熟悉,所以我的脚本可能无法开箱即用,需要更正......
基于 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>
不知道我在哪里找到这个。但我在互联网上的“某处”找到了这个。
这会在构建发生之前更新所有 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 或更高版本后,上述操作可能会开始失败。
看:
这是解决方法。
<FileUpdate Files="@(AssemblyInfoFiles)"
Regex="AssemblyFileVersion\("(\d+)\.(\d+)\.(\d+)\.(\d+)"
ReplacementText="AssemblyFileVersion("$1.$2.$3.$(SubVersionRevision)" />
结果应该是:
在 Windows/资源管理器//文件/属性中……。
程序集版本将为 1.0.0.0。
如果 333 是 SVN 修订版,则文件版本将为 1.0.0.333。
当心。用于内部版本号的结构很短,因此您对修订可以达到多高有一个上限。
在我们的例子中,我们已经超过了限制。
如果您尝试输入内部版本号 99.99.99.599999,则文件版本属性实际上将显示为 99.99.99.10175。