Iva*_*van 12 .net versioning msbuild tfs wix
只是想知道.NET构建版本化的最佳方法是什么?
我用:
我想设置版本:
理想的版本号将允许跟踪已安装的软件回到确切的源代码.
就像是:
<Major>.<Minor>.<TFS_changeset_number>
Run Code Online (Sandbox Code Playgroud)
我希望在解决方案附近的版本控制中存储一些简单文本\ XML文件的前两部分版本,因为我相信它们应该共存.开发人员将手动更新此文件(例如,遵循语义版本控制方法).每个构建都将读取此版本文件,从调用CI工具获取3d版本的部分,并使用该版本更新所有必需的文件.
实现这个的最佳方法是什么?
我过去曾使用过几种方法:
1)执行此版本的NAnt\MsBuild包装器,然后调用MsBuild获取解决方案.它可以从CI工具(Jenkins\TeamCity\etc)调用.
问题 - 当我构建解决方案两次时,与TFS门控签入的集成很难看.
2)自定义TFS构建过程模板
问题 - 它不是那么简单,并导致一些合并工作TFS升级.此外,在门控签到中还不存在变更集编号,因此我们只能使用先前的变更集ID.
3)解决方案中的单独MsBuild项目,它仅执行此版本控制任务,并配置为首先在VS解决方案的项目构建顺序中运行.
问题 - 需要在所有其他项目(包括所有未来的项目)中引用这个元项目,这些项目感觉很难看
我知道不同的MsBuild和TFS扩展包可以简化更新.这个主题不是关于哪一个是最好的.问题是方法论而不是技术问题.
我还认为,如果微软在其标准TFS构建模板中包含版本控制功能,那将是理想的选择.其他CI工具已经具有此功能(AssemblyInfo修补程序).
更新11/09/2014
我决定明确表达符合敏捷\持续交付最佳实践的版本控制原则:
1)能够再现任何历史建筑
2)由于1)并且根据CD原则,所有内容(源代码,测试,应用程序配置,环境配置,构建\包\部署脚本等)都存储在版本控制下,因此具有分配给它的版本
3)版本号与其适用的源代码紧密存储在一起
4)人们可以根据他们的业务\营销逻辑更新版本
5)该版本只有一个主副本,用于自动构建\包装过程的所有部分
6)您可以轻松地说出目标系统上当前安装了哪个版本的软件
7)已安装软件的版本必须明确标识用于构建它的源代码
8)比较版本比较低,哪些更高,以控制允许哪些升级\降级方案及其实现细节是非常简单的
更新15/09/2014
请看下面我自己的答案.
我很幸运能找到满足我所有要求的解决方案!
好悲伤,所有那些复杂的答案.
在TFS 2013中,这很简单.该社区TFS创建扩展网站提供了一个简单的PowerShell拉从通过TFS分配构建名称内部版本号.
您将构建号格式配置为"$(BuildDefinitionName)_6.0.0 $(Rev:.r)",这将产生类似"6.0.0.1"的内容,其中"1"为每个构建增加.
然后,将PowerShell版本控制脚本添加到构建中,它会自动删除上面的版本号,并将其应用于构建文件夹中的所有AssemblyInfo.*文件.您可以通过更新脚本来添加其他文件类型.
我想出了一个满足我所有要求的解决方案,而且令人惊讶的是非常简单!
主意
将所有自定义版本控制工作放入自定义Version.proj MsBuild 脚本中,并在.sln之前的 TFS 构建定义中调用它。该脚本将 Version 注入源代码(SharedAssemblyInfo.cs、Wix 代码、readme.txt),然后解决方案构建会构建该源代码。
版本由存储在 TFS 中的Version.xml文件中的 Major 和 Minor 数字以及源代码组成;以及由父 TFS 构建过程作为TF_BUILD_SOURCEGETVERSION env var 提供的变更集编号
感谢微软为此:
因此不需要使用任何MsBuild或TFS社区\扩展包\插件\任何东西。并且无需修改标准TFS构建过程模板。简单的解决方案带来高可维护性!
执行
版本.proj
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!--
Run this script for every build in CI tool before building the main solution
If you build in TFS, simply add script as the first item in a list of projects under Process tab > Build > Projects
-->
<PropertyGroup>
<VersionFile>..\Version.xml</VersionFile>
<MainProjectDir>... set this to main solution directory ...</MainProjectDir>
</PropertyGroup>
<Import Project="$(VersionFile)"/>
<Import Project="Common.proj"/>
<Target Name="GetMajorMinorNumbers">
<Error Text="ERROR: MajorVersion is not set in $(VersionFile)" Condition="'$(MajorVersion)' == ''" />
<Message Text="MajorVersion: $(MajorVersion)" />
<Error Text="ERROR: MinorVersion is not set in $(VersionFile)" Condition="'$(MinorVersion)' == ''" />
<Message Text="MinorVersion: $(MinorVersion)" />
</Target>
<Target Name="GetChangesetNumber">
<Error Text="ERROR: env var TF_BUILD_SOURCEGETVERSION is not set, see http://msdn.microsoft.com/en-us/library/hh850448.aspx" Condition="'$(TF_BUILD_SOURCEGETVERSION)' == ''" />
<Message Text="TF_BUILD_SOURCEGETVERSION: $(TF_BUILD_SOURCEGETVERSION)" />
</Target>
<Target Name="FormFullVersion">
<PropertyGroup>
<FullVersion>$(MajorVersion).$(MinorVersion).$(TF_BUILD_SOURCEGETVERSION.Substring(1))</FullVersion>
</PropertyGroup>
<Message Text="FullVersion: $(FullVersion)" />
</Target>
<Target Name="UpdateVersionInFilesByRegex">
<ItemGroup>
<!-- could have simplified regex as Assembly(File)?Version to include both items, but this can update only one of them if another is not found and operation will still finish successfully which is bad -->
<FilesToUpdate Include="$(MainProjectDir)\**\AssemblyInfo.cs">
<Regex>(?<=\[assembly:\s*Assembly?Version\(["'])(\d+\.){2,3}\d+(?=["']\)\])</Regex>
<Replacement>$(FullVersion)</Replacement>
</FilesToUpdate>
<FilesToUpdate Include="$(MainProjectDir)\**\AssemblyInfo.cs">
<Regex>(?<=\[assembly:\s*AssemblyFileVersion\(["'])(\d+\.){2,3}\d+(?=["']\)\])</Regex>
<Replacement>$(FullVersion)</Replacement>
</FilesToUpdate>
<FilesToUpdate Include="CommonProperties.wxi">
<Regex>(?<=<\?define\s+ProductVersion\s*=\s*['"])(\d+\.){2,3}\d+(?=["']\s*\?>)</Regex>
<Replacement>$(FullVersion)</Replacement>
</FilesToUpdate>
</ItemGroup>
<Exec Command="attrib -r %(FilesToUpdate.Identity)" />
<Message Text="Updating version in %(FilesToUpdate.Identity)" />
<RegexReplace Path="%(FilesToUpdate.Identity)" Regex="%(Regex)" Replacement="%(Replacement)"/>
</Target>
<Target Name="WriteReadmeFile">
<Error Text="ERROR: env var TF_BUILD_BINARIESDIRECTORY is not set, see http://msdn.microsoft.com/en-us/library/hh850448.aspx" Condition="'$(TF_BUILD_BINARIESDIRECTORY)' == ''" />
<WriteLinesToFile
File="$(TF_BUILD_BINARIESDIRECTORY)\readme.txt"
Lines="This is version $(FullVersion)"
Overwrite="true"
Encoding="Unicode"/>
</Target>
<Target Name="Build">
<CallTarget Targets="GetMajorMinorNumbers" />
<CallTarget Targets="GetChangesetNumber" />
<CallTarget Targets="FormFullVersion" />
<CallTarget Targets="UpdateVersionInFilesByRegex" />
<CallTarget Targets="WriteReadmeFile" />
</Target>
</Project>
Run Code Online (Sandbox Code Playgroud)
通用项目
<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' ToolsVersion="12.0">
<!-- based on example from http://msdn.microsoft.com/en-us/library/dd722601.aspx -->
<UsingTask TaskName="RegexReplace" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll">
<ParameterGroup>
<Path ParameterType="System.String" Required="true" />
<Regex ParameterType="System.String" Required="true" />
<Replacement ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Reference Include="System.Core" />
<Using Namespace="System" />
<Using Namespace="System.IO" />
<Using Namespace="System.Text.RegularExpressions" />
<Code Type="Fragment" Language="cs"><![CDATA[
string content = File.ReadAllText(Path);
if (! System.Text.RegularExpressions.Regex.IsMatch(content, Regex)) {
Log.LogError("ERROR: file does not match pattern");
}
content = System.Text.RegularExpressions.Regex.Replace(content, Regex, Replacement);
File.WriteAllText(Path, content);
return !Log.HasLoggedErrors;
]]></Code>
</Task>
</UsingTask>
<Target Name='Demo' >
<RegexReplace Path="C:\Project\Target.config" Regex="$MyRegex$" Replacement="MyValue"/>
</Target>
</Project>
Run Code Online (Sandbox Code Playgroud)
版本.xml
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MajorVersion>1</MajorVersion>
<MinorVersion>1</MinorVersion>
</PropertyGroup>
</Project>
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
12325 次 |
最近记录: |