可以将单个TFS 2010构建定义用于多个分支吗?

时间:2011-10-06 07:40:58

标签: msbuild build tfs2010

我负责管理我们产品的构建,并且已经被要求提出一种定制现有构建定义的方法,以便在需要时构建不同的分支。

此产品的构建过程已经有多个自定义步骤和操作,并且产品中包含大量项目文件,因此无法为每个创建的新分支设置新的构建定义。

构建定义设置为从Main分支构建。目的是输入一个特定的分支(使用可以在构建排队时输入的工作流参数),然后构建它而不是默认的Main分支,而不必编辑构建定义。

我有一个单独的测试程序,用于测试我的所有自定义构建活动和过程。在此构建定义的工作流程中,我添加了一些用于记录目的的构建消息,以便我可以查看构建过程中使用的变量值。

我还基于这个测试程序创建了一个分支,准备测试可用于构建多个分支的构建定义

首先,我从原始分支运行原始测试解决方案的项目文件的构建,然后更改构建定义,以便使用新分支完成相同的操作并运行另一个构建。比较两个分支之间的构建日志时,它们之间只有一些细微差别。 (记录详细程度设置为诊断)

第一个区别 - 我查看了Workspace变量,构建的Folders属性引用了它们各自的分支,特别是Folders属性的ServerItem属性

第二个区别 - 正在构建的项目文件(BuildSettings.ProjectsToBuild)来自各自的分支

除了这些

之外,我没有看到2个构建日志之间的任何其他差异

这里的主要问题

是否存在交换为单个构建定义构建的分支的标准方法?

如果没有,是否可以在排队构建时将自定义工作流模板中的默认主分支(在Workspace和BuildSettings.ProjectsToBuild中)的所有引用更改为输入的分支?

与往常一样,提前感谢任何和所有帮助

4 个答案:

答案 0 :(得分:4)

我已经设法修改了我的构建工作流模板,以便可以为解决方案的多个分支构建。为了实现这一点,我必须更改工作流中的某些内容,并为运行构建的服务帐户创建一些额外的工作区。

  1. 我在工作流程中添加了一个参数,以便在构建排队时输入所需的分支。

  2. 我更改了构建的放置位置,使其与输入的分支相关(可选)

  3. 在构建计算机上为分支构建

  4. 创建了一个单独的sources目录
  5. 初始化WorkspaceName和SourcesDirectory,使它们与新工作区名称和源目录文件夹匹配

  6. 我创建了一个自定义活动来更改BuildSettings.ProjectsToBuild中的项目/解决方案列表,以便他们从输入的分支中引用它们

  7. 我在测试阶段注意到,即使我输入分支的新工作区最初设置为使用输入的分支作为其ServerItem,它仍然会创建具有在构建中输入的ServerItem的工作区定义。为了解决这个问题,我创建了另一个自定义活动来重新映射分支工作区,以便ServerItem指向正确的分支

  8. 我的工作流程中还涉及其他一些内容,但它们是我的开发人员要求的更多调整,上述步骤导致了单个构建定义的多个分支构建。

答案 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解决方案文件吗?