Msbuild 单个TFS 2010构建定义能否用于多个分支?
我负责我们产品的构建,并被要求提出一种定制现有构建定义的方法,以便在需要时构建不同的分支 此产品的生成过程已经有多个自定义步骤和操作,并且该产品有大量已生成的项目文件,因此为创建的每个新分支设置新的生成定义是无效的 生成定义设置为从主分支生成。其目的是输入一个特定的分支(使用一个工作流参数,该参数可以在生成排队时输入),然后生成该分支而不是默认的主分支,而无需编辑生成定义 我有一个单独的测试程序,用于测试所有自定义构建活动和过程。在这个构建定义的工作流中,我添加了一些用于日志记录的构建消息,以便可以查看构建过程中使用的变量的值 我还基于这个测试程序创建了一个分支,用于测试可用于构建多个分支的构建定义 首先,我从原始分支为原始测试解决方案的项目文件运行了一个构建,然后更改了构建定义,以便使用新分支执行同样的操作,然后运行另一个构建。当比较这两个分支之间的构建日志时,它们之间只有一些细微的差异。(日志详细度设置为诊断) 第一个区别-我查看了一个工作区变量,构建的Folders属性引用了它们各自的分支,特别是Folders属性的ServerItem属性 第二个区别-正在生成的项目文件(BuildSettings.ProjectsToBuild)来自各自的分支 除此之外,我没有看到这两个构建日志之间的任何其他差异 这里的主要问题是: 是否有一种标准方法可以将正在生成的分支交换为单个生成定义 如果没有,在对生成进行排队时,是否可以将自定义工作流模板(在Workspace and BuildSettings.ProjectsToBuild中)中对默认主分支的所有引用都更改为输入的分支 一如既往,提前感谢您提供的所有帮助简言之:否和是:-) 在这些答案的基础上,TFS系统默认模板更倾向于为要构建的每个分支使用一个构建定义,或者指定需要一次性构建的所有分支,但要使用一个构建定义。在“队列新建”对话框中,没有标准方法从可用分支中进行选择 下一个答案是肯定的,因为您确实可以自定义构建模板,我知道您已经开始这样做了。根据您的分支结构,向模板中添加一个属性(显示在“队列新建”对话框中)应该相当容易,并具有一个(例如)半列分隔字符串,其中包含您希望在运行期间生成的所有分支,对于该列表中的每个元素,在模板实际开始迭代该列表之前,在工作流过程中添加要构建的解决方案Msbuild 单个TFS 2010构建定义能否用于多个分支?,msbuild,build,Msbuild,Build,我负责我们产品的构建,并被要求提出一种定制现有构建定义的方法,以便在需要时构建不同的分支 此产品的生成过程已经有多个自定义步骤和操作,并且该产品有大量已生成的项目文件,因此为创建的每个新分支设置新的生成定义是无效的 生成定义设置为从主分支生成。其目的是输入一个特定的分支(使用一个工作流参数,该参数可以在生成排队时输入),然后生成该分支而不是默认的主分支,而无需编辑生成定义 我有一个单独的测试程序,用于测试所有自定义构建活动和过程。在这个构建定义的工作流中,我添加了一些用于日志记录的构建消息,以便
这应该可以完成工作,但是,我很感兴趣的是,你最终是如何想要这种能力的?您没有使用VS解决方案文件吗?我已设法修改了生成的工作流模板,以便可以为解决方案的多个分支生成。为了实现这一点,我必须更改工作流中的某些内容,并为运行构建的服务帐户创建一些额外的工作区
在我的工作流程中,我还涉及到一些其他的事情,但它们是我的开发人员要求的更多的调整,上面的步骤导致了单个构建定义的多个分支构建 我还希望在我的构建定义中有更多的分支灵活性,因此我实现了一个代码活动来更改ProjectsToBuild(如上面的害虫步骤5)。以下是代码(删除了特定于项目的内容):
[BuildActivity(HostenEnvironmentOption.All)]
公共密封类转换项目根据牧场:代码活动
{
公共静态字符串s_MainBranch=“$/MyTeamProject/Main”;
公共InArgument BuildDetail{get;set;}
公共InArgument BuildingSettingsOriginal{get;set;}
public OutArgument BuildingSettings转换为{get;set;}
受保护的覆盖无效执行(CodeActivityContext上下文)
{
Logger.Instance.Init(上下文);
IBuildDetail buildDetail=buildDetail.Get(上下文);
BuildSettingsConverted.Set(上下文,ConvertProject(BuildSettingsOriginal.Get(上下文),buildDetail.BuildDefinition));
}
///返回一个BuildSettings,其中ProjectsToBuild根据生成定义的工作区进行转换
P
[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;
}
}