我负责管理我们产品的构建,并且已经被要求提出一种定制现有构建定义的方法,以便在需要时构建不同的分支。
此产品的构建过程已经有多个自定义步骤和操作,并且产品中包含大量项目文件,因此无法为每个创建的新分支设置新的构建定义。
构建定义设置为从Main分支构建。目的是输入一个特定的分支(使用可以在构建排队时输入的工作流参数),然后构建它而不是默认的Main分支,而不必编辑构建定义。
我有一个单独的测试程序,用于测试我的所有自定义构建活动和过程。在此构建定义的工作流程中,我添加了一些用于记录目的的构建消息,以便我可以查看构建过程中使用的变量值。
我还基于这个测试程序创建了一个分支,准备测试可用于构建多个分支的构建定义
首先,我从原始分支运行原始测试解决方案的项目文件的构建,然后更改构建定义,以便使用新分支完成相同的操作并运行另一个构建。比较两个分支之间的构建日志时,它们之间只有一些细微差别。 (记录详细程度设置为诊断)
第一个区别 - 我查看了Workspace变量,构建的Folders属性引用了它们各自的分支,特别是Folders属性的ServerItem属性
第二个区别 - 正在构建的项目文件(BuildSettings.ProjectsToBuild)来自各自的分支
除了这些
之外,我没有看到2个构建日志之间的任何其他差异这里的主要问题:
是否存在交换为单个构建定义构建的分支的标准方法?
如果没有,是否可以在排队构建时将自定义工作流模板中的默认主分支(在Workspace和BuildSettings.ProjectsToBuild中)的所有引用更改为输入的分支?
与往常一样,提前感谢任何和所有帮助
答案 0 :(得分:4)
我已经设法修改了我的构建工作流模板,以便可以为解决方案的多个分支构建。为了实现这一点,我必须更改工作流中的某些内容,并为运行构建的服务帐户创建一些额外的工作区。
我在工作流程中添加了一个参数,以便在构建排队时输入所需的分支。
我更改了构建的放置位置,使其与输入的分支相关(可选)
在构建计算机上为分支构建
初始化WorkspaceName和SourcesDirectory,使它们与新工作区名称和源目录文件夹匹配
我创建了一个自定义活动来更改BuildSettings.ProjectsToBuild中的项目/解决方案列表,以便他们从输入的分支中引用它们
我在测试阶段注意到,即使我输入分支的新工作区最初设置为使用输入的分支作为其ServerItem,它仍然会创建具有在构建中输入的ServerItem的工作区定义。为了解决这个问题,我创建了另一个自定义活动来重新映射分支工作区,以便ServerItem指向正确的分支
我的工作流程中还涉及其他一些内容,但它们是我的开发人员要求的更多调整,上述步骤导致了单个构建定义的多个分支构建。
答案 1 :(得分:1)
我还希望在我的构建定义中有更多的分支敏捷性,所以我实现了一个代码活动来更改ProjectsToBuild(就像上面的Vermin的第5步)。这是代码(删除了项目特定的东西):
[BuildActivity(HostEnvironmentOption.All)]
public sealed class ConvertProjectsAccordingToBranch : CodeActivity
{
public static string s_MainBranch = "$/MyTeamProject/Main";
public InArgument<IBuildDetail> BuildDetail { get; set; }
public InArgument<BuildSettings> BuildSettingsOriginal { get; set; }
public OutArgument<BuildSettings> BuildSettingsConverted { get; set; }
protected override void Execute(CodeActivityContext context)
{
Logger.Instance.Init(context);
IBuildDetail buildDetail = BuildDetail.Get(context);
BuildSettingsConverted.Set(context, ConvertProjects(BuildSettingsOriginal.Get(context), buildDetail.BuildDefinition));
}
/// <summary>Returns a BuildSettings with ProjectsToBuild converted according to the build definition's workspace</summary>
public BuildSettings ConvertProjects(BuildSettings settingsOriginal, IBuildDefinition buildDefinition)
{
var mappings = buildDefinition.Workspace.Mappings;
if (mappings.Count() != 1)
{
throw new BuildProcessException(string.Format(CultureInfo.InvariantCulture,
"Build definition must have exactly one workspace mapping. Build definition ID:{0} has {1} mappings",
buildDefinition.Id, // IBuildDefinition doesn't have any Name property, seriously!
mappings.Count()));
}
string definitionBranch = mappings.First().ServerItem;
var settingsConverted = new BuildSettings()
{
PlatformConfigurations = settingsOriginal.PlatformConfigurations,
};
foreach (string projectOriginal in settingsOriginal.ProjectsToBuild)
{
var projectConverted = projectOriginal.Replace(s_MainBranch, definitionBranch);
if (!projectConverted.StartsWith(definitionBranch))
{
throw new BuildProcessException(string.Format(CultureInfo.InvariantCulture,
"Project {0} is not under main branch {1}, Definition branch: {2}",
projectOriginal, s_MainBranch, definitionBranch));
}
settingsConverted.ProjectsToBuild.Add(projectConverted);
Logger.Instance.Log("Converted ProjectToBuild: {0}, original: {1}", projectConverted, projectOriginal);
}
return settingsConverted;
}
}
我也有ConvertProjects()
的单元测试,但它依赖于本地的东西,所以我没有在这里发布。这是微不足道的,绝对值得写作!
答案 2 :(得分:1)
我知道这已经很老了,但是如果有人发现这个帖子的话。
我们有相同的要求:能够构建一个功能分支,以便在合并到开发之前提供用于测试的特定功能的构建。
我们就是这样做的:
创建了一组Visual Studio扩展程序:
创建分支构建将克隆用作模板的构建定义。根据分支更改构建定义名称和工作空间。构建定义将在团队资源管理器(VS2012)中可见。
启动分支构建将找到构建定义并启动构建。
删除分支将找到构建定义,删除所有构建,删除构建定义,并删除分支(清理)。构建和分支的生命周期很短,因此清理它们非常重要。
答案 3 :(得分:0)
简而言之:否和是: - )
对这些答案进行更详细的说明,TFS系统默认模板更喜欢为您要构建的每个分支都有一个构建定义,或者指定需要在onces上构建的所有分支,但是在单个构建定义中。没有标准的方法可以从队列新版本对话框中的可用分支中进行选择。
下一个答案是肯定的,因为您确实可以自定义构建模板,我知道您已经开始这样做了。根据您的分支结构,在Queue新构建对话框中向模板添加属性应该相当容易,并且有一个(例如)半列分隔字符串,其中包含您希望在运行期间构建的所有分支,对于该列表中的每个元素,在模板实际开始迭代该列表之前,添加一个在工作流程过程中构建的解决方案。
那应该做的工作,但是,我对你最终想要这种能力感兴趣吗?你没有使用VS解决方案文件吗?