团队开发中应用系统发布的版本管理尤为重要,任何修改到编译、发布会产生一个新版本。Team Foundation Server的Build process template基于Windows Workflow Foundation,我们需要通过一个CodeActivity在Initialize workspace后根据特定规则修改AssemblyInfo.cs并签入这个修改。一个有意义的版本号可以反馈给开发人员许多信息,通常我会如下定义版本信息:
[Major Version].[Minor Version].[Build Number].[Revision] => 2.0.4709.9353
Major Version:主版本号
Minor Version:次版本号
Build Number:当天减去2000年1月1日的天数
Revision:TFS上针对该项目的最新修订号
首先下载http://tfsbuildextensions.codeplex.com的TfsBuildExtensions,如何配置Build process template请参考http://tfsbuildextensions.codeplex.com/documentation下的How to integrate the AssemblyInfo build activity。需要注意在没有项目的情况下是无法拖动TfsBuildExtensions的Activity。
打开TFSBuildExtensions的解决方案,定位到Activities项目,打开Framework\AssemblyInfo\AssemblyInfo.cs,查看AssemblyInfo的UpdateVersion函数,它的默认实现无论代码是否进行修改都会递增,同时不会将修改后的AssemblyInfo.cs签入。我们期望的目标:
1、签出AssemblyInfo.cs。
2、比对修订集是否需要更新,自定义修改版本信息。
3、签入AssemblyInfo.cs,并标记变更来自于TFS Build。
具体修改如下:
1、添加CurrentWorkspace属性,来源变量Workspace。
/// <summary> /// 当前工作空间 /// </summary> [RequiredArgument] public InArgument<Workspace> CurrentWorkspace { get; set; }
2、定义TFS Build签入标识:
/// <summary> /// 前缀-团队编译 /// </summary> private const String PREFIX_TEAM_BUILD = "Team Build ";
3、修改UpdateVersion函数,如果当前修订号不等于上一次变更历史标识同时签入注释来源于非TFS Build则修改revision。
String projectDir = Path.GetDirectoryName(Path.GetDirectoryName(this.file.FullName)); Workspace currentWorkspace = this.CurrentWorkspace.Get(this.ActivityContext); Changeset changeset = currentWorkspace.VersionControlServer.QueryHistory(new ItemSpec(projectDir, RecursionType.Full)).FirstOrDefault(); Int32 revision = version.Revision; if ((version.Revision != changeset.ChangesetId) && !changeset.Comment.StartsWith(PREFIX_TEAM_BUILD, StringComparison.OrdinalIgnoreCase)) revision = changeset.ChangesetId;
4、修改UpdateVersion函数,build来自于固定天数。
version = new Version( Convert.ToInt32(this.ReplaceTokens(tokens[0], version.Major)), Convert.ToInt32(this.ReplaceTokens(tokens[1], version.Minor)), (DateTime.Now - new DateTime(2000, 1, 1)).Days, revision);
5、签出、签入AssemblyInfo.cs并标记来自于TFS Build的变更。
Workspace currentWorkspace = this.CurrentWorkspace.Get(this.ActivityContext); currentWorkspace.PendEdit(path); WorkspaceCheckInParameters checkinParameters = new WorkspaceCheckInParameters( new ItemSpec[] { new ItemSpec(path, RecursionType.None) }, String.Concat(PREFIX_TEAM_BUILD, version) ); currentWorkspace.CheckIn(checkinParameters);